Skip to content

Commit

Permalink
Replace renderers w/ components, remove HTML parser from core (#563)
Browse files Browse the repository at this point in the history
* Replace `renderers` w/ `components`
* Replace `allowNode` w/ `allowElement`, which is now given a hast element (as
  the first parameter)
* Replace `allowedTypes` w/ `allowedElements`
* Replace `disallowedTypes` w/ `disallowedElements`
* Change signature of `linkTarget` and `transformLinkUri`, which are now given
  hast children (as the second parameter)
* Change signature of `transformImageUri`, which is now given the `alt` string
  as the second parameter (instead of the fourth)
* Replace `plugins` w/ `remarkPlugins` (backwards compatible change)
* Add `rehypePlugins`
* Change `includeNodeIndex` to `includeElementIndex`: it still sets an `index`,
  but that value now represents the number of preceding elements, it also sets a
  `siblingCount` (instead of `parentChildCount`) with the number of sibling
  elements in the parent
* The `columnAlignment` prop is no longer given to table elements: it’s
  available as `style` on `th` and `td` elements instead
* The `spread` prop is no longer given to list elements: it’s already handled

Remove buggy HTML parsers from core

* If you want HTML, add [`rehype-raw`](https://github.com/rehypejs/rehype-raw)
  to `rehypePlugins` and it’ll work without bugs!
* Remove `allowDangerousHtml` (previously called `escapeHtml`) option: pass
  `rehype-raw` in `rehypePlugins` to allow HTML instead
* Remove `with-html.js`, `plugins/html-parser.js` entries from library
* Remove naïve HTML parser too: either use `rehype-raw` to properly support
  HTML, or don’t allow it at all

Closes GH-549.
Closes GH-563.

The following issues are solved as rehype is now available:

Closes GH-522.
Closes GH-465.
Closes GH-427.
Closes GH-384.
Closes GH-356.

The following issues are solved as a proper HTML parser (`rehype-raw`) is now
available:

Closes GH-562.
Closes GH-460.
Closes GH-454.
Closes GH-452.
Closes GH-433.
Closes GH-386.
Closes GH-385.
Closes GH-345.
Closes GH-320.
Closes GH-302.
Closes GH-267.
Closes GH-259.

The following issues are solved as docs are improved:

Closes GH-251.
  • Loading branch information
wooorm committed Apr 12, 2021
1 parent 683515f commit 77c680f
Show file tree
Hide file tree
Showing 21 changed files with 1,799 additions and 1,782 deletions.
69 changes: 32 additions & 37 deletions index.d.ts
@@ -1,9 +1,9 @@
// TypeScript Version: 3.4

import {ElementType, ReactNode, ReactElement} from 'react'
import {ElementType, ReactElement} from 'react'
import {PluggableList} from 'unified'
import * as unist from 'unist'
import * as mdast from 'mdast'
import * as hast from 'hast'

type Not<T> = {
[key in keyof T]?: never
Expand All @@ -16,65 +16,60 @@ declare namespace ReactMarkdown {

type Position = unist.Position

type NodeType = mdast.Content['type']
type LinkTargetResolver = (
href: string,
children: Array<hast.Element | hast.Comment | hast.Text>,
title?: string
) => string

type AlignType = mdast.AlignType

type ReferenceType = mdast.ReferenceType

type LinkTargetResolver = (uri: string, text: string, title?: string) => string

type Renderer<T> = (props: T) => ElementType<T>
interface Renderers {
[key: string]: string | Renderer<any>
type Component<T> = (props: T) => ElementType<T>
interface Components {
[key: string]: string | Component<any>
}

interface ReactMarkdownPropsBase {
readonly className?: string
readonly skipHtml?: boolean
readonly sourcePos?: boolean
readonly includeNodeIndex?: boolean
readonly includeElementIndex?: boolean
readonly rawSourcePos?: boolean
readonly allowNode?: (node: mdast.Content, index: number, parent: NodeType) => boolean
readonly allowElement?: (
node: hast.Element,
index: number,
parent: hast.Element | hast.Root
) => boolean
readonly linkTarget?: string | LinkTargetResolver
readonly transformLinkUri?:
| ((uri: string, children?: ReactNode, title?: string) => string)
| null
readonly transformImageUri?:
| ((uri: string, children?: ReactNode, title?: string, alt?: string) => string)
| ((
href: string,
children: Array<hast.Element | hast.Comment | hast.Text>,
title?: string
) => string)
| null
readonly renderers?: {[nodeType: string]: ElementType}
readonly plugins?: PluggableList
readonly transformImageUri?: ((src: string, alt: string, title?: string) => string) | null
readonly components?: {[tagName: string]: ElementType}
readonly remarkPlugins?: PluggableList
readonly rehypePlugins?: PluggableList
readonly unwrapDisallowed?: boolean
}

interface ChildrenProp {
readonly children: string
}

interface AllowedTypesProp {
readonly allowedTypes?: NodeType[]
interface AllowedElementsProp {
readonly allowedElements?: string[]
}

interface DisallowedTypesProp {
readonly disallowedTypes: NodeType[]
}

interface AllowDangerousHtmlProp {
readonly allowDangerousHtml?: boolean
}

interface SkipHtmlProp {
readonly skipHtml?: boolean
interface DisallowedElementsProp {
readonly disallowedElements: string[]
}

type ReactMarkdownProps = ReactMarkdownPropsBase &
ChildrenProp &
MutuallyExclusive<AllowedTypesProp, DisallowedTypesProp> &
MutuallyExclusive<SkipHtmlProp, AllowDangerousHtmlProp>
MutuallyExclusive<AllowedElementsProp, DisallowedElementsProp>

const types: NodeType[]
const renderers: Renderers
function uriTransformer(uri: string): string
function uriTransformer(url: string): string
}

declare function ReactMarkdown(props: ReactMarkdown.ReactMarkdownProps): ReactElement
Expand Down
26 changes: 17 additions & 9 deletions package.json
Expand Up @@ -74,19 +74,21 @@
"lib/",
"plugins/",
"index.d.ts",
"react-markdown.min.js",
"with-html.d.ts",
"with-html.js"
"react-markdown.min.js"
],
"dependencies": {
"@types/mdast": "^3.0.3",
"@types/hast": "^2.0.0",
"@types/unist": "^2.0.3",
"html-to-react": "^1.4.5",
"mdast-add-list-metadata": "1.0.1",
"comma-separated-tokens": "^1.0.0",
"prop-types": "^15.7.2",
"property-information": "^5.0.0",
"react-is": "^17.0.0",
"remark-parse": "^9.0.0",
"remark-rehype": "^8.0.0",
"space-separated-tokens": "^1.1.0",
"style-to-object": "^0.3.0",
"unified": "^9.0.0",
"unist-util-is": "^4.1.0",
"unist-util-visit": "^2.0.0"
},
"peerDependencies": {
Expand Down Expand Up @@ -121,6 +123,7 @@
"react": "^17.0.0",
"react-dom": "^17.0.0",
"react-test-renderer": "^17.0.0",
"rehype-raw": "^5.0.0",
"remark-cli": "^9.0.0",
"remark-gfm": "^1.0.0",
"remark-math": "^4.0.0",
Expand Down Expand Up @@ -199,19 +202,24 @@
"overrides": [
{
"files": [
"src/**/*.js",
"with-html.js"
"src/**/*.js"
],
"extends": [
"plugin:es/restrict-to-es2015"
]
},
{
"env": {
"jest": true
},
"files": [
"test/**/*.js"
],
"rules": {
"react/no-children-prop": 0
"react/no-children-prop": 0,
"react/display-name": 0,
"no-nested-ternary": 0,
"react/prop-types": 0
}
}
]
Expand Down
1 change: 0 additions & 1 deletion plugins/html-parser.js

This file was deleted.

22 changes: 6 additions & 16 deletions react-markdown-types-test.tsx
@@ -1,43 +1,33 @@
import * as React from 'react'
import * as ReactDom from 'react-dom'
import * as ReactMarkdown from 'react-markdown'
import * as ReactMarkdownWitHtml from 'react-markdown/with-html'

/* must have children */
let test = <ReactMarkdown># header</ReactMarkdown>
test = <ReactMarkdown children="# header" />
// $ExpectError
test = <ReactMarkdown />

/* should support allowedTypes or disallowedTypes, but not both */
test = <ReactMarkdown allowedTypes={['heading']}># header</ReactMarkdown>
test = <ReactMarkdown disallowedTypes={['heading']}># header</ReactMarkdown>
/* should support allowedElements or disallowedElements, but not both */
test = <ReactMarkdown allowedElements={['h1']}># header</ReactMarkdown>
test = <ReactMarkdown disallowedElements={['h1']}># header</ReactMarkdown>
test = (
<ReactMarkdown disallowedTypes={['heading']} unwrapDisallowed>
<ReactMarkdown disallowedElements={['h1']} unwrapDisallowed>
# header
</ReactMarkdown>
)
test = (
<ReactMarkdown allowedTypes={['heading']} unwrapDisallowed>
<ReactMarkdown allowedElements={['h1']} unwrapDisallowed>
# header
</ReactMarkdown>
)
test = (
// $ExpectError
<ReactMarkdown allowedTypes={['heading']} disallowedTypes={['heading']}>
<ReactMarkdown allowedElements={['h1']} disallowedElements={['h1']}>
# header
</ReactMarkdown>
)

/* should support skipHtml or allowDangerousHtml, but not both */
test = <ReactMarkdown skipHtml># header</ReactMarkdown>
test = <ReactMarkdown allowDangerousHtml># header</ReactMarkdown>
test = (
// $ExpectError
<ReactMarkdown skipHtml allowDangerousHtml>
# header
</ReactMarkdown>
)

ReactDom.render(<ReactMarkdown># header</ReactMarkdown>, document.body)
ReactDom.render(<ReactMarkdownWitHtml># header</ReactMarkdownWitHtml>, document.body)

0 comments on commit 77c680f

Please sign in to comment.