1 import PropTypes from 'prop-types';
2 import React from 'react';
3 import { useNavigate } from 'react-router-dom';
5 import PngDialog from './PngDialog';
7 const isApng = el => el.nodeName === 'IMG' && el.getAttribute('type') === 'image/apng';
9 const isLink = el => el.nodeName === 'A';
11 const canClick = el => {
12 if (isLink(el)) return true;
13 if (isApng(el)) return true;
17 const RawHTML = ({ html }) => {
18 const navigate = useNavigate();
19 const [apng, setApng] = React.useState(null);
20 const [show, setShow] = React.useState(false);
21 const [title, setTitle] = React.useState(null);
23 const onClick = e => {
24 if (e.defaultPrevented) return;
25 if (e.metaKey || e.ctrlKey || e.shiftKey) return;
26 if (e.button !== 0) return;
29 while (el && !canClick(el)) {
35 if (el.target && el.target !== '_self') return;
36 if (el.attributes.download) return;
37 if (el.rel && /(?:^|\s+)external(?:\s+|$)/.test(el.rel)) return;
39 const href = el.getAttribute('href');
41 if (href.startsWith('#')) return;
42 if (href.startsWith('http')) return;
43 if (href.startsWith('mailto')) return;
44 if (href.startsWith('tel')) return;
50 // scroll to top on location change
51 scrollTo({ top: 0, behavior: 'smooth' });
59 setApng(el.getAttribute('src'));
61 setTitle(el.getAttribute('alt'));
66 <div className="raw-html" onClick={onClick} dangerouslySetInnerHTML={{ __html: html }} />
67 <PngDialog onHide={() => setShow(false)} show={show} src={apng} title={title} />
72 html: PropTypes.string,
75 export default RawHTML;