diff --git a/components/HTMLBlock/index.jsx b/components/HTMLBlock/index.jsx deleted file mode 100644 index 102a721f2..000000000 --- a/components/HTMLBlock/index.jsx +++ /dev/null @@ -1,69 +0,0 @@ -/* eslint-disable no-eval - */ -const escape = require('lodash.escape'); -const PropTypes = require('prop-types'); -const React = require('react'); - -const MATCH_SCRIPT_TAGS = /]*>([\s\S]*?)<\/script *>\n?/gim; - -const extractScripts = (html = '') => { - const scripts = []; - let match; - while ((match = MATCH_SCRIPT_TAGS.exec(html)) !== null) { - scripts.push(match[1]); - } - const cleaned = html.replace(MATCH_SCRIPT_TAGS, ''); - return [cleaned, () => scripts.map(js => window.eval(js))]; -}; - -class HTMLBlock extends React.PureComponent { - constructor(props) { - super(props); - [this.html, this.exec] = extractScripts(this.props.html); - } - - componentDidMount() { - const { runScripts } = this.props; - if (typeof window !== 'undefined' && (runScripts === '' || runScripts)) this.exec(); - } - - render() { - const { html, safeMode } = this.props; - - if (safeMode) { - return ( -
-          
-        
- ); - } - - return
; - } -} - -HTMLBlock.defaultProps = { - runScripts: false, - safeMode: false, -}; - -HTMLBlock.propTypes = { - html: PropTypes.string, - runScripts: PropTypes.any, - safeMode: PropTypes.bool, -}; - -const CreateHtmlBlock = - ({ safeMode }) => - // eslint-disable-next-line react/display-name - props => - ; - -CreateHtmlBlock.sanitize = schema => { - schema.tagNames.push('html-block'); - schema.attributes['html-block'] = ['html', 'runScripts']; - - return schema; -}; - -module.exports = CreateHtmlBlock; diff --git a/components/HTMLBlock/index.tsx b/components/HTMLBlock/index.tsx new file mode 100644 index 000000000..e3e9f88d9 --- /dev/null +++ b/components/HTMLBlock/index.tsx @@ -0,0 +1,36 @@ +import React, { useEffect } from 'react'; +import { renderToString, renderToStaticMarkup } from 'react-dom/server'; + +const MATCH_SCRIPT_TAGS = /]*>([\s\S]*?)<\/script *>\n?/gim; + +const extractScripts = (html: string = ''): [string, () => void] => { + const scripts: string[] = []; + let match: RegExpExecArray | null; + while ((match = MATCH_SCRIPT_TAGS.exec(html)) !== null) { + scripts.push(match[1]); + } + const cleaned = html.replace(MATCH_SCRIPT_TAGS, ''); + return [cleaned, () => scripts.map(js => window.eval(js))]; +}; + +const HTMLBlock = props => { + const { children, runScripts, safeMode = false } = props; + const html = renderToString(<>{children}); + const [cleanedHtml, exec] = extractScripts(html); + + useEffect(() => { + if (typeof window !== 'undefined' && typeof runScripts === 'boolean' && runScripts) exec(); + }, [runScripts, exec]); + + if (safeMode) { + return ( +
+        
+      
+ ); + } + + return
; +}; + +export default HTMLBlock; diff --git a/components/Image/index.tsx b/components/Image/index.tsx index 14faac973..61e654f1a 100644 --- a/components/Image/index.tsx +++ b/components/Image/index.tsx @@ -1,21 +1,7 @@ import * as React from 'react'; -interface Props extends React.PropsWithChildren> { - align: string; - alt: string; - border: boolean; - caption: string; - className: string; - height: string; - lazy: boolean; - src: string; - title: string; - width: string; -} - -const Image = (props: Props) => { +const Image = props => { const [lightbox, setLightbox] = React.useState(false); - const { align = '', alt = '', @@ -23,10 +9,10 @@ const Image = (props: Props) => { caption, className = '', height = 'auto', - lazy, src = '', title = '', width = 'auto', + lazyImages: lazy = true, } = props; if (className === 'emoji') { diff --git a/docs/sanitizing-tests.md b/docs/sanitizing-tests.md index a646bcca3..4a48e5b69 100644 --- a/docs/sanitizing-tests.md +++ b/docs/sanitizing-tests.md @@ -1,22 +1,7 @@ -## Sanitizing `style` tags - - - - -## Sanitizing `style` attributes - -

fish content

- - ## Sanitizing html blocks -[block:html] -{ - "html": "" -} -[/block] + +

Header

+

hello there

+
\ No newline at end of file diff --git a/enums.ts b/enums.ts index aa398912f..a8e849ef0 100644 --- a/enums.ts +++ b/enums.ts @@ -3,4 +3,5 @@ export enum NodeTypes { emoji = 'emoji', i = 'i', image = 'image', + htmlBlock = 'html-block', } diff --git a/index.tsx b/index.tsx index faa9f9c9d..75d47bcb6 100644 --- a/index.tsx +++ b/index.tsx @@ -48,6 +48,7 @@ const makeUseMDXComponents = (more: RunOpts['components']) => { ...Components, Variable, 'code-tabs': Components.CodeTabs, + 'html-block': Components.HTMLBlock, img: Components.Image, }; diff --git a/processor/compile/html-block.js b/processor/compile/html-block.js deleted file mode 100644 index 64e393e3c..000000000 --- a/processor/compile/html-block.js +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = function () { - const { Compiler } = this; - const { visitors } = Compiler.prototype; - - visitors['html-block'] = node => { - const html = node.data.hProperties.html; - return `[block:html]\n${JSON.stringify({ html }, null, 2)}\n[/block]`; - }; -}; diff --git a/processor/compile/html-block.ts b/processor/compile/html-block.ts new file mode 100644 index 000000000..e9f4db9a3 --- /dev/null +++ b/processor/compile/html-block.ts @@ -0,0 +1,8 @@ +import { HTMLBlock } from '../../types'; + +const htmlBlock = (node: HTMLBlock) => { + const html = node.data.hProperties.html; + return `${JSON.stringify({ html }, null, 2)}`; +} + +export default htmlBlock; diff --git a/processor/compile/index.ts b/processor/compile/index.ts index 9b2ea5e3e..95572d0ae 100644 --- a/processor/compile/index.ts +++ b/processor/compile/index.ts @@ -1,6 +1,7 @@ import gemoji from './gemoji'; import codeTabs from './code-tabs'; import image from './image'; +import htmlBlock from './html-block'; import { NodeTypes } from '../../enums'; const compilers = { @@ -8,6 +9,7 @@ const compilers = { [NodeTypes.emoji]: gemoji, [NodeTypes.codeTabs]: codeTabs, [NodeTypes.image]: image, + [NodeTypes.htmlBlock]: htmlBlock, }, }; diff --git a/types.d.ts b/types.d.ts index b760d402c..7f1524f7f 100644 --- a/types.d.ts +++ b/types.d.ts @@ -9,6 +9,16 @@ interface CodeTabs extends Parent { }; } +interface HTMLBlock extends Parent { + type: NodeTypes.htmlBlock; + data: Data & { + hName: 'html-block'; + hProperties: { + html: string; + }; + }; +} + interface Gemoji extends Literal { type: NodeTypes.emoji; name: string;