Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 45 additions & 32 deletions src/lib/remark-callouts.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,47 +4,60 @@ import { visit } from "unist-util-visit"
* Remark plugin to transform directive nodes (:::tip, :::note, etc.) into styled callout boxes
*/
export function remarkCallouts() {
const knownTypes = {
note: {
containerClass: "callout callout-note",
icon: "ℹ️",
title: "Note",
},
tip: {
containerClass: "callout callout-tip",
icon: "💡",
title: "Tip",
},
warning: {
containerClass: "callout callout-warning",
icon: "⚠️",
title: "Warning",
},
danger: {
containerClass: "callout callout-danger",
icon: "🚨",
title: "Danger",
},
info: {
containerClass: "callout callout-info",
icon: "ℹ️",
title: "Info",
},
}

return (tree) => {
visit(tree, (node) => {
visit(tree, (node, index, parent) => {
if (
node.type === "containerDirective" ||
node.type === "leafDirective" ||
node.type === "textDirective"
) {
const data = node.data || (node.data = {})
const hast = data.hDirectiveLabel || {}
const type = node.name
const style = knownTypes[node.name]

// Map directive types to styles
const styles = {
note: {
containerClass: "callout callout-note",
icon: "ℹ️",
title: "Note",
},
tip: {
containerClass: "callout callout-tip",
icon: "💡",
title: "Tip",
},
warning: {
containerClass: "callout callout-warning",
icon: "⚠️",
title: "Warning",
},
danger: {
containerClass: "callout callout-danger",
icon: "🚨",
title: "Danger",
},
info: {
containerClass: "callout callout-info",
icon: "ℹ️",
title: "Info",
},
// Restore text/leaf directives that remark-directive parsed from
// normal content (e.g. `:00` from `[0:00](url)`, `::after` in CSS discussion)
if (node.type === "textDirective" || node.type === "leafDirective") {
const prefix = node.type === "textDirective" ? ":" : "::"
node.type = "text"
node.value = `${prefix}${node.name}`
delete node.data
delete node.name
delete node.attributes
delete node.children
return
}

const style = styles[type] || styles.note
if (!style) return

const data = node.data || (node.data = {})
const hast = data.hDirectiveLabel || {}

// Get the label from attributes or use default
const label =
Expand Down
Loading