@dr-ishaan/remake-blocks 1.0.0 → 1.1.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/LICENSE +1 -1
- package/README.md +167 -16
- package/dist/accordion.js +28 -0
- package/dist/astro.d.ts +57 -0
- package/dist/astro.d.ts.map +1 -0
- package/dist/astro.js +87 -0
- package/dist/astro.js.map +1 -0
- package/dist/index.d.ts +8 -52
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -86
- package/dist/index.js.map +1 -1
- package/dist/remark-remake-blocks.d.ts +24 -0
- package/dist/remark-remake-blocks.d.ts.map +1 -0
- package/dist/remark-remake-blocks.js +724 -0
- package/dist/remark-remake-blocks.js.map +1 -0
- package/dist/styles.css +225 -4
- package/dist/types.d.ts +76 -13
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +6 -5
- package/dist/types.js.map +1 -1
- package/package.json +36 -16
- package/dist/remark-callout-blocks.d.ts +0 -16
- package/dist/remark-callout-blocks.d.ts.map +0 -1
- package/dist/remark-callout-blocks.js +0 -628
- package/dist/remark-callout-blocks.js.map +0 -1
|
@@ -1,628 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* remark plugin for @dr-ishaan/remake-blocks
|
|
3
|
-
*
|
|
4
|
-
* A remark plugin that transforms callout directives inside blockquotes
|
|
5
|
-
* into styled callout components, and optionally enhances regular blockquotes.
|
|
6
|
-
*
|
|
7
|
-
* 29 first-class callout types — each directive maps 1:1 to its own
|
|
8
|
-
* unique visual identity. No alias resolution.
|
|
9
|
-
*/
|
|
10
|
-
import { visit } from "unist-util-visit";
|
|
11
|
-
// ---------------------------------------------------------------------------
|
|
12
|
-
// 29 Built-in callout configurations
|
|
13
|
-
// ---------------------------------------------------------------------------
|
|
14
|
-
const BUILTIN_CALLOUTS = [
|
|
15
|
-
// ── GFM Primaries (5) ─────────────────────────────────────────────────
|
|
16
|
-
{
|
|
17
|
-
type: "note",
|
|
18
|
-
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg>`,
|
|
19
|
-
className: "callout-note",
|
|
20
|
-
defaultTitle: "Note",
|
|
21
|
-
color: "#0969da",
|
|
22
|
-
backgroundColor: "#ddf4ff",
|
|
23
|
-
iconColor: "#0969da",
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
type: "tip",
|
|
27
|
-
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5"/><path d="M9 18h6"/><path d="M10 22h4"/></svg>`,
|
|
28
|
-
className: "callout-tip",
|
|
29
|
-
defaultTitle: "Tip",
|
|
30
|
-
color: "#1a7f37",
|
|
31
|
-
backgroundColor: "#dafbe1",
|
|
32
|
-
iconColor: "#1a7f37",
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
type: "important",
|
|
36
|
-
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>`,
|
|
37
|
-
className: "callout-important",
|
|
38
|
-
defaultTitle: "Important",
|
|
39
|
-
color: "#8250df",
|
|
40
|
-
backgroundColor: "#fbefff",
|
|
41
|
-
iconColor: "#8250df",
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
type: "warning",
|
|
45
|
-
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>`,
|
|
46
|
-
className: "callout-warning",
|
|
47
|
-
defaultTitle: "Warning",
|
|
48
|
-
color: "#9a6700",
|
|
49
|
-
backgroundColor: "#fff8c5",
|
|
50
|
-
iconColor: "#9a6700",
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
type: "caution",
|
|
54
|
-
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/></svg>`,
|
|
55
|
-
className: "callout-caution",
|
|
56
|
-
defaultTitle: "Caution",
|
|
57
|
-
color: "#cf222e",
|
|
58
|
-
backgroundColor: "#ffebe9",
|
|
59
|
-
iconColor: "#cf222e",
|
|
60
|
-
},
|
|
61
|
-
// ── Obsidian Primaries (10) ────────────────────────────────────────────
|
|
62
|
-
{
|
|
63
|
-
type: "abstract",
|
|
64
|
-
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z"/><path d="M14 2v6h6"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><line x1="10" y1="9" x2="8" y2="9"/></svg>`,
|
|
65
|
-
className: "callout-abstract",
|
|
66
|
-
defaultTitle: "Abstract",
|
|
67
|
-
color: "#0891b2",
|
|
68
|
-
backgroundColor: "#ecfeff",
|
|
69
|
-
iconColor: "#0891b2",
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
type: "info",
|
|
73
|
-
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>`,
|
|
74
|
-
className: "callout-info",
|
|
75
|
-
defaultTitle: "Info",
|
|
76
|
-
color: "#57606a",
|
|
77
|
-
backgroundColor: "#f6f8fa",
|
|
78
|
-
iconColor: "#57606a",
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
type: "success",
|
|
82
|
-
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><path d="M22 4 12 14.01l-3-3"/></svg>`,
|
|
83
|
-
className: "callout-success",
|
|
84
|
-
defaultTitle: "Success",
|
|
85
|
-
color: "#1a8840",
|
|
86
|
-
backgroundColor: "#caf7ca",
|
|
87
|
-
iconColor: "#1a8840",
|
|
88
|
-
},
|
|
89
|
-
{
|
|
90
|
-
type: "question",
|
|
91
|
-
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><path d="M12 17h.01"/></svg>`,
|
|
92
|
-
className: "callout-question",
|
|
93
|
-
defaultTitle: "Question",
|
|
94
|
-
color: "#bf6c06",
|
|
95
|
-
backgroundColor: "#fff1e5",
|
|
96
|
-
iconColor: "#bf6c06",
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
type: "failure",
|
|
100
|
-
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/></svg>`,
|
|
101
|
-
className: "callout-failure",
|
|
102
|
-
defaultTitle: "Failure",
|
|
103
|
-
color: "#b33a3a",
|
|
104
|
-
backgroundColor: "#ffe2e2",
|
|
105
|
-
iconColor: "#b33a3a",
|
|
106
|
-
},
|
|
107
|
-
{
|
|
108
|
-
type: "danger",
|
|
109
|
-
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>`,
|
|
110
|
-
className: "callout-danger",
|
|
111
|
-
defaultTitle: "Danger",
|
|
112
|
-
color: "#cf222e",
|
|
113
|
-
backgroundColor: "#ffebe9",
|
|
114
|
-
iconColor: "#cf222e",
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
type: "quote",
|
|
118
|
-
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 21c3 0 7-1 7-8V5c0-1.25-.756-2.017-2-2H4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2 1 0 1 0 1 1v1c0 1-1 2-2 2s-1 .008-1 1.031V21z"/><path d="M15 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2h-4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2h.75c0 2.25.25 4-2.75 4v3z"/></svg>`,
|
|
119
|
-
className: "callout-quote",
|
|
120
|
-
defaultTitle: "Quote",
|
|
121
|
-
color: "#656d76",
|
|
122
|
-
backgroundColor: "#f6f8fa",
|
|
123
|
-
iconColor: "#656d76",
|
|
124
|
-
},
|
|
125
|
-
{
|
|
126
|
-
type: "bug",
|
|
127
|
-
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m8 2 1.88 1.88"/><path d="M14.12 3.88 16 2"/><path d="M9 7.13v-1a3.003 3.003 0 1 1 6 0v1"/><path d="M12 20c-3.3 0-6-2.7-6-6v-3a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v3c0 3.3-2.7 6-6 6"/><path d="M12 20v-9"/><path d="M6.53 9C4.6 8.8 3 7.1 3 5"/><path d="M6 13H2"/><path d="M3 21c0-2.1 1.7-3.9 3.8-4"/><path d="M20.97 5c0 2.1-1.6 3.8-3.5 4"/><path d="M22 13h-4"/><path d="M17.2 17c2.1.1 3.8 1.9 3.8 4"/></svg>`,
|
|
128
|
-
className: "callout-bug",
|
|
129
|
-
defaultTitle: "Bug",
|
|
130
|
-
color: "#c93257",
|
|
131
|
-
backgroundColor: "#ffedf2",
|
|
132
|
-
iconColor: "#c93257",
|
|
133
|
-
},
|
|
134
|
-
{
|
|
135
|
-
type: "example",
|
|
136
|
-
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><line x1="10" y1="9" x2="8" y2="9"/></svg>`,
|
|
137
|
-
className: "callout-example",
|
|
138
|
-
defaultTitle: "Example",
|
|
139
|
-
color: "#8250df",
|
|
140
|
-
backgroundColor: "#fbefff",
|
|
141
|
-
iconColor: "#8250df",
|
|
142
|
-
},
|
|
143
|
-
{
|
|
144
|
-
type: "todo",
|
|
145
|
-
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="18" x="3" y="3" rx="2"/><path d="m9 12 2 2 4-4"/></svg>`,
|
|
146
|
-
className: "callout-todo",
|
|
147
|
-
defaultTitle: "Todo",
|
|
148
|
-
color: "#2274a5",
|
|
149
|
-
backgroundColor: "#e5f2fc",
|
|
150
|
-
iconColor: "#2274a5",
|
|
151
|
-
},
|
|
152
|
-
// ── Promoted Aliases — first-class types (14) ──────────────────────────
|
|
153
|
-
{
|
|
154
|
-
type: "summary",
|
|
155
|
-
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z"/><path d="M14 2v6h6"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg>`,
|
|
156
|
-
className: "callout-summary",
|
|
157
|
-
defaultTitle: "Summary",
|
|
158
|
-
color: "#0e7490",
|
|
159
|
-
backgroundColor: "#f0fdfa",
|
|
160
|
-
iconColor: "#0e7490",
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
type: "tldr",
|
|
164
|
-
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg>`,
|
|
165
|
-
className: "callout-tldr",
|
|
166
|
-
defaultTitle: "TL;DR",
|
|
167
|
-
color: "#06b6d4",
|
|
168
|
-
backgroundColor: "#ecfeff",
|
|
169
|
-
iconColor: "#06b6d4",
|
|
170
|
-
},
|
|
171
|
-
{
|
|
172
|
-
type: "hint",
|
|
173
|
-
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 18v3c0 .6.4 1 1 1h4v-3h3v-3h2l1.4-1.4a6.5 6.5 0 1 0-4-4Z"/><circle cx="16.5" cy="7.5" r=".5" fill="currentColor"/></svg>`,
|
|
174
|
-
className: "callout-hint",
|
|
175
|
-
defaultTitle: "Hint",
|
|
176
|
-
color: "#3d8b37",
|
|
177
|
-
backgroundColor: "#e8f5e9",
|
|
178
|
-
iconColor: "#3d8b37",
|
|
179
|
-
},
|
|
180
|
-
{
|
|
181
|
-
type: "check",
|
|
182
|
-
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="18" x="3" y="3" rx="2"/><path d="m9 12 2 2 4-4"/></svg>`,
|
|
183
|
-
className: "callout-check",
|
|
184
|
-
defaultTitle: "Check",
|
|
185
|
-
color: "#0d9488",
|
|
186
|
-
backgroundColor: "#f0fdfa",
|
|
187
|
-
iconColor: "#0d9488",
|
|
188
|
-
},
|
|
189
|
-
{
|
|
190
|
-
type: "done",
|
|
191
|
-
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><path d="M22 4 12 14.01l-3-3"/></svg>`,
|
|
192
|
-
className: "callout-done",
|
|
193
|
-
defaultTitle: "Done",
|
|
194
|
-
color: "#15803d",
|
|
195
|
-
backgroundColor: "#dcfce7",
|
|
196
|
-
iconColor: "#15803d",
|
|
197
|
-
},
|
|
198
|
-
{
|
|
199
|
-
type: "help",
|
|
200
|
-
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><path d="M12 17h.01"/></svg>`,
|
|
201
|
-
className: "callout-help",
|
|
202
|
-
defaultTitle: "Help",
|
|
203
|
-
color: "#c26506",
|
|
204
|
-
backgroundColor: "#fff7ed",
|
|
205
|
-
iconColor: "#c26506",
|
|
206
|
-
},
|
|
207
|
-
{
|
|
208
|
-
type: "faq",
|
|
209
|
-
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/><path d="M8 10h.01"/><path d="M12 10h.01"/><path d="M16 10h.01"/></svg>`,
|
|
210
|
-
className: "callout-faq",
|
|
211
|
-
defaultTitle: "FAQ",
|
|
212
|
-
color: "#b45309",
|
|
213
|
-
backgroundColor: "#fffbeb",
|
|
214
|
-
iconColor: "#b45309",
|
|
215
|
-
},
|
|
216
|
-
{
|
|
217
|
-
type: "attention",
|
|
218
|
-
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>`,
|
|
219
|
-
className: "callout-attention",
|
|
220
|
-
defaultTitle: "Attention",
|
|
221
|
-
color: "#ca8a04",
|
|
222
|
-
backgroundColor: "#fefce8",
|
|
223
|
-
iconColor: "#ca8a04",
|
|
224
|
-
},
|
|
225
|
-
{
|
|
226
|
-
type: "fail",
|
|
227
|
-
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="7.86 2 16.14 2 22 7.86 22 16.14 16.14 22 7.86 22 2 16.14 2 7.86 7.86 2"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/></svg>`,
|
|
228
|
-
className: "callout-fail",
|
|
229
|
-
defaultTitle: "Fail",
|
|
230
|
-
color: "#be123c",
|
|
231
|
-
backgroundColor: "#fff1f2",
|
|
232
|
-
iconColor: "#be123c",
|
|
233
|
-
},
|
|
234
|
-
{
|
|
235
|
-
type: "missing",
|
|
236
|
-
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/><line x1="8" y1="11" x2="14" y2="11"/></svg>`,
|
|
237
|
-
className: "callout-missing",
|
|
238
|
-
defaultTitle: "Missing",
|
|
239
|
-
color: "#9f3a3a",
|
|
240
|
-
backgroundColor: "#fef2f2",
|
|
241
|
-
iconColor: "#9f3a3a",
|
|
242
|
-
},
|
|
243
|
-
{
|
|
244
|
-
type: "error",
|
|
245
|
-
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="7.86 2 16.14 2 22 7.86 22 16.14 16.14 22 7.86 22 2 16.14 2 7.86 7.86 2"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>`,
|
|
246
|
-
className: "callout-error",
|
|
247
|
-
defaultTitle: "Error",
|
|
248
|
-
color: "#dc2626",
|
|
249
|
-
backgroundColor: "#fef2f2",
|
|
250
|
-
iconColor: "#dc2626",
|
|
251
|
-
},
|
|
252
|
-
{
|
|
253
|
-
type: "cite",
|
|
254
|
-
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 9a3 3 0 0 1 0 6v2a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-2a3 3 0 0 1 0-6V7a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2Z"/><path d="M13 5v2"/><path d="M13 17v2"/><path d="M13 11v2"/></svg>`,
|
|
255
|
-
className: "callout-cite",
|
|
256
|
-
defaultTitle: "Cite",
|
|
257
|
-
color: "#5b6abf",
|
|
258
|
-
backgroundColor: "#eef2ff",
|
|
259
|
-
iconColor: "#5b6abf",
|
|
260
|
-
},
|
|
261
|
-
];
|
|
262
|
-
// ---------------------------------------------------------------------------
|
|
263
|
-
// Default plugin options
|
|
264
|
-
// ---------------------------------------------------------------------------
|
|
265
|
-
const DEFAULT_OPTIONS = {
|
|
266
|
-
calloutContainerTag: "div",
|
|
267
|
-
calloutClass: "callout",
|
|
268
|
-
calloutTitleClass: "callout-title",
|
|
269
|
-
calloutBodyClass: "callout-body",
|
|
270
|
-
enhanceBlockquotes: true,
|
|
271
|
-
blockquoteClass: "blockquote-enhanced",
|
|
272
|
-
dataCalloutType: true,
|
|
273
|
-
customCallouts: [],
|
|
274
|
-
calloutPattern: undefined,
|
|
275
|
-
};
|
|
276
|
-
// ---------------------------------------------------------------------------
|
|
277
|
-
// Helper: Build the callout configuration map
|
|
278
|
-
// ---------------------------------------------------------------------------
|
|
279
|
-
function buildCalloutConfigMap(options) {
|
|
280
|
-
const map = new Map();
|
|
281
|
-
for (const config of BUILTIN_CALLOUTS) {
|
|
282
|
-
map.set(config.type.toLowerCase(), config);
|
|
283
|
-
}
|
|
284
|
-
if (options.customCallouts) {
|
|
285
|
-
for (const config of options.customCallouts) {
|
|
286
|
-
map.set(config.type.toLowerCase(), config);
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
return map;
|
|
290
|
-
}
|
|
291
|
-
// ---------------------------------------------------------------------------
|
|
292
|
-
// Helper: Build the dynamic regex matching all directives
|
|
293
|
-
// ---------------------------------------------------------------------------
|
|
294
|
-
function buildCalloutPattern(configMap) {
|
|
295
|
-
const allDirectives = Array.from(configMap.keys())
|
|
296
|
-
.map((t) => t.toUpperCase())
|
|
297
|
-
.sort((a, b) => b.length - a.length);
|
|
298
|
-
return new RegExp(`^\\[!(${allDirectives.join("|")})\\]([+-]?)(?:[^\\S\\n]+(.+))?`, "i");
|
|
299
|
-
}
|
|
300
|
-
// ---------------------------------------------------------------------------
|
|
301
|
-
// Helper: Parse the first paragraph of a blockquote to detect a callout
|
|
302
|
-
// ---------------------------------------------------------------------------
|
|
303
|
-
function parseCalloutDirective(blockquote, calloutPattern, configMap) {
|
|
304
|
-
const firstChild = blockquote.children[0];
|
|
305
|
-
if (!firstChild || firstChild.type !== "paragraph")
|
|
306
|
-
return null;
|
|
307
|
-
const firstText = extractTextContent(firstChild);
|
|
308
|
-
if (!firstText)
|
|
309
|
-
return null;
|
|
310
|
-
const match = firstText.match(calloutPattern);
|
|
311
|
-
if (!match)
|
|
312
|
-
return null;
|
|
313
|
-
const type = match[1].toLowerCase();
|
|
314
|
-
if (!configMap.has(type))
|
|
315
|
-
return null;
|
|
316
|
-
// match[2] is the collapsible marker: "+", "-", or ""
|
|
317
|
-
const foldMarker = match[2] || "";
|
|
318
|
-
const collapsible = foldMarker === "+" || foldMarker === "-";
|
|
319
|
-
const collapsibleOpen = foldMarker === "+";
|
|
320
|
-
// The remainder is everything after the full regex match
|
|
321
|
-
const remainder = firstText.slice(match[0].length);
|
|
322
|
-
let customTitle;
|
|
323
|
-
let remainingContent;
|
|
324
|
-
if (match[3]) {
|
|
325
|
-
customTitle = match[3].trim() || undefined;
|
|
326
|
-
if (remainder.includes("\n")) {
|
|
327
|
-
const newlineIdx = remainder.indexOf("\n");
|
|
328
|
-
remainingContent = remainder.slice(newlineIdx + 1).trim() || undefined;
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
else {
|
|
332
|
-
const hasNewlineAfterDirective = /^\s*\n/.test(remainder);
|
|
333
|
-
if (hasNewlineAfterDirective) {
|
|
334
|
-
const afterNewline = remainder.replace(/^\s*\n/, "");
|
|
335
|
-
remainingContent = afterNewline.trim() || undefined;
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
return { type, customTitle, remainingContent, collapsible, collapsibleOpen };
|
|
339
|
-
}
|
|
340
|
-
// ---------------------------------------------------------------------------
|
|
341
|
-
// Helper: Extract plain text from an inline node
|
|
342
|
-
// ---------------------------------------------------------------------------
|
|
343
|
-
function extractTextContent(node) {
|
|
344
|
-
let text = "";
|
|
345
|
-
for (const child of node.children) {
|
|
346
|
-
if (child.type === "text") {
|
|
347
|
-
text += child.value;
|
|
348
|
-
}
|
|
349
|
-
else if ("children" in child && Array.isArray(child.children)) {
|
|
350
|
-
text += extractTextContent(child);
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
return text;
|
|
354
|
-
}
|
|
355
|
-
// ---------------------------------------------------------------------------
|
|
356
|
-
// Helper: Create an HTML node
|
|
357
|
-
// ---------------------------------------------------------------------------
|
|
358
|
-
function html(value) {
|
|
359
|
-
return { type: "html", value };
|
|
360
|
-
}
|
|
361
|
-
// ---------------------------------------------------------------------------
|
|
362
|
-
// Helper: Build the callout HTML
|
|
363
|
-
// ---------------------------------------------------------------------------
|
|
364
|
-
function buildCalloutHtml(parsed, blockquote, calloutPattern, configMap, options) {
|
|
365
|
-
const config = configMap.get(parsed.type);
|
|
366
|
-
const title = parsed.customTitle || config.defaultTitle;
|
|
367
|
-
const dataAttr = options.dataCalloutType ? ` data-callout-type="${parsed.type}"` : "";
|
|
368
|
-
// Build body HTML from blockquote children, properly handling the first
|
|
369
|
-
// paragraph (strip the directive text but preserve inline markdown).
|
|
370
|
-
let bodyHtml = "";
|
|
371
|
-
const bodyChildren = blockquote.children.slice(1); // skip first paragraph (directive line)
|
|
372
|
-
for (const child of bodyChildren) {
|
|
373
|
-
bodyHtml += serializeNodeToHtml(child);
|
|
374
|
-
}
|
|
375
|
-
// Handle content from the first paragraph after the directive.
|
|
376
|
-
// If remainingContent exists (text after directive on same line),
|
|
377
|
-
// or if the first paragraph has children after the directive text,
|
|
378
|
-
// we need to serialize them properly to preserve inline markdown.
|
|
379
|
-
const firstPara = blockquote.children[0];
|
|
380
|
-
if (firstPara && firstPara.type === "paragraph") {
|
|
381
|
-
const firstParaHtml = serializeFirstParagraphAfterDirective(firstPara, calloutPattern);
|
|
382
|
-
if (firstParaHtml) {
|
|
383
|
-
bodyHtml = firstParaHtml + bodyHtml;
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
const iconColor = config.iconColor || config.color;
|
|
387
|
-
// ARIA role based on semantic type
|
|
388
|
-
const ariaRole = getAriaRole(parsed.type);
|
|
389
|
-
const ariaLabel = `role="${ariaRole}"`;
|
|
390
|
-
if (parsed.collapsible) {
|
|
391
|
-
// Collapsible callout → native <details>/<summary> (no JS needed)
|
|
392
|
-
const openAttr = parsed.collapsibleOpen ? " open" : "";
|
|
393
|
-
const calloutHtml = [
|
|
394
|
-
`<details class="${options.calloutClass} ${config.className} collapsible"${dataAttr} ${ariaLabel}${openAttr}>`,
|
|
395
|
-
` <summary class="${options.calloutTitleClass}" style="color:${iconColor}">`,
|
|
396
|
-
` <span class="callout-icon" style="color:${iconColor}">${config.icon}</span>`,
|
|
397
|
-
` <span class="callout-title-text">${escapeHtml(title)}</span>`,
|
|
398
|
-
` </summary>`,
|
|
399
|
-
` <div class="${options.calloutBodyClass}">`,
|
|
400
|
-
bodyHtml,
|
|
401
|
-
` </div>`,
|
|
402
|
-
`</details>`,
|
|
403
|
-
].join("\n");
|
|
404
|
-
return html(calloutHtml);
|
|
405
|
-
}
|
|
406
|
-
// Regular callout → semantic <aside> element
|
|
407
|
-
const calloutHtml = [
|
|
408
|
-
`<aside class="${options.calloutClass} ${config.className}"${dataAttr} ${ariaLabel}>`,
|
|
409
|
-
` <div class="${options.calloutTitleClass}" style="color:${iconColor}">`,
|
|
410
|
-
` <span class="callout-icon" style="color:${iconColor}">${config.icon}</span>`,
|
|
411
|
-
` <span class="callout-title-text">${escapeHtml(title)}</span>`,
|
|
412
|
-
` </div>`,
|
|
413
|
-
` <div class="${options.calloutBodyClass}">`,
|
|
414
|
-
bodyHtml,
|
|
415
|
-
` </div>`,
|
|
416
|
-
`</aside>`,
|
|
417
|
-
].join("\n");
|
|
418
|
-
return html(calloutHtml);
|
|
419
|
-
}
|
|
420
|
-
// ---------------------------------------------------------------------------
|
|
421
|
-
// Helper: Map callout type to ARIA role
|
|
422
|
-
// ---------------------------------------------------------------------------
|
|
423
|
-
function getAriaRole(type) {
|
|
424
|
-
switch (type) {
|
|
425
|
-
case "warning":
|
|
426
|
-
case "attention":
|
|
427
|
-
case "caution":
|
|
428
|
-
case "danger":
|
|
429
|
-
case "error":
|
|
430
|
-
case "fail":
|
|
431
|
-
case "failure":
|
|
432
|
-
case "missing":
|
|
433
|
-
return "alert";
|
|
434
|
-
case "note":
|
|
435
|
-
case "info":
|
|
436
|
-
case "abstract":
|
|
437
|
-
case "summary":
|
|
438
|
-
case "tldr":
|
|
439
|
-
case "example":
|
|
440
|
-
case "cite":
|
|
441
|
-
case "quote":
|
|
442
|
-
return "note";
|
|
443
|
-
case "tip":
|
|
444
|
-
case "hint":
|
|
445
|
-
case "important":
|
|
446
|
-
case "success":
|
|
447
|
-
case "check":
|
|
448
|
-
case "done":
|
|
449
|
-
case "todo":
|
|
450
|
-
return "note";
|
|
451
|
-
case "question":
|
|
452
|
-
case "help":
|
|
453
|
-
case "faq":
|
|
454
|
-
case "bug":
|
|
455
|
-
return "note";
|
|
456
|
-
default:
|
|
457
|
-
return "note";
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
// ---------------------------------------------------------------------------
|
|
461
|
-
// Helper: Serialize the first paragraph's content after the directive,
|
|
462
|
-
// preserving inline markdown (bold, italic, code, links, etc.)
|
|
463
|
-
// ---------------------------------------------------------------------------
|
|
464
|
-
function serializeFirstParagraphAfterDirective(paragraph, calloutPattern) {
|
|
465
|
-
// Find the text node containing the directive and split it
|
|
466
|
-
const children = paragraph.children;
|
|
467
|
-
let foundDirective = false;
|
|
468
|
-
const remainingChildren = [];
|
|
469
|
-
for (let i = 0; i < children.length; i++) {
|
|
470
|
-
const child = children[i];
|
|
471
|
-
if (!foundDirective && child.type === "text") {
|
|
472
|
-
const textVal = child.value;
|
|
473
|
-
const match = textVal.match(calloutPattern);
|
|
474
|
-
if (match) {
|
|
475
|
-
foundDirective = true;
|
|
476
|
-
// Get the text after the full match (includes custom title + newline + body)
|
|
477
|
-
const afterDirective = textVal.slice(match[0].length);
|
|
478
|
-
// If there's a custom title captured by regex, strip it from remaining text
|
|
479
|
-
// match[3] is the custom title (if any), but the regex already consumed it
|
|
480
|
-
// The remaining text after match[0] may start with a newline + body text
|
|
481
|
-
// or just be the custom title text that was already captured.
|
|
482
|
-
// After the directive + optional fold marker + optional title,
|
|
483
|
-
// what remains on this line (after the title) is body content.
|
|
484
|
-
// But the regex captures the title as match[3]. The text after
|
|
485
|
-
// match[0] could be empty, a newline, or continuation text.
|
|
486
|
-
if (afterDirective.trim()) {
|
|
487
|
-
// Check if what remains includes a newline (body content after title)
|
|
488
|
-
const newlineIdx = afterDirective.indexOf("\n");
|
|
489
|
-
if (newlineIdx !== -1) {
|
|
490
|
-
// Content after newline is body content
|
|
491
|
-
const bodyText = afterDirective.slice(newlineIdx + 1).trim();
|
|
492
|
-
if (bodyText) {
|
|
493
|
-
remainingChildren.push({ type: "text", value: bodyText });
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
// If no newline, the remaining text is part of the title (already captured)
|
|
497
|
-
// or there's nothing left.
|
|
498
|
-
}
|
|
499
|
-
// Also include any subsequent children (after the text node with the directive)
|
|
500
|
-
for (let j = i + 1; j < children.length; j++) {
|
|
501
|
-
remainingChildren.push(children[j]);
|
|
502
|
-
}
|
|
503
|
-
break;
|
|
504
|
-
}
|
|
505
|
-
else {
|
|
506
|
-
// Text node doesn't contain directive (shouldn't happen but handle gracefully)
|
|
507
|
-
remainingChildren.push(child);
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
else if (foundDirective) {
|
|
511
|
-
remainingChildren.push(child);
|
|
512
|
-
}
|
|
513
|
-
// If we haven't found the directive yet and it's not a text node, skip it
|
|
514
|
-
// (the directive is always in a text node)
|
|
515
|
-
}
|
|
516
|
-
if (remainingChildren.length === 0)
|
|
517
|
-
return "";
|
|
518
|
-
// Serialize the remaining children as inline HTML
|
|
519
|
-
const innerHtml = remainingChildren.map((c) => inlineNodeToHtml(c)).join("");
|
|
520
|
-
return innerHtml.trim() ? `<p>${innerHtml}</p>\n` : "";
|
|
521
|
-
}
|
|
522
|
-
// ---------------------------------------------------------------------------
|
|
523
|
-
// Helper: Serialize mdast nodes to simple HTML
|
|
524
|
-
// ---------------------------------------------------------------------------
|
|
525
|
-
function serializeNodeToHtml(node, indent = "") {
|
|
526
|
-
switch (node.type) {
|
|
527
|
-
case "paragraph": {
|
|
528
|
-
const inner = node.children.map((c) => inlineNodeToHtml(c)).join("");
|
|
529
|
-
return `${indent}<p>${inner}</p>\n`;
|
|
530
|
-
}
|
|
531
|
-
case "heading": {
|
|
532
|
-
const inner = node.children.map((c) => inlineNodeToHtml(c)).join("");
|
|
533
|
-
return `${indent}<h${node.depth}>${inner}</h${node.depth}>\n`;
|
|
534
|
-
}
|
|
535
|
-
case "list": {
|
|
536
|
-
const tag = node.ordered ? "ol" : "ul";
|
|
537
|
-
const items = node.children.map((c) => serializeNodeToHtml(c, indent + " ")).join("");
|
|
538
|
-
return `${indent}<${tag}>\n${items}${indent}</${tag}>\n`;
|
|
539
|
-
}
|
|
540
|
-
case "listItem": {
|
|
541
|
-
const inner = node.children.map((c) => serializeNodeToHtml(c, indent + " ")).join("");
|
|
542
|
-
return `${indent}<li>\n${inner}${indent}</li>\n`;
|
|
543
|
-
}
|
|
544
|
-
case "code": {
|
|
545
|
-
const lang = node.lang ? ` class="language-${node.lang}"` : "";
|
|
546
|
-
return `${indent}<pre><code${lang}>${escapeHtml(node.value)}</code></pre>\n`;
|
|
547
|
-
}
|
|
548
|
-
case "blockquote": {
|
|
549
|
-
const inner = node.children.map((c) => serializeNodeToHtml(c, indent + " ")).join("");
|
|
550
|
-
return `${indent}<blockquote>\n${inner}${indent}</blockquote>\n`;
|
|
551
|
-
}
|
|
552
|
-
case "thematicBreak": {
|
|
553
|
-
return `${indent}<hr />\n`;
|
|
554
|
-
}
|
|
555
|
-
default:
|
|
556
|
-
return "";
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
function inlineNodeToHtml(node) {
|
|
560
|
-
switch (node.type) {
|
|
561
|
-
case "text":
|
|
562
|
-
return escapeHtml(node.value);
|
|
563
|
-
case "strong":
|
|
564
|
-
return `<strong>${node.children.map((c) => inlineNodeToHtml(c)).join("")}</strong>`;
|
|
565
|
-
case "emphasis":
|
|
566
|
-
return `<em>${node.children.map((c) => inlineNodeToHtml(c)).join("")}</em>`;
|
|
567
|
-
case "inlineCode":
|
|
568
|
-
return `<code>${escapeHtml(node.value)}</code>`;
|
|
569
|
-
case "link":
|
|
570
|
-
return `<a href="${escapeHtml(node.url)}">${node.children.map((c) => inlineNodeToHtml(c)).join("")}</a>`;
|
|
571
|
-
case "image":
|
|
572
|
-
return `<img src="${escapeHtml(node.url)}" alt="${escapeHtml(node.alt || "")}" />`;
|
|
573
|
-
case "delete":
|
|
574
|
-
return `<del>${node.children.map((c) => inlineNodeToHtml(c)).join("")}</del>`;
|
|
575
|
-
case "html":
|
|
576
|
-
return node.value;
|
|
577
|
-
default:
|
|
578
|
-
if (node.children) {
|
|
579
|
-
return node.children.map((c) => inlineNodeToHtml(c)).join("");
|
|
580
|
-
}
|
|
581
|
-
return "";
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
// ---------------------------------------------------------------------------
|
|
585
|
-
// Helper: Escape HTML entities
|
|
586
|
-
// ---------------------------------------------------------------------------
|
|
587
|
-
function escapeHtml(str) {
|
|
588
|
-
return str
|
|
589
|
-
.replace(/&/g, "&")
|
|
590
|
-
.replace(/</g, "<")
|
|
591
|
-
.replace(/>/g, ">")
|
|
592
|
-
.replace(/"/g, """)
|
|
593
|
-
.replace(/'/g, "'");
|
|
594
|
-
}
|
|
595
|
-
// ---------------------------------------------------------------------------
|
|
596
|
-
// Plugin implementation
|
|
597
|
-
// ---------------------------------------------------------------------------
|
|
598
|
-
export const remarkCalloutBlocks = (userOptions) => {
|
|
599
|
-
const options = {
|
|
600
|
-
...DEFAULT_OPTIONS,
|
|
601
|
-
...userOptions,
|
|
602
|
-
};
|
|
603
|
-
const configMap = buildCalloutConfigMap(options);
|
|
604
|
-
const calloutPattern = options.calloutPattern || buildCalloutPattern(configMap);
|
|
605
|
-
return (tree) => {
|
|
606
|
-
visit(tree, "blockquote", (node, index, parent) => {
|
|
607
|
-
if (index === undefined || !parent)
|
|
608
|
-
return;
|
|
609
|
-
const parsed = parseCalloutDirective(node, calloutPattern, configMap);
|
|
610
|
-
if (parsed) {
|
|
611
|
-
const calloutNode = buildCalloutHtml(parsed, node, calloutPattern, configMap, options);
|
|
612
|
-
parent.children[index] = calloutNode;
|
|
613
|
-
}
|
|
614
|
-
else if (options.enhanceBlockquotes) {
|
|
615
|
-
const enhancedNode = html([
|
|
616
|
-
`<div class="${options.blockquoteClass}">`,
|
|
617
|
-
` <blockquote>`,
|
|
618
|
-
node.children.map((c) => serializeNodeToHtml(c, " ")).join(""),
|
|
619
|
-
` </blockquote>`,
|
|
620
|
-
`</div>`,
|
|
621
|
-
].join("\n"));
|
|
622
|
-
parent.children[index] = enhancedNode;
|
|
623
|
-
}
|
|
624
|
-
});
|
|
625
|
-
};
|
|
626
|
-
};
|
|
627
|
-
export { BUILTIN_CALLOUTS };
|
|
628
|
-
//# sourceMappingURL=remark-callout-blocks.js.map
|