UNPKG

@readme/markdown

Version:

ReadMe's React-based Markdown parser

104 lines (85 loc) 2.55 kB
/* eslint-disable no-param-reassign, react/jsx-props-no-spreading, no-fallthrough */ const React = require('react'); const PropTypes = require('prop-types'); const Lightbox = require('./Lightbox'); class Image extends React.Component { constructor(props) { super(props); this.state = { lightbox: false, }; this.lightbox = React.createRef(); this.toggle = this.toggle.bind(this); this.handleKey = this.handleKey.bind(this); this.isEmoji = props.className === 'emoji'; } componentDidMount() { this.lightboxSetup(); } toggle(toState) { if (this.props.className === 'emoji') return; if (typeof toState === 'undefined') toState = !this.state.lightbox; if (toState) this.lightboxSetup(); this.setState({ lightbox: toState }); } lightboxSetup() { const $el = this.lightbox.current; setTimeout(() => { $el.scrollTop = ($el.scrollHeight - $el.offsetHeight) / 2; this.setState({ lightbox: true }); }, 0); } handleKey(e) { let { key, metaKey: cmd } = e; cmd = cmd ? 'cmd+' : ''; key = `${cmd}${key.toLowerCase()}`; switch (key) { case 'cmd+.': case 'escape': // CLOSE this.toggle(false); break; case ' ': case 'enter': // OPEN if (!this.state.open) this.toggle(true); e.preventDefault(); default: } } render() { const { alt } = this.props; if (this.isEmoji) { return <img {...this.props} alt={alt} loading="lazy" />; } return ( <span className="img" onClick={() => this.toggle()} onKeyDown={this.handleKey} role={'button'} tabIndex={0}> <img {...this.props} alt={alt} /> <Lightbox ref={this.lightbox} {...this.props} close={this.toggle} opened={this.state.lightbox} /> </span> ); } } Image.propTypes = { align: PropTypes.string, alt: PropTypes.string, caption: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]), className: PropTypes.oneOfType([PropTypes.string, PropTypes.array]), height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), src: PropTypes.string.isRequired, title: PropTypes.string, width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), }; Image.defaultProps = { align: '', alt: '', caption: '', height: 'auto', src: '', title: '', width: 'auto', }; module.exports = sanitizeSchema => { sanitizeSchema.attributes.img = ['className', 'title', 'alt', 'width', 'height', 'align', 'src', 'longDesc']; return Image; };