UNPKG

@readme/markdown

Version:

ReadMe's React-based Markdown parser

76 lines (66 loc) 2.24 kB
const React = require('react'); const PropTypes = require('prop-types'); // Only load CodeMirror in the browser, for SSR // apps. Necessary because of people like this: // https://github.com/codemirror/CodeMirror/issues/3701#issuecomment-164904534 const syntaxHighlighter = typeof window !== 'undefined' ? require('@readme/syntax-highlighter') : false; const copy = require('copy-to-clipboard'); const remapLang = { c: 'cplusplus', 'c++': 'cplusplus', cpp: 'cplusplus', docker: 'dockerfile', html: 'htmlmixed', js: 'javascript', py: 'python', sh: 'shell', bash: 'shell', mysql: 'sql', }; function CopyCode({ code, rootClass = 'rdmd-code-copy', className = '' }) { const copyClass = `${rootClass}_copied`; const button = React.createRef(); /* istanbul ignore next */ const copier = () => { if (copy(code)) { const $el = button.current; $el.classList.add(copyClass); setTimeout(() => $el.classList.remove(copyClass), 1500); } }; return <button ref={button} className={`${rootClass} ${className}`} onClick={copier} />; } CopyCode.propTypes = { className: PropTypes.string, code: PropTypes.string, rootClass: PropTypes.string, }; function Code(props) { const { className, children, lang, meta } = props; const langClass = className.search(/lang(?:uage)?-\w+/) >= 0 ? className.match(/\s?lang(?:uage)?-(\w+)/)[1] : ''; const language = lang in remapLang ? remapLang[lang] : lang || langClass; return ( <React.Fragment> <code className={['rdmd-code', `lang-${language}`].join(' ')} data-lang={language} name={meta}> {!syntaxHighlighter || <CopyCode className="fa" code={children[0]} />} {syntaxHighlighter ? syntaxHighlighter(children[0], language, { tokenizeVariables: true }) : children[0]} </code> </React.Fragment> ); } Code.propTypes = { children: PropTypes.arrayOf(PropTypes.string).isRequired, className: PropTypes.string, lang: PropTypes.string, meta: PropTypes.string, }; Code.defaultProps = { className: '', lang: '', meta: '', }; module.exports = sanitizeSchema => { // This is for code blocks class name sanitizeSchema.attributes.code = ['className', 'lang', 'meta', 'value']; return Code; };