| | |
| | |
| | |
| |
|
| | import { visit } from 'unist-util-visit' |
| | import { h } from 'hastscript' |
| | import octicons from '@primer/octicons' |
| | import type { Element } from 'hast' |
| |
|
| | interface AlertType { |
| | icon: string |
| | color: string |
| | } |
| |
|
| | const alertTypes: Record<string, AlertType> = { |
| | NOTE: { icon: 'info', color: 'accent' }, |
| | IMPORTANT: { icon: 'report', color: 'done' }, |
| | WARNING: { icon: 'alert', color: 'attention' }, |
| | TIP: { icon: 'light-bulb', color: 'success' }, |
| | CAUTION: { icon: 'stop', color: 'danger' }, |
| | } |
| |
|
| | |
| | const ALERT_REGEXP = new RegExp(`\\[!(${Object.keys(alertTypes).join('|')})\\]`, 'gi') |
| |
|
| | |
| | const matcher = (node: any): boolean => |
| | node.type === 'element' && |
| | node.tagName === 'blockquote' && |
| | ALERT_REGEXP.test(JSON.stringify(node.children)) |
| |
|
| | export default function alerts({ alertTitles = {} }: { alertTitles?: Record<string, string> }) { |
| | |
| | return (tree: any) => { |
| | |
| | visit(tree, matcher, (node: any) => { |
| | const key = getAlertKey(node) |
| | if (!(key in alertTypes)) { |
| | console.warn( |
| | `Alert key '${key}' should be all uppercase (change it to '${key.toUpperCase()}')`, |
| | ) |
| | } |
| | const alertType = alertTypes[getAlertKey(node).toUpperCase()] |
| | node.tagName = 'div' |
| | node.properties.className = `ghd-alert ghd-alert-${alertType.color}` |
| | node.properties.dataContainer = 'alert' |
| | node.children = [ |
| | h( |
| | 'p', |
| | { className: 'ghd-alert-title' }, |
| | getOcticonSVG(alertType.icon), |
| | alertTitles[key] || '', |
| | ), |
| | ...removeAlertSyntax(node.children), |
| | ] |
| | }) |
| | } |
| | } |
| |
|
| | function getAlertKey(node: Element): string { |
| | const body = JSON.stringify(node.children) |
| | const matches = body.match(ALERT_REGEXP) |
| | return matches![0].slice(2, -1) |
| | } |
| |
|
| | |
| | function removeAlertSyntax(node: any): any { |
| | if (Array.isArray(node)) { |
| | return node.map(removeAlertSyntax) |
| | } |
| | if (node.children) { |
| | node.children = node.children.map(removeAlertSyntax) |
| | } |
| | if (node.value) { |
| | node.value = node.value.replace(ALERT_REGEXP, '') |
| | } |
| | return node |
| | } |
| |
|
| | function getOcticonSVG(name: string): Element { |
| | return h( |
| | 'svg', |
| | { |
| | version: '1.1', |
| | width: 16, |
| | height: 16, |
| | viewBox: '0 0 16 16', |
| | className: 'octicon mr-2', |
| | ariaHidden: true, |
| | }, |
| | h('path', { d: octicons[name].heights[16].path.match(/d="(.*)"/)![1] }), |
| | ) |
| | } |
| |
|