@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 +199 -0
- package/package.json +55 -0
- package/src/constants.js +125 -0
- package/src/helper.js +15 -0
- package/src/index.d.ts +39 -0
- package/src/index.js +41 -0
- package/src/renderer.js +26 -0
- package/src/styles.js +19 -0
- package/src/tokenizer.js +78 -0
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
|
+
}
|
package/src/constants.js
ADDED
|
@@ -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
|
+
}
|
package/src/renderer.js
ADDED
|
@@ -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
|
+
}
|
package/src/tokenizer.js
ADDED
|
@@ -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
|
+
}
|