FIX Render callout blocks correctly (#277)

This commit is contained in:
Guy Sartorelli 2023-10-19 10:09:13 +13:00 committed by GitHub
parent 23b063cd6b
commit 52467ffc4e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 16 additions and 18 deletions

View File

@ -5,9 +5,16 @@
* @returns * @returns
*/ */
const cleanCalloutTags = (html: string): string => { const cleanCalloutTags = (html: string): string => {
// Replace callout <p> tags with a <callout> tag so we can swap it out with the right react component
html = html.replace(
/<p>\s*\[(hint|warning|info|alert|notice|note)\](.*?)\[\/\1\]\s*<\/p>/gs,
(_, type, content) => `<callout type="${type}">${content}</callout>`
);
// Replace any <p> and </p> tags inside callout tags with <br>, since the above operation may have
// inadvertantly broken some <p> tags.
return html.replace( return html.replace(
/(?:<p>\s*)((?:\[(hint|warning|info|alert|notice|note)\]).*?(?:\[\/(hint|warning|info|alert|notice|note)\]))(?:\s*<\/p>)/gs, /<callout type="[a-z]*">.*?<\/callout>/gs,
(_, callout) => callout (callout) => callout.replace(/(<p>|<\/p>)/g, '<br>')
); );
}; };

View File

@ -5,19 +5,8 @@ import CalloutBlock from '../components/CalloutBlock';
* Turn [hint] and other callouts into a proper React component. * Turn [hint] and other callouts into a proper React component.
* @param data * @param data
*/ */
const parseCalloutTags = (data: any): ReactElement|false => { const parseCalloutTags = (type: string, content: any): ReactElement|false => {
let matches; return createElement(CalloutBlock, { type, content });
matches = data.match(/\[(hint|warning|info|alert|notice|note)\](.*?)\[\/(?:hint|warning|info|alert|notice|note)\]/s);
if (matches) {
const type = matches[1];
const content = matches[2];
return createElement(CalloutBlock, { type, content });
}
return false;
}; };
export default parseCalloutTags; export default parseCalloutTags;

View File

@ -1,4 +1,4 @@
import parse, { DomElement } from 'html-react-parser'; import parse, { DomElement, domToReact } from 'html-react-parser';
import cleanChildrenTags from './cleanChildrenTags'; import cleanChildrenTags from './cleanChildrenTags';
import cleanWhitespace from './cleanWhitespace'; import cleanWhitespace from './cleanWhitespace';
import cleanApiTags from './cleanApiTags'; import cleanApiTags from './cleanApiTags';
@ -12,7 +12,7 @@ import cleanHeaders from './cleanHeaders';
import parseCalloutTags from './parseCalloutTags'; import parseCalloutTags from './parseCalloutTags';
/** /**
* Replace all the [CHILDREN] with proper React components. * Replace all the [CHILDREN] and callout tags with proper React components.
* @param html * @param html
* @return ReactElement | ReactElement[] | string * @return ReactElement | ReactElement[] | string
*/ */
@ -38,13 +38,15 @@ const parseHTML = (html: string): ReactElement | ReactElement[] | string => {
if (name.match(/^h[0-9]$/)) { if (name.match(/^h[0-9]$/)) {
return rewriteHeader(domNode); return rewriteHeader(domNode);
} }
if (name === 'callout') {
return parseCalloutTags(domNode.attribs.type, domToReact(domNode.children));
}
} }
if (domNode.data && domNode.parent?.name !== 'code') { if (domNode.data && domNode.parent?.name !== 'code') {
const { data } = domNode; const { data } = domNode;
if (data.match(/\[CHILDREN.*?\]/)) { if (data.match(/\[CHILDREN.*?\]/)) {
return parseChildrenOf(data); return parseChildrenOf(data);
} }
return parseCalloutTags(data);
} }
return false; return false;