| <script lang="ts" context="module"> |
| import { marked, type Token } from 'marked'; |
|
|
| type AlertType = 'NOTE' | 'TIP' | 'IMPORTANT' | 'WARNING' | 'CAUTION'; |
|
|
| interface AlertTheme { |
| border: string; |
| text: string; |
| icon: ComponentType; |
| } |
|
|
| export interface AlertData { |
| type: AlertType; |
| text: string; |
| tokens: Token[]; |
| } |
|
|
| const alertStyles: Record<AlertType, AlertTheme> = { |
| NOTE: { |
| border: 'border-sky-500', |
| text: 'text-sky-500', |
| icon: Info |
| }, |
| TIP: { |
| border: 'border-emerald-500', |
| text: 'text-emerald-500', |
| icon: LightBlub |
| }, |
| IMPORTANT: { |
| border: 'border-purple-500', |
| text: 'text-purple-500', |
| icon: Star |
| }, |
| WARNING: { |
| border: 'border-yellow-500', |
| text: 'text-yellow-500', |
| icon: ArrowRightCircle |
| }, |
| CAUTION: { |
| border: 'border-rose-500', |
| text: 'text-rose-500', |
| icon: Bolt |
| } |
| }; |
|
|
| export function alertComponent(token: Token): AlertData | false { |
| const regExpStr = `^(?:\\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\\])\\s*?\n*`; |
| const regExp = new RegExp(regExpStr); |
| const matches = token.text?.match(regExp); |
|
|
| if (matches && matches.length) { |
| const alertType = matches[1] as AlertType; |
| const newText = token.text.replace(regExp, ''); |
| const newTokens = marked.lexer(newText); |
| return { |
| type: alertType, |
| text: newText, |
| tokens: newTokens |
| }; |
| } |
| return false; |
| } |
| </script> |
|
|
| <script lang="ts"> |
| import Info from '$lib/components/icons/Info.svelte'; |
| import Star from '$lib/components/icons/Star.svelte'; |
| import LightBlub from '$lib/components/icons/LightBlub.svelte'; |
| import Bolt from '$lib/components/icons/Bolt.svelte'; |
| import ArrowRightCircle from '$lib/components/icons/ArrowRightCircle.svelte'; |
| import MarkdownTokens from './MarkdownTokens.svelte'; |
| import type { ComponentType } from 'svelte'; |
| |
| export let token: Token; |
| export let alert: AlertData; |
| export let id = ''; |
| export let tokenIdx = 0; |
| export let onTaskClick: ((event: MouseEvent) => void) | undefined = undefined; |
| export let onSourceClick: ((event: MouseEvent) => void) | undefined = undefined; |
| </script> |
|
|
| <!-- |
|
|
| Renders the following Markdown as alerts: |
|
|
| > [!NOTE] |
| > Example note |
|
|
| > [!TIP] |
| > Example tip |
|
|
| > [!IMPORTANT] |
| > Example important |
|
|
| > [!CAUTION] |
| > Example caution |
|
|
| > [!WARNING] |
| > Example warning |
|
|
| --> |
| <div class={`border-l-4 pl-2.5 ${alertStyles[alert.type].border} my-0.5`}> |
| <div class="{alertStyles[alert.type].text} items-center flex gap-1 py-1.5"> |
| <svelte:component this={alertStyles[alert.type].icon} className="inline-block size-4" /> |
| <span class=" font-medium">{alert.type}</span> |
| </div> |
| <div class="pb-2"> |
| <MarkdownTokens id={`${id}-${tokenIdx}`} tokens={alert.tokens} {onTaskClick} {onSourceClick} /> |
| </div> |
| </div> |
|
|