mirror of
https://github.com/silverstripe/doc.silverstripe.org
synced 2024-10-22 15:05:50 +00:00
ENH Render the new callout block style (#284)
This commit is contained in:
parent
52467ffc4e
commit
fc34b760c0
@ -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;
|
@ -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;
|
||||||
|
@ -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;
|
|
@ -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') {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user