ENH Render the new callout block style (#284)

This commit is contained in:
Guy Sartorelli 2024-02-02 09:41:43 +13:00 committed by GitHub
parent 52467ffc4e
commit fc34b760c0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 31 additions and 31 deletions

View File

@ -4,16 +4,17 @@ import { CalloutBlockProps } from '../types';
const getCalloutClass = (type: string): string => { const getCalloutClass = (type: string): string => {
switch (type) { switch (type) {
case 'hint': case 'TIP':
return 'success'; return 'success';
case 'notice': case 'IMPORTANT':
case 'WARNING':
return 'warning'; return 'warning';
case 'alert': case 'CAUTION':
return 'danger'; return 'danger';
case 'note': case 'NOTE':
return 'info' return 'info'
default: default:
return type; return 'info';
} }
}; };
@ -23,7 +24,6 @@ const CalloutBlock: StatelessComponent<CalloutBlockProps> = ({ type, content })
<div className="content">{content}</div> <div className="content">{content}</div>
</div> </div>
); );
}; };
export default CalloutBlock; export default CalloutBlock;

View File

@ -283,6 +283,10 @@
.callout-title { .callout-title {
font-size: 1rem; font-size: 1rem;
} }
.content p:last-of-type {
margin-bottom: 0;
}
&.callout-block-info { &.callout-block-info {
border-color: $theme-info-color; border-color: $theme-info-color;

View File

@ -1,21 +0,0 @@
/**
* Removes the paragraph tags from around callout blocks so they end up being valid HTML
*
* @param html
* @returns
*/
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(
/<callout type="[a-z]*">.*?<\/callout>/gs,
(callout) => callout.replace(/(<p>|<\/p>)/g, '<br>')
);
};
export default cleanCalloutTags;

View File

@ -4,7 +4,6 @@ import cleanWhitespace from './cleanWhitespace';
import cleanApiTags from './cleanApiTags'; import cleanApiTags from './cleanApiTags';
import rewriteLink from './rewriteLink'; import rewriteLink from './rewriteLink';
import parseChildrenOf from './parseChildrenOf'; import parseChildrenOf from './parseChildrenOf';
import cleanCalloutTags from './cleanCalloutTags';
import { ReactElement } from 'react'; import { ReactElement } from 'react';
import rewriteTable from './rewriteTable'; import rewriteTable from './rewriteTable';
import rewriteHeader from './rewriteHeader'; import rewriteHeader from './rewriteHeader';
@ -19,7 +18,6 @@ import parseCalloutTags from './parseCalloutTags';
const parseHTML = (html: string): ReactElement | ReactElement[] | string => { const parseHTML = (html: string): ReactElement | ReactElement[] | string => {
let cleanHTML = html; let cleanHTML = html;
cleanHTML = cleanChildrenTags(cleanHTML); cleanHTML = cleanChildrenTags(cleanHTML);
cleanHTML = cleanCalloutTags(cleanHTML);
cleanHTML = cleanWhitespace(cleanHTML); cleanHTML = cleanWhitespace(cleanHTML);
cleanHTML = cleanApiTags(cleanHTML); cleanHTML = cleanApiTags(cleanHTML);
cleanHTML = cleanHeaders(cleanHTML); cleanHTML = cleanHeaders(cleanHTML);
@ -38,8 +36,27 @@ 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') { if (name === 'blockquote') {
return parseCalloutTags(domNode.attribs.type, domToReact(domNode.children)); for (const child of children) {
// For some reason blockquotes start with an empty new line with this parser.
if (child.type === 'text' && child.data === "\n") {
continue;
}
// If the first relevant child isn't a paragraph or is empty, it's not a callout block.
if (child.type !== 'tag' || child.name !== 'p' || !child.children?.length || child.children[0].type !== 'text') {
break;
}
// Check if the first text node marks this as a callout block
const firstTextNode = child.children[0];
const calloutTypeRegex = /^\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\]\n/;
const matches = firstTextNode.data.match(calloutTypeRegex);
if (!matches) {
break;
}
// Remove the type marker and render the component
firstTextNode.data = firstTextNode.data.replace(calloutTypeRegex, '');
return parseCalloutTags(matches[1], domToReact(children));
}
} }
} }
if (domNode.data && domNode.parent?.name !== 'code') { if (domNode.data && domNode.parent?.name !== 'code') {