import React from 'react';
import { useNavigate } from 'react-router-dom';
+import PngDialog from './PngDialog';
+
+const isApng = el => el.nodeName === 'IMG' && el.getAttribute('type') === 'image/apng';
+
+const isLink = el => el.nodeName === 'A';
+
+const canClick = el => {
+ if (isLink(el)) return true;
+ if (isApng(el)) return true;
+ return false;
+};
+
const RawHTML = ({ html }) => {
const navigate = useNavigate();
+ const [apng, setApng] = React.useState(null);
+ const [show, setShow] = React.useState(false);
+ const [title, setTitle] = React.useState(null);
const onClick = e => {
if (e.defaultPrevented) return;
if (e.button !== 0) return;
let el = e.target;
- while (el && el.nodeName !== 'A') {
+ while (el && !canClick(el)) {
el = el.parentNode;
}
if (!el) return;
- if (el.target && el.target !== '_self') return;
- if (el.attributes.download) return;
- if (el.rel && /(?:^|\s+)external(?:\s+|$)/.test(el.rel)) return;
+ if (isLink(el)) {
+ if (el.target && el.target !== '_self') return;
+ if (el.attributes.download) return;
+ if (el.rel && /(?:^|\s+)external(?:\s+|$)/.test(el.rel)) return;
+
+ const href = el.getAttribute('href');
- const href = el.getAttribute('href');
+ if (href.startsWith('#')) return;
+ if (href.startsWith('http')) return;
+ if (href.startsWith('mailto')) return;
+ if (href.startsWith('tel')) return;
- if (href.startsWith('#')) return;
- if (href.startsWith('http')) return;
- if (href.startsWith('mailto')) return;
- if (href.startsWith('tel')) return;
+ el.blur();
+ e.preventDefault();
- el.blur();
- e.preventDefault();
+ setTimeout(() => {
+ // scroll to top on location change
+ scrollTo({ top: 0, behavior: 'smooth' });
+ }, 50);
- setTimeout(() => {
- // scroll to top on location change
- scrollTo({ top: 0, behavior: 'smooth' });
- }, 50);
+ navigate(href);
+ return;
+ }
- navigate(href);
+ if (isApng(el)) {
+ setApng(el.getAttribute('src'));
+ setShow(true);
+ setTitle(el.getAttribute('alt'));
+ }
};
- return <div onClick={onClick} dangerouslySetInnerHTML={{ __html: html }} />;
+ return <>
+ <div className="raw-html" onClick={onClick} dangerouslySetInnerHTML={{ __html: html }} />
+ <PngDialog onHide={() => setShow(false)} show={show} src={apng} title={title} />
+ </>;
};
RawHTML.propTypes = {