@fsegurai/marked-extended-alert 15.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,199 @@
1
+ <p align="center">
2
+ <img alt="Marked Extensions Logo" src="https://raw.githubusercontent.com/fsegurai/marked-extensions/main/demo/public/marked-extensions.svg">
3
+ </p>
4
+
5
+ <p align="center">
6
+ <a href="https://github.com/fsegurai/marked-extensions/actions/workflows/release-library.yml">
7
+ <img src="https://github.com/fsegurai/marked-extensions/actions/workflows/release-library.yml/badge.svg"
8
+ alt="Build Status">
9
+ </a>
10
+ <a href="https://www.npmjs.org/package/@fsegurai/marked-extended-alert">
11
+ <img src="https://img.shields.io/npm/v/@fsegurai/marked-extended-alert.svg"
12
+ alt="Latest Release">
13
+ </a>
14
+ <br>
15
+ <img alt="GitHub contributors" src="https://img.shields.io/github/contributors/fsegurai/marked-extensions">
16
+ <img alt="Dependency status for repo" src="https://img.shields.io/librariesio/github/fsegurai/marked-extensions">
17
+ <a href="https://opensource.org/licenses/MIT">
18
+ <img alt="GitHub License" src="https://img.shields.io/github/license/fsegurai/marked-extensions">
19
+ </a>
20
+ <br>
21
+ <img alt="Stars" src="https://img.shields.io/github/stars/fsegurai/marked-extensions?style=square&labelColor=343b41"/>
22
+ <img alt="Forks" src="https://img.shields.io/github/forks/fsegurai/marked-extensions?style=square&labelColor=343b41"/>
23
+ </p>
24
+
25
+ **A library of extended alert blocks for Marked.js.**
26
+
27
+ `@fsegurai/marked-extended-alert` is an extension for Marked.js that adds support for GitHub-style alert blocks, allowing you to create visually distinct note, warning, tip, and other information boxes in your Markdown content. It supports any markdown rendering within alerts and is highly customizable to fit your needs.
28
+
29
+ ### Table of contents
30
+
31
+ - [Installation](#installation)
32
+ - [Usage](#usage)
33
+ - [Basic Usage](#basic-usage)
34
+ - [Configuration Options](#configuration-options)
35
+ - [Available Alert Types](#available-alert-types)
36
+ - [More Resources](#more-resources)
37
+ - [Available Extensions](#available-extensions)
38
+ - [Demo Application](#demo-application)
39
+ - [License](#license)
40
+
41
+ ## Installation
42
+
43
+ To add `@fsegurai/marked-extended-alert` along with Marked.js to your `package.json` use the following commands.
44
+
45
+ ```bash
46
+ bun install @fsegurai/marked-extended-alert marked@^15.0.0 --save
47
+ ```
48
+
49
+ ## Usage
50
+
51
+ ### Basic Usage
52
+
53
+ Import `@fsegurai/marked-extended-alert` and apply it to your Marked instance as shown below.
54
+
55
+ ````javascript
56
+ import { marked } from "marked";
57
+ import markedExtendedAlert from "@fsegurai/marked-extended-alert";
58
+
59
+ // or UMD script
60
+ // <script src="https://cdn.jsdelivr.net/npm/marked/lib/marked.umd.js"></script>
61
+ // <script src="https://cdn.jsdelivr.net/npm/@fsegurai/marked-extended-alert/lib/index.umd.js"></script>
62
+
63
+ // Basic usage
64
+ marked.use(markedExtendedAlert());
65
+
66
+ const exampleMarkdown = `
67
+ > [!NOTE]
68
+ > This is a note alert with a **bold text** and a [link](https://example.com).
69
+ > - Item 1
70
+ > - Item 2
71
+
72
+ > [!WARNING]
73
+ > This is a warning alert.
74
+
75
+ > [!TIP]
76
+ > This is a tip alert.
77
+
78
+ > [!NOTE]
79
+ > This alert contains a table:
80
+ >
81
+ > | Header 1 | Header 2 |
82
+ > |----------|----------|
83
+ > | Cell 1 | Cell 2 |
84
+ > | Cell 3 | Cell 4 |
85
+ `;
86
+
87
+ marked.parse(exampleMarkdown);
88
+
89
+
90
+ ```javascript
91
+ import { marked } from "marked";
92
+ import markedExtendedAlert from "@fsegurai/marked-extended-alert";
93
+
94
+ // Configure with custom options
95
+ marked.use(
96
+ markedExtendedAlert({
97
+ className: 'custom-alert',
98
+ variants: [
99
+ {
100
+ type: 'success',
101
+ icon: '<svg class="custom-icon"></svg>',
102
+ title: 'Success!',
103
+ }
104
+ ],
105
+ injectStyles: true
106
+ })j
107
+ );
108
+
109
+ const customMarkdown = \`
110
+ > [!SUCCESS]
111
+ > This is a custom success alert with nested markdown:
112
+ > - Item with **bold text**
113
+ > - Another item with \`code\`
114
+ \`;
115
+
116
+ const result = marked.parse(customMarkdown);
117
+ ````
118
+
119
+ ### Configuration Options
120
+
121
+ The marked-extended-alert extension accepts the following configuration options:
122
+
123
+ - `className`: The base CSS class name for alerts. Defaults to 'markdown-alert'.
124
+ - `variants`: Array of custom variants to override or extend the default ones. The structure should look like this:
125
+ ```javascript
126
+ {
127
+ type: 'success',
128
+ icon: '<svg class="custom-icon"></svg>',
129
+ title: 'Success!',
130
+ }
131
+ ```
132
+ - `injectStyles`: Whether to automatically inject CSS styles. Defaults to true.
133
+
134
+ ### Available Alert Types
135
+
136
+ - `NOTE`: A note alert, typically used for additional information or tips.
137
+
138
+ ```markdown
139
+ > [!NOTE]
140
+ > This is a note alert.
141
+ ```
142
+
143
+ - `TIP`: A tip alert, often used for helpful hints or suggestions.
144
+
145
+ ```markdown
146
+ > [!TIP]
147
+ > This is a tip alert.
148
+ ```
149
+
150
+ - `IMPORTANT`: An important alert, used for critical information that requires attention.
151
+
152
+ ```markdown
153
+ > [!IMPORTANT]
154
+ > This is an important alert.
155
+ ```
156
+
157
+ - `WARNING`: A warning alert, indicating potential issues or caution.
158
+
159
+ ```markdown
160
+ > [!WARNING]
161
+ > This is a warning alert.
162
+ ```
163
+
164
+ - `CAUTION`: A caution alert, similar to a warning but with a different emphasis.
165
+
166
+ ```markdown
167
+ > [!CAUTION]
168
+ > This is a caution alert.
169
+ ```
170
+
171
+ ### Available Extensions
172
+
173
+ - [Marked Extended Accordion](https://www.npmjs.com/package/@fsegurai/marked-extended-accordion)
174
+ - [Marked Extended Alert](https://www.npmjs.com/package/@fsegurai/marked-extended-alert)
175
+ - [Marked Extended Footnote](https://www.npmjs.com/package/@fsegurai/marked-extended-footnote)
176
+ - [Marked Extended Lists](https://www.npmjs.com/package/@fsegurai/marked-extended-lists)
177
+ - [Marked Extended Spoiler](https://www.npmjs.com/package/@fsegurai/marked-extended-spoiler)
178
+ - [Marked Extended Tables](https://www.npmjs.com/package/@fsegurai/marked-extended-tables)
179
+ - [Marked Extended Tabs](https://www.npmjs.com/package/@fsegurai/marked-extended-tabs)
180
+ - [Marked Extended Timeline](https://www.npmjs.com/package/@fsegurai/marked-extended-timeline)
181
+ - [Marked Extended Typographic](https://www.npmjs.com/package/@fsegurai/marked-extended-typographic)
182
+
183
+ ### Demo Application
184
+
185
+ To see all extensions in action, check out the [[DEMO]](https://fsegurai.github.io/marked-extensions).
186
+
187
+ To set up the demo locally, follow the next steps:
188
+
189
+ ```bash
190
+ git clone https://github.com/fsegurai/marked-extensions.git
191
+ bun install
192
+ bun start
193
+ ```
194
+
195
+ This will serve the application locally at [http://[::1]:8000](http://[::1]:8000).
196
+
197
+ ## License
198
+
199
+ Licensed under [MIT](https://opensource.org/licenses/MIT).
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@fsegurai/marked-extended-alert",
3
+ "version": "15.0.0",
4
+ "description": "Extended Alerts for Marked.js",
5
+ "main": "./dist/index.cjs",
6
+ "module": "./src/index.js",
7
+ "browser": "./dist/index.umd.js",
8
+ "type": "module",
9
+ "types": "./src/index.d.ts",
10
+ "files": [
11
+ "lib/",
12
+ "src/"
13
+ ],
14
+ "exports": {
15
+ ".": {
16
+ "import": "./src/index.js",
17
+ "require": "./lib/index.cjs"
18
+ }
19
+ },
20
+ "keywords": [
21
+ "parser",
22
+ "markedjs",
23
+ "extension",
24
+ "marked",
25
+ "marked-extended-accordion",
26
+ "marked-extended-alert",
27
+ "marked-extended-footnote",
28
+ "marked-extended-lists",
29
+ "marked-extended-spoiler",
30
+ "marked-extended-tables",
31
+ "marked-extended-tabs",
32
+ "marked-extended-timeline",
33
+ "marked-extended-typographic"
34
+ ],
35
+ "author": {
36
+ "name": "Fabián Segura",
37
+ "url": "https://www.fsegurai.com/"
38
+ },
39
+ "license": "MIT",
40
+ "scripts": {
41
+ "prepare": "rollup -c rollup.config.js",
42
+ "test:types": "tsd -f spec/index.test-d.ts -t src/index.d.ts"
43
+ },
44
+ "peerDependencies": {
45
+ "marked": ">=13 <16"
46
+ },
47
+ "repository": {
48
+ "type": "git",
49
+ "url": "git+https://github.com/fsegurai/marked-extensions.git"
50
+ },
51
+ "bugs": {
52
+ "url": "https://github.com/fsegurai/marked-extensions/issues"
53
+ },
54
+ "homepage": "https://github.com/fsegurai/marked-extensions#readme"
55
+ }
@@ -0,0 +1,125 @@
1
+ 'use strict';
2
+
3
+ export const DEFAULT_OPTIONS = {
4
+ className: 'markdown-alert',
5
+ variants: [],
6
+ injectStyles: true,
7
+ };
8
+
9
+ /**
10
+ * The default configuration for alert variants.
11
+ */
12
+ export const DEFAULT_VARIANTS = [
13
+ {
14
+ type: 'note',
15
+ icon: '<svg class="octicon octicon-info mr-2" viewBox="0 0 16 16" width="16" height="16" aria-hidden="true"><path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path></svg>',
16
+ },
17
+ {
18
+ type: 'tip',
19
+ icon: '<svg class="octicon octicon-light-bulb mr-2" viewBox="0 0 16 16" width="16" height="16" aria-hidden="true"><path d="M8 1.5c-2.363 0-4 1.69-4 3.75 0 .984.424 1.625.984 2.304l.214.253c.223.264.47.556.673.848.284.411.537.896.621 1.49a.75.75 0 0 1-1.484.211c-.04-.282-.163-.547-.37-.847a8.456 8.456 0 0 0-.542-.68c-.084-.1-.173-.205-.268-.32C3.201 7.75 2.5 6.766 2.5 5.25 2.5 2.31 4.863 0 8 0s5.5 2.31 5.5 5.25c0 1.516-.701 2.5-1.328 3.259-.095.115-.184.22-.268.319-.207.245-.383.453-.541.681-.208.3-.33.565-.37.847a.751.751 0 0 1-1.485-.212c.084-.593.337-1.078.621-1.489.203-.292.45-.584.673-.848.075-.088.147-.173.213-.253.561-.679.985-1.32.985-2.304 0-2.06-1.637-3.75-4-3.75ZM5.75 12h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1 0-1.5ZM6 15.25a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 1 0 1.5h-2.5a.75.75 0 0 1-.75-.75Z"></path></svg>',
20
+ },
21
+ {
22
+ type: 'important',
23
+ icon: '<svg class="octicon octicon-report mr-2" viewBox="0 0 16 16" width="16" height="16" aria-hidden="true"><path d="M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v9.5A1.75 1.75 0 0 1 14.25 13H8.06l-2.573 2.573A1.458 1.458 0 0 1 3 14.543V13H1.75A1.75 1.75 0 0 1 0 11.25Zm1.75-.25a.25.25 0 0 0-.25.25v9.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h6.5a.25.25 0 0 0 .25-.25v-9.5a.25.25 0 0 0-.25-.25Zm7 2.25v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 9a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path></svg>',
24
+ },
25
+ {
26
+ type: 'warning',
27
+ icon: '<svg class="octicon octicon-alert mr-2" viewBox="0 0 16 16" width="16" height="16" aria-hidden="true"><path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path></svg>',
28
+ },
29
+ {
30
+ type: 'caution',
31
+ icon: '<svg class="octicon octicon-stop mr-2" viewBox="0 0 16 16" width="16" height="16" aria-hidden="true"><path d="M4.47.22A.749.749 0 0 1 5 0h6c.199 0 .389.079.53.22l4.25 4.25c.141.14.22.331.22.53v6a.749.749 0 0 1-.22.53l-4.25 4.25A.749.749 0 0 1 11 16H5a.749.749 0 0 1-.53-.22L.22 11.53A.749.749 0 0 1 0 11V5c0-.199.079-.389.22-.53Zm.84 1.28L1.5 5.31v5.38l3.81 3.81h5.38l3.81-3.81V5.31L10.69 1.5ZM8 4a.75.75 0 0 1 .75.75v3.5a.75.75 0 0 1-1.5 0v-3.5A.75.75 0 0 1 8 4Zm0 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path></svg>',
32
+ },
33
+ ];
34
+
35
+ /**
36
+ * Default CSS styles for alerts
37
+ */
38
+ export const DEFAULT_STYLES = `
39
+ .markdown-alert {
40
+ padding: 0 1em;
41
+ margin-bottom: 16px;
42
+ color: inherit;
43
+ border-left: 0.25em solid #444c56;
44
+ }
45
+
46
+ .markdown-alert-title {
47
+ display: inline-flex;
48
+ align-items: center;
49
+ font-weight: 500;
50
+ }
51
+
52
+ .markdown-alert-note {
53
+ border-left-color: #539bf5;
54
+
55
+ & > .markdown-alert-title {
56
+ color: #539bf5;
57
+
58
+ & svg {
59
+ fill: #539bf5;
60
+ }
61
+ }
62
+ }
63
+
64
+ .markdown-alert-tip {
65
+ border-left-color: #57ab5a;
66
+
67
+ & > .markdown-alert-title {
68
+ color: #57ab5a;
69
+
70
+ & svg {
71
+ fill: #57ab5a;
72
+ }
73
+ }
74
+ }
75
+
76
+ .markdown-alert-important {
77
+ border-left-color: #986ee2;
78
+
79
+ & > .markdown-alert-title {
80
+ color: #986ee2;
81
+
82
+ & svg {
83
+ fill: #986ee2;
84
+ }
85
+ }
86
+ }
87
+
88
+ .markdown-alert-warning {
89
+ border-left-color: #c69026;
90
+
91
+ & > .markdown-alert-title {
92
+ color: #c69026;
93
+
94
+ & svg {
95
+ fill: #c69026;
96
+ }
97
+ }
98
+ }
99
+
100
+ .markdown-alert-caution {
101
+ border-left-color: #e5534b;
102
+
103
+ & > .markdown-alert-title {
104
+ color: #e5534b;
105
+
106
+ & svg {
107
+ fill: #e5534b;
108
+ }
109
+ }
110
+ }
111
+
112
+ .mr-2 {
113
+ margin-right: 0.5rem;
114
+ }
115
+ `;
116
+
117
+ /**
118
+ * Default template for rendering alerts
119
+ */
120
+ export const DEFAULT_TEMPLATE = `
121
+ <div class="{className} {className}-{variant}">
122
+ <p class="{titleClassName}">{icon}{title}</p>
123
+ <div class="{className}-content">{content}</div>
124
+ </div>
125
+ `;
package/src/helper.js ADDED
@@ -0,0 +1,15 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Returns regex pattern to match alert syntax.
5
+ */
6
+ export function createSyntaxPattern(type) {
7
+ return `^(?:\\[!${type.toUpperCase()}])\\s*?\n*`;
8
+ }
9
+
10
+ /**
11
+ * Capitalizes the first letter of a string.
12
+ */
13
+ export function ucfirst(str) {
14
+ return str.slice(0, 1).toUpperCase() + str.slice(1).toLowerCase();
15
+ }
package/src/index.d.ts ADDED
@@ -0,0 +1,39 @@
1
+ import { MarkedExtension } from 'marked';
2
+
3
+ interface AlertVariant {
4
+ type: string;
5
+ icon?: string;
6
+ title?: string;
7
+ titleClassName?: string;
8
+ cssClass?: string;
9
+ }
10
+
11
+ /**
12
+ * Options for customizing alerts
13
+ */
14
+ export interface AlertOptions {
15
+ /**
16
+ * Base class name for alerts
17
+ * @default 'markdown-alert'
18
+ */
19
+ className?: string;
20
+
21
+ /**
22
+ * Custom variants to override or extend defaults
23
+ * @default []
24
+ */
25
+ variants?: AlertVariant[];
26
+
27
+ /**
28
+ * Whether to automatically inject CSS styles
29
+ * @default true
30
+ */
31
+ injectStyles?: boolean;
32
+ }
33
+
34
+ /**
35
+ * Creates a Marked.js extension for rendering alert blocks
36
+ * @param options - Configuration options for the alert extension
37
+ * @returns A Marked.js extension object
38
+ */
39
+ export default function markedExtendedAlert(options?: AlertOptions): MarkedExtension;
package/src/index.js ADDED
@@ -0,0 +1,41 @@
1
+ 'use strict';
2
+
3
+ import { DEFAULT_OPTIONS } from './constants.js';
4
+ import { ensureStyles } from './styles.js';
5
+ import { processAlertToken } from './tokenizer.js';
6
+ import { renderAlert } from './renderer.js';
7
+
8
+ /**
9
+ * A [marked](https://marked.js.org/) extension to support [GFM alerts](https://github.com/orgs/community/discussions/16925).
10
+ * @param {Object} options - Configuration options
11
+ * @param {string} [options.className='markdown-alert'] - Base class name for alerts
12
+ * @param {Array} [options.variants=[]] - Custom variants to override or extend defaults
13
+ * @param {boolean} [options.injectStyles=true] - Whether to automatically inject CSS styles
14
+ * @returns {Object} Marked extension object
15
+ */
16
+ export default function markedExtendedAlert(options = {}) {
17
+ const config = { ...DEFAULT_OPTIONS, ...options };
18
+
19
+ // Resolve variants
20
+
21
+ // Inject styles if needed
22
+ if (config.injectStyles) ensureStyles();
23
+
24
+ return {
25
+ walkTokens(token) {
26
+ if (token.type !== 'blockquote') return;
27
+
28
+ // Process blockquote token for alerts
29
+ processAlertToken({ token, ...config });
30
+ },
31
+ extensions: [
32
+ {
33
+ name: 'alert',
34
+ level: 'block',
35
+ renderer({ meta, tokens = [] }) {
36
+ return renderAlert(meta, tokens, this.parser);
37
+ },
38
+ },
39
+ ],
40
+ };
41
+ }
@@ -0,0 +1,26 @@
1
+ 'use strict';
2
+
3
+ import { DEFAULT_TEMPLATE } from './constants';
4
+
5
+ /**
6
+ * Renders an alert with the given properties
7
+ * @param {Object} meta - Metadata for the alert
8
+ * @param {Array} tokens - Tokens to render within the alert
9
+ * @param {Object} parser - Parser to use for rendering content
10
+ * @returns {String} HTML representation of the alert
11
+ */
12
+ export function renderAlert(meta = {}, tokens = [], parser) {
13
+ if (!meta) return '';
14
+
15
+ const { className, variant, icon, title, titleClassName } = meta;
16
+
17
+ // Tokenize and then parse the content
18
+ const markedContent = tokens && tokens.length > 0 ? parser.parse(tokens) : '';
19
+
20
+ return DEFAULT_TEMPLATE.replace(/{className}/g, className)
21
+ .replace(/{variant}/g, variant)
22
+ .replace(/{titleClassName}/g, titleClassName)
23
+ .replace(/{icon}/g, icon)
24
+ .replace(/{title}/g, title)
25
+ .replace(/{content}/g, markedContent);
26
+ }
package/src/styles.js ADDED
@@ -0,0 +1,19 @@
1
+ /* eslint-disable no-undef */
2
+ 'use strict';
3
+
4
+ import { DEFAULT_STYLES } from './constants.js';
5
+
6
+ /**
7
+ * Adds CSS styles for alerts to the page head if they don't already exist
8
+ */
9
+ export function ensureStyles() {
10
+ if (typeof window === 'undefined') return;
11
+
12
+ if (!window.__alertStylesAdded) {
13
+ const styleEl = document.createElement('style');
14
+ styleEl.id = 'marked-extended-alert-styles';
15
+ styleEl.textContent = DEFAULT_STYLES;
16
+ document.head.appendChild(styleEl);
17
+ window.__alertStylesAdded = true;
18
+ }
19
+ }
@@ -0,0 +1,78 @@
1
+ 'use strict';
2
+
3
+ import { DEFAULT_VARIANTS } from './constants.js';
4
+ import { createSyntaxPattern, ucfirst } from './helper.js';
5
+
6
+ /**
7
+ * Process a blockquote token to check and convert it into an alert
8
+ * @param {Object} options - Configuration options
9
+ * @param {Object} options.token - The token to process
10
+ * @param {string} [options.className='markdown-alert'] - Base class name for alerts
11
+ * @param {Array} [options.variants=[]] - Custom variants to override or extend defaults
12
+ */
13
+ export function processAlertToken(options = {}) {
14
+ const { token, className, variants } = options;
15
+
16
+ const resolvedVariants = resolveVariants(variants);
17
+
18
+ const matchedVariant = resolvedVariants.find(({ type }) => new RegExp(createSyntaxPattern(type)).test(token.text));
19
+
20
+ if (!matchedVariant) return;
21
+
22
+ const {
23
+ type: variantType,
24
+ icon,
25
+ title = ucfirst(variantType),
26
+ titleClassName = `${className}-title`,
27
+ } = matchedVariant;
28
+
29
+ const typeRegexp = new RegExp(createSyntaxPattern(variantType));
30
+
31
+ // Transform the token into an alert token
32
+ Object.assign(token, {
33
+ type: 'alert',
34
+ meta: {
35
+ className,
36
+ variant: variantType,
37
+ icon,
38
+ title,
39
+ titleClassName,
40
+ },
41
+ });
42
+
43
+ // Clean up the first line to remove the alert marker
44
+ const firstLine = token.tokens?.[0];
45
+ const firstLineText = firstLine?.raw?.replace(typeRegexp, '').trim();
46
+
47
+ if (firstLineText) {
48
+ const patternToken = firstLine.tokens[0];
49
+
50
+ Object.assign(patternToken, {
51
+ raw: patternToken.raw.replace(typeRegexp, ''),
52
+ text: patternToken.text.replace(typeRegexp, ''),
53
+ });
54
+
55
+ if (firstLine.tokens[1]?.type === 'br') {
56
+ firstLine.tokens.splice(1, 1);
57
+ }
58
+ } else {
59
+ token.tokens?.shift();
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Resolves the variants configuration, combining the provided variants with
65
+ * the default variants.
66
+ * @param {Array} variants - Custom variants to merge with defaults
67
+ * @returns {Array} Merged variants
68
+ */
69
+ function resolveVariants(variants) {
70
+ if (!variants.length) return DEFAULT_VARIANTS;
71
+
72
+ return Object.values(
73
+ [...DEFAULT_VARIANTS, ...variants].reduce((map, item) => {
74
+ map[item.type] = item;
75
+ return map;
76
+ }, {}),
77
+ );
78
+ }