@changerawr/markdown 1.0.4 → 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 +21 -0
- package/README.md +129 -11
- package/dist/index.d.mts +63 -47
- package/dist/index.d.ts +63 -47
- package/dist/index.js +677 -448
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +661 -449
- package/dist/index.mjs.map +1 -1
- package/dist/react/index.d.mts +2 -37
- package/dist/react/index.d.ts +2 -37
- package/dist/react/index.js +604 -432
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +604 -433
- package/dist/react/index.mjs.map +1 -1
- package/dist/standalone.browser.js +2722 -0
- package/dist/standalone.d.mts +2 -37
- package/dist/standalone.d.ts +2 -37
- package/dist/standalone.js +604 -431
- package/dist/standalone.js.map +1 -1
- package/dist/standalone.mjs +604 -431
- package/dist/standalone.mjs.map +1 -1
- package/dist/tailwind/index.d.mts +6 -2
- package/dist/tailwind/index.d.ts +6 -2
- package/dist/tailwind/index.js +204 -95
- package/dist/tailwind/index.js.map +1 -1
- package/dist/tailwind/index.mjs +204 -95
- package/dist/tailwind/index.mjs.map +1 -1
- package/package.json +4 -2
package/dist/index.mjs
CHANGED
|
@@ -1,43 +1,58 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
1
|
// src/parser.ts
|
|
4
2
|
var MarkdownParser = class {
|
|
5
3
|
constructor(config) {
|
|
6
4
|
this.rules = [];
|
|
7
5
|
this.warnings = [];
|
|
8
|
-
this.config =
|
|
6
|
+
this.config = {
|
|
7
|
+
debugMode: false,
|
|
8
|
+
maxIterations: 1e4,
|
|
9
|
+
validateMarkdown: false,
|
|
10
|
+
...config
|
|
11
|
+
};
|
|
9
12
|
}
|
|
10
13
|
addRule(rule) {
|
|
11
14
|
this.rules.push(rule);
|
|
12
15
|
this.rules.sort((a, b) => {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
if (
|
|
16
|
-
if (
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
const aFeatureExtension = ["alert", "button", "embed"].includes(a.name);
|
|
17
|
+
const bFeatureExtension = ["alert", "button", "embed"].includes(b.name);
|
|
18
|
+
if (aFeatureExtension && !bFeatureExtension) return -1;
|
|
19
|
+
if (!aFeatureExtension && bFeatureExtension) return 1;
|
|
20
|
+
const aCoreExtension = ["text", "heading", "bold", "italic", "code", "codeblock", "link", "image", "list", "task-list", "blockquote", "hr", "paragraph", "line-break"].includes(a.name);
|
|
21
|
+
const bCoreExtension = ["text", "heading", "bold", "italic", "code", "codeblock", "link", "image", "list", "task-list", "blockquote", "hr", "paragraph", "line-break"].includes(b.name);
|
|
22
|
+
if (aCoreExtension && !bCoreExtension) return -1;
|
|
23
|
+
if (!aCoreExtension && bCoreExtension) return 1;
|
|
24
|
+
if (a.name === "image" && b.name === "link") return -1;
|
|
25
|
+
if (a.name === "link" && b.name === "image") return 1;
|
|
26
|
+
if (a.name === "task-item" && b.name === "list-item") return -1;
|
|
27
|
+
if (a.name === "list-item" && b.name === "task-item") return 1;
|
|
28
|
+
if (a.name === "codeblock" && b.name === "code") return -1;
|
|
29
|
+
if (a.name === "code" && b.name === "codeblock") return 1;
|
|
30
|
+
if (a.name === "bold" && b.name === "italic") return -1;
|
|
31
|
+
if (a.name === "italic" && b.name === "bold") return 1;
|
|
19
32
|
return a.name.localeCompare(b.name);
|
|
20
33
|
});
|
|
21
34
|
}
|
|
22
|
-
setupDefaultRulesIfEmpty() {
|
|
23
|
-
const hasDefaultRules = this.rules.some(
|
|
24
|
-
(rule) => !["alert", "button", "embed"].includes(rule.name)
|
|
25
|
-
);
|
|
26
|
-
if (!hasDefaultRules) {
|
|
27
|
-
this.setupDefaultRules();
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
35
|
hasRule(name) {
|
|
31
36
|
return this.rules.some((rule) => rule.name === name);
|
|
32
37
|
}
|
|
33
38
|
parse(markdown3) {
|
|
34
39
|
this.warnings = [];
|
|
35
|
-
|
|
40
|
+
if (!markdown3.trim()) {
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
if (this.rules.length === 0) {
|
|
44
|
+
this.warnings.push("No parse rules registered - consider using CoreExtensions");
|
|
45
|
+
return [{
|
|
46
|
+
type: "text",
|
|
47
|
+
content: markdown3,
|
|
48
|
+
raw: markdown3
|
|
49
|
+
}];
|
|
50
|
+
}
|
|
36
51
|
const processedMarkdown = this.preprocessMarkdown(markdown3);
|
|
37
52
|
const tokens = [];
|
|
38
53
|
let remaining = processedMarkdown;
|
|
39
54
|
let iterationCount = 0;
|
|
40
|
-
const maxIterations = this.config.maxIterations ||
|
|
55
|
+
const maxIterations = this.config.maxIterations || 1e4;
|
|
41
56
|
while (remaining.length > 0 && iterationCount < maxIterations) {
|
|
42
57
|
iterationCount++;
|
|
43
58
|
let matched = false;
|
|
@@ -126,9 +141,6 @@ var MarkdownParser = class {
|
|
|
126
141
|
clearWarnings() {
|
|
127
142
|
this.warnings = [];
|
|
128
143
|
}
|
|
129
|
-
getIterationCount() {
|
|
130
|
-
return 0;
|
|
131
|
-
}
|
|
132
144
|
preprocessMarkdown(markdown3) {
|
|
133
145
|
if (this.config.validateMarkdown) {
|
|
134
146
|
this.validateMarkdown(markdown3);
|
|
@@ -183,161 +195,6 @@ var MarkdownParser = class {
|
|
|
183
195
|
}
|
|
184
196
|
return processed;
|
|
185
197
|
}
|
|
186
|
-
setupDefaultRules() {
|
|
187
|
-
this.addRule({
|
|
188
|
-
name: "heading",
|
|
189
|
-
pattern: /^(#{1,6})\s+(.+)$/m,
|
|
190
|
-
render: (match) => ({
|
|
191
|
-
type: "heading",
|
|
192
|
-
content: match[2]?.trim() || "",
|
|
193
|
-
raw: match[0] || "",
|
|
194
|
-
attributes: {
|
|
195
|
-
level: String(match[1]?.length || 1)
|
|
196
|
-
}
|
|
197
|
-
})
|
|
198
|
-
});
|
|
199
|
-
this.addRule({
|
|
200
|
-
name: "codeblock",
|
|
201
|
-
pattern: /```(\w+)?\s*\n([\s\S]*?)\n```/,
|
|
202
|
-
render: (match) => ({
|
|
203
|
-
type: "codeblock",
|
|
204
|
-
content: match[2] || "",
|
|
205
|
-
raw: match[0] || "",
|
|
206
|
-
attributes: {
|
|
207
|
-
language: match[1] || "text"
|
|
208
|
-
}
|
|
209
|
-
})
|
|
210
|
-
});
|
|
211
|
-
this.addRule({
|
|
212
|
-
name: "hard-break-backslash",
|
|
213
|
-
pattern: /\\\s*\n/,
|
|
214
|
-
render: (match) => ({
|
|
215
|
-
type: "line-break",
|
|
216
|
-
content: "",
|
|
217
|
-
raw: match[0] || ""
|
|
218
|
-
})
|
|
219
|
-
});
|
|
220
|
-
this.addRule({
|
|
221
|
-
name: "hard-break-spaces",
|
|
222
|
-
pattern: / +\n/,
|
|
223
|
-
render: (match) => ({
|
|
224
|
-
type: "line-break",
|
|
225
|
-
content: "",
|
|
226
|
-
raw: match[0] || ""
|
|
227
|
-
})
|
|
228
|
-
});
|
|
229
|
-
this.addRule({
|
|
230
|
-
name: "paragraph-break",
|
|
231
|
-
pattern: /\n\s*\n/,
|
|
232
|
-
render: (match) => ({
|
|
233
|
-
type: "paragraph-break",
|
|
234
|
-
content: "",
|
|
235
|
-
raw: match[0] || ""
|
|
236
|
-
})
|
|
237
|
-
});
|
|
238
|
-
this.addRule({
|
|
239
|
-
name: "bold",
|
|
240
|
-
pattern: /\*\*((?:(?!\*\*).)+)\*\*/,
|
|
241
|
-
render: (match) => ({
|
|
242
|
-
type: "bold",
|
|
243
|
-
content: match[1] || "",
|
|
244
|
-
raw: match[0] || ""
|
|
245
|
-
})
|
|
246
|
-
});
|
|
247
|
-
this.addRule({
|
|
248
|
-
name: "italic",
|
|
249
|
-
pattern: /\*((?:(?!\*).)+)\*/,
|
|
250
|
-
render: (match) => ({
|
|
251
|
-
type: "italic",
|
|
252
|
-
content: match[1] || "",
|
|
253
|
-
raw: match[0] || ""
|
|
254
|
-
})
|
|
255
|
-
});
|
|
256
|
-
this.addRule({
|
|
257
|
-
name: "code",
|
|
258
|
-
pattern: /`([^`]+)`/,
|
|
259
|
-
render: (match) => ({
|
|
260
|
-
type: "code",
|
|
261
|
-
content: match[1] || "",
|
|
262
|
-
raw: match[0] || ""
|
|
263
|
-
})
|
|
264
|
-
});
|
|
265
|
-
this.addRule({
|
|
266
|
-
name: "image",
|
|
267
|
-
pattern: /!\[([^\]]*)\]\(([^)]+?)(?:\s+"([^"]+)")?\)/,
|
|
268
|
-
render: (match) => ({
|
|
269
|
-
type: "image",
|
|
270
|
-
content: match[1] || "",
|
|
271
|
-
raw: match[0] || "",
|
|
272
|
-
attributes: {
|
|
273
|
-
alt: match[1] || "",
|
|
274
|
-
src: match[2] || "",
|
|
275
|
-
title: match[3] || ""
|
|
276
|
-
}
|
|
277
|
-
})
|
|
278
|
-
});
|
|
279
|
-
this.addRule({
|
|
280
|
-
name: "link",
|
|
281
|
-
pattern: /\[([^\]]+)\]\(([^)]+)\)/,
|
|
282
|
-
render: (match) => ({
|
|
283
|
-
type: "link",
|
|
284
|
-
content: match[1] || "",
|
|
285
|
-
raw: match[0] || "",
|
|
286
|
-
attributes: {
|
|
287
|
-
href: match[2] || ""
|
|
288
|
-
}
|
|
289
|
-
})
|
|
290
|
-
});
|
|
291
|
-
this.addRule({
|
|
292
|
-
name: "task-list",
|
|
293
|
-
pattern: /^(\s*)-\s*\[([ xX])\]\s*(.+)$/m,
|
|
294
|
-
render: (match) => ({
|
|
295
|
-
type: "task-item",
|
|
296
|
-
content: match[3] || "",
|
|
297
|
-
raw: match[0] || "",
|
|
298
|
-
attributes: {
|
|
299
|
-
checked: String((match[2] || "").toLowerCase() === "x")
|
|
300
|
-
}
|
|
301
|
-
})
|
|
302
|
-
});
|
|
303
|
-
this.addRule({
|
|
304
|
-
name: "list",
|
|
305
|
-
pattern: /^(\s*)[-*+]\s+(.+)$/m,
|
|
306
|
-
render: (match) => ({
|
|
307
|
-
type: "list-item",
|
|
308
|
-
content: match[2] || "",
|
|
309
|
-
raw: match[0] || ""
|
|
310
|
-
})
|
|
311
|
-
});
|
|
312
|
-
this.addRule({
|
|
313
|
-
name: "blockquote",
|
|
314
|
-
pattern: /^>\s+(.+)$/m,
|
|
315
|
-
render: (match) => ({
|
|
316
|
-
type: "blockquote",
|
|
317
|
-
content: match[1] || "",
|
|
318
|
-
raw: match[0] || ""
|
|
319
|
-
})
|
|
320
|
-
});
|
|
321
|
-
this.addRule({
|
|
322
|
-
name: "hr",
|
|
323
|
-
pattern: /^---$/m,
|
|
324
|
-
render: (match) => ({
|
|
325
|
-
type: "hr",
|
|
326
|
-
content: "",
|
|
327
|
-
raw: match[0] || ""
|
|
328
|
-
})
|
|
329
|
-
});
|
|
330
|
-
this.addRule({
|
|
331
|
-
name: "soft-break",
|
|
332
|
-
pattern: /\n/,
|
|
333
|
-
render: (match) => ({
|
|
334
|
-
type: "soft-break",
|
|
335
|
-
content: " ",
|
|
336
|
-
// Convert to space for inline text
|
|
337
|
-
raw: match[0] || ""
|
|
338
|
-
})
|
|
339
|
-
});
|
|
340
|
-
}
|
|
341
198
|
};
|
|
342
199
|
|
|
343
200
|
// src/utils.ts
|
|
@@ -656,7 +513,6 @@ var MarkdownRenderer = class {
|
|
|
656
513
|
debugMode: false,
|
|
657
514
|
...config
|
|
658
515
|
};
|
|
659
|
-
this.setupDefaultRules();
|
|
660
516
|
}
|
|
661
517
|
addRule(rule) {
|
|
662
518
|
this.rules.set(rule.type, rule);
|
|
@@ -666,28 +522,20 @@ var MarkdownRenderer = class {
|
|
|
666
522
|
}
|
|
667
523
|
render(tokens) {
|
|
668
524
|
this.warnings = [];
|
|
669
|
-
const
|
|
525
|
+
const tokensWithFormat = tokens.map((token) => ({
|
|
526
|
+
...token,
|
|
527
|
+
attributes: {
|
|
528
|
+
...token.attributes,
|
|
529
|
+
format: this.config.format
|
|
530
|
+
}
|
|
531
|
+
}));
|
|
532
|
+
const htmlParts = tokensWithFormat.map((token) => this.renderToken(token));
|
|
670
533
|
const combinedHtml = htmlParts.join("");
|
|
671
534
|
if (this.config.sanitize && !this.config.allowUnsafeHtml) {
|
|
672
535
|
return sanitizeHtml(combinedHtml);
|
|
673
536
|
}
|
|
674
537
|
return combinedHtml;
|
|
675
538
|
}
|
|
676
|
-
getWarnings() {
|
|
677
|
-
return [...this.warnings];
|
|
678
|
-
}
|
|
679
|
-
getConfig() {
|
|
680
|
-
return { ...this.config };
|
|
681
|
-
}
|
|
682
|
-
updateConfig(config) {
|
|
683
|
-
this.config = { ...this.config, ...config };
|
|
684
|
-
}
|
|
685
|
-
setDebugMode(enabled) {
|
|
686
|
-
this.config.debugMode = enabled;
|
|
687
|
-
}
|
|
688
|
-
clearWarnings() {
|
|
689
|
-
this.warnings = [];
|
|
690
|
-
}
|
|
691
539
|
renderToken(token) {
|
|
692
540
|
const rule = this.rules.get(token.type);
|
|
693
541
|
if (rule) {
|
|
@@ -699,9 +547,6 @@ var MarkdownRenderer = class {
|
|
|
699
547
|
return this.createErrorBlock(`Render error for ${token.type}: ${errorMessage}`);
|
|
700
548
|
}
|
|
701
549
|
}
|
|
702
|
-
if (token.type === "text") {
|
|
703
|
-
return escapeHtml(token.content || token.raw || "");
|
|
704
|
-
}
|
|
705
550
|
if (this.config.debugMode) {
|
|
706
551
|
return this.createDebugBlock(token);
|
|
707
552
|
}
|
|
@@ -729,15 +574,234 @@ var MarkdownRenderer = class {
|
|
|
729
574
|
<strong>Content:</strong> ${escapeHtml(token.content || token.raw || "")}
|
|
730
575
|
</div>`;
|
|
731
576
|
}
|
|
732
|
-
|
|
733
|
-
this.
|
|
577
|
+
getWarnings() {
|
|
578
|
+
return [...this.warnings];
|
|
579
|
+
}
|
|
580
|
+
getConfig() {
|
|
581
|
+
return { ...this.config };
|
|
582
|
+
}
|
|
583
|
+
updateConfig(config) {
|
|
584
|
+
this.config = { ...this.config, ...config };
|
|
585
|
+
}
|
|
586
|
+
setDebugMode(enabled) {
|
|
587
|
+
this.config.debugMode = enabled;
|
|
588
|
+
}
|
|
589
|
+
clearWarnings() {
|
|
590
|
+
this.warnings = [];
|
|
591
|
+
}
|
|
592
|
+
};
|
|
593
|
+
|
|
594
|
+
// src/extensions/core/blockquote.ts
|
|
595
|
+
var BlockquoteExtension = {
|
|
596
|
+
name: "blockquote",
|
|
597
|
+
parseRules: [
|
|
598
|
+
{
|
|
599
|
+
name: "blockquote",
|
|
600
|
+
pattern: /^>\s+(.+)$/m,
|
|
601
|
+
render: (match) => ({
|
|
602
|
+
type: "blockquote",
|
|
603
|
+
content: match[1] || "",
|
|
604
|
+
raw: match[0] || ""
|
|
605
|
+
})
|
|
606
|
+
}
|
|
607
|
+
],
|
|
608
|
+
renderRules: [
|
|
609
|
+
{
|
|
610
|
+
type: "blockquote",
|
|
611
|
+
render: (token) => {
|
|
612
|
+
const content = escapeHtml(token.content);
|
|
613
|
+
const format = token.attributes?.format || "html";
|
|
614
|
+
if (format === "html") {
|
|
615
|
+
return `<blockquote style="border-left: 2px solid #d1d5db; padding: 8px 0 8px 16px; margin: 16px 0; font-style: italic; color: #6b7280;">${content}</blockquote>`;
|
|
616
|
+
}
|
|
617
|
+
return `<blockquote class="pl-4 py-2 border-l-2 border-border italic text-muted-foreground my-4">${content}</blockquote>`;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
]
|
|
621
|
+
};
|
|
622
|
+
|
|
623
|
+
// src/extensions/core/breaks.ts
|
|
624
|
+
var LineBreakExtension = {
|
|
625
|
+
name: "line-break",
|
|
626
|
+
parseRules: [
|
|
627
|
+
{
|
|
628
|
+
name: "hard-break-backslash",
|
|
629
|
+
pattern: /\\\s*\n/,
|
|
630
|
+
render: (match) => ({
|
|
631
|
+
type: "line-break",
|
|
632
|
+
content: "",
|
|
633
|
+
raw: match[0] || ""
|
|
634
|
+
})
|
|
635
|
+
},
|
|
636
|
+
{
|
|
637
|
+
name: "hard-break-spaces",
|
|
638
|
+
pattern: / +\n/,
|
|
639
|
+
render: (match) => ({
|
|
640
|
+
type: "line-break",
|
|
641
|
+
content: "",
|
|
642
|
+
raw: match[0] || ""
|
|
643
|
+
})
|
|
644
|
+
}
|
|
645
|
+
],
|
|
646
|
+
renderRules: [
|
|
647
|
+
{
|
|
648
|
+
type: "line-break",
|
|
649
|
+
render: () => "<br>"
|
|
650
|
+
},
|
|
651
|
+
{
|
|
652
|
+
type: "paragraph-break",
|
|
653
|
+
render: () => "</p><p>"
|
|
654
|
+
},
|
|
655
|
+
{
|
|
656
|
+
type: "soft-break",
|
|
657
|
+
render: (token) => token.content || " "
|
|
658
|
+
}
|
|
659
|
+
]
|
|
660
|
+
};
|
|
661
|
+
|
|
662
|
+
// src/extensions/core/code.ts
|
|
663
|
+
var InlineCodeExtension = {
|
|
664
|
+
name: "inline-code",
|
|
665
|
+
parseRules: [
|
|
666
|
+
{
|
|
667
|
+
name: "code",
|
|
668
|
+
pattern: /`([^`]+)`/,
|
|
669
|
+
render: (match) => ({
|
|
670
|
+
type: "code",
|
|
671
|
+
content: match[1] || "",
|
|
672
|
+
raw: match[0] || ""
|
|
673
|
+
})
|
|
674
|
+
}
|
|
675
|
+
],
|
|
676
|
+
renderRules: [
|
|
677
|
+
{
|
|
678
|
+
type: "code",
|
|
679
|
+
render: (token) => {
|
|
680
|
+
const content = escapeHtml(token.content);
|
|
681
|
+
const format = token.attributes?.format;
|
|
682
|
+
if (format === "html") {
|
|
683
|
+
return `<code style="background-color: #f3f4f6; padding: 2px 6px; border-radius: 4px; font-family: monospace; font-size: 0.875rem;">${content}</code>`;
|
|
684
|
+
}
|
|
685
|
+
return `<code class="bg-muted px-1.5 py-0.5 rounded text-sm font-mono">${content}</code>`;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
]
|
|
689
|
+
};
|
|
690
|
+
var CodeBlockExtension = {
|
|
691
|
+
name: "codeblock",
|
|
692
|
+
parseRules: [
|
|
693
|
+
{
|
|
694
|
+
name: "codeblock",
|
|
695
|
+
pattern: /```(\w+)?\s*\n([\s\S]*?)\n```/,
|
|
696
|
+
render: (match) => ({
|
|
697
|
+
type: "codeblock",
|
|
698
|
+
content: match[2] || "",
|
|
699
|
+
raw: match[0] || "",
|
|
700
|
+
attributes: {
|
|
701
|
+
language: match[1] || "text"
|
|
702
|
+
}
|
|
703
|
+
})
|
|
704
|
+
}
|
|
705
|
+
],
|
|
706
|
+
renderRules: [
|
|
707
|
+
{
|
|
708
|
+
type: "codeblock",
|
|
709
|
+
render: (token) => {
|
|
710
|
+
const language = token.attributes?.language || "text";
|
|
711
|
+
const escapedCode = escapeHtml(token.content);
|
|
712
|
+
const format = token.attributes?.format || "html";
|
|
713
|
+
if (format === "html") {
|
|
714
|
+
return `<pre style="background-color: #f3f4f6; padding: 16px; border-radius: 6px; overflow-x: auto; margin: 16px 0;"><code class="language-${escapeHtml(language)}">${escapedCode}</code></pre>`;
|
|
715
|
+
}
|
|
716
|
+
return `<pre class="bg-muted p-4 rounded-md overflow-x-auto my-4"><code class="language-${escapeHtml(language)}">${escapedCode}</code></pre>`;
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
]
|
|
720
|
+
};
|
|
721
|
+
|
|
722
|
+
// src/extensions/core/emphasis.ts
|
|
723
|
+
var BoldExtension = {
|
|
724
|
+
name: "bold",
|
|
725
|
+
parseRules: [
|
|
726
|
+
{
|
|
727
|
+
name: "bold",
|
|
728
|
+
pattern: /\*\*((?:(?!\*\*).)+)\*\*/,
|
|
729
|
+
render: (match) => ({
|
|
730
|
+
type: "bold",
|
|
731
|
+
content: match[1] || "",
|
|
732
|
+
raw: match[0] || ""
|
|
733
|
+
})
|
|
734
|
+
}
|
|
735
|
+
],
|
|
736
|
+
renderRules: [
|
|
737
|
+
{
|
|
738
|
+
type: "bold",
|
|
739
|
+
render: (token) => {
|
|
740
|
+
const content = escapeHtml(token.content);
|
|
741
|
+
const format = token.attributes?.format;
|
|
742
|
+
if (format === "html") {
|
|
743
|
+
return `<strong>${content}</strong>`;
|
|
744
|
+
}
|
|
745
|
+
return `<strong class="font-bold">${content}</strong>`;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
]
|
|
749
|
+
};
|
|
750
|
+
var ItalicExtension = {
|
|
751
|
+
name: "italic",
|
|
752
|
+
parseRules: [
|
|
753
|
+
{
|
|
754
|
+
name: "italic",
|
|
755
|
+
pattern: /\*((?:(?!\*).)+)\*/,
|
|
756
|
+
render: (match) => ({
|
|
757
|
+
type: "italic",
|
|
758
|
+
content: match[1] || "",
|
|
759
|
+
raw: match[0] || ""
|
|
760
|
+
})
|
|
761
|
+
}
|
|
762
|
+
],
|
|
763
|
+
renderRules: [
|
|
764
|
+
{
|
|
765
|
+
type: "italic",
|
|
766
|
+
render: (token) => {
|
|
767
|
+
const content = escapeHtml(token.content);
|
|
768
|
+
const format = token.attributes?.format;
|
|
769
|
+
if (format === "html") {
|
|
770
|
+
return `<em>${content}</em>`;
|
|
771
|
+
}
|
|
772
|
+
return `<em class="italic">${content}</em>`;
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
]
|
|
776
|
+
};
|
|
777
|
+
|
|
778
|
+
// src/extensions/core/heading.ts
|
|
779
|
+
var HeadingExtension = {
|
|
780
|
+
name: "heading",
|
|
781
|
+
parseRules: [
|
|
782
|
+
{
|
|
783
|
+
name: "heading",
|
|
784
|
+
pattern: /^(#{1,6})\s+(.+)$/m,
|
|
785
|
+
render: (match) => ({
|
|
786
|
+
type: "heading",
|
|
787
|
+
content: match[2]?.trim() || "",
|
|
788
|
+
raw: match[0] || "",
|
|
789
|
+
attributes: {
|
|
790
|
+
level: String(match[1]?.length || 1)
|
|
791
|
+
}
|
|
792
|
+
})
|
|
793
|
+
}
|
|
794
|
+
],
|
|
795
|
+
renderRules: [
|
|
796
|
+
{
|
|
734
797
|
type: "heading",
|
|
735
798
|
render: (token) => {
|
|
736
799
|
const level = parseInt(token.attributes?.level || "1");
|
|
737
800
|
const text = token.content;
|
|
738
801
|
const id = generateId(text);
|
|
739
802
|
const escapedContent = escapeHtml(text);
|
|
740
|
-
|
|
803
|
+
const format = token.attributes?.format || "html";
|
|
804
|
+
if (format === "html") {
|
|
741
805
|
return `<h${level} id="${id}">${escapedContent}</h${level}>`;
|
|
742
806
|
}
|
|
743
807
|
let headingClasses = "group relative flex items-center gap-2";
|
|
@@ -764,61 +828,108 @@ var MarkdownRenderer = class {
|
|
|
764
828
|
return `<h${level} id="${id}" class="${headingClasses}">
|
|
765
829
|
${escapedContent}
|
|
766
830
|
<a href="#${id}" class="opacity-0 group-hover:opacity-100 text-muted-foreground transition-opacity">
|
|
767
|
-
<svg width="16" height="16" viewBox="0 0
|
|
768
|
-
|
|
769
|
-
|
|
831
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
832
|
+
<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/>
|
|
833
|
+
<path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/>
|
|
834
|
+
</svg>
|
|
770
835
|
</a>
|
|
771
836
|
</h${level}>`;
|
|
772
837
|
}
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
this.addRule({
|
|
795
|
-
type: "code",
|
|
838
|
+
}
|
|
839
|
+
]
|
|
840
|
+
};
|
|
841
|
+
|
|
842
|
+
// src/extensions/core/hr.ts
|
|
843
|
+
var HorizontalRuleExtension = {
|
|
844
|
+
name: "hr",
|
|
845
|
+
parseRules: [
|
|
846
|
+
{
|
|
847
|
+
name: "hr",
|
|
848
|
+
pattern: /^---$/m,
|
|
849
|
+
render: (match) => ({
|
|
850
|
+
type: "hr",
|
|
851
|
+
content: "",
|
|
852
|
+
raw: match[0] || ""
|
|
853
|
+
})
|
|
854
|
+
}
|
|
855
|
+
],
|
|
856
|
+
renderRules: [
|
|
857
|
+
{
|
|
858
|
+
type: "hr",
|
|
796
859
|
render: (token) => {
|
|
797
|
-
const
|
|
798
|
-
if (
|
|
799
|
-
return
|
|
860
|
+
const format = token.attributes?.format;
|
|
861
|
+
if (format === "html") {
|
|
862
|
+
return '<hr style="margin: 24px 0; border: none; border-top: 1px solid #d1d5db;">';
|
|
800
863
|
}
|
|
801
|
-
return
|
|
864
|
+
return '<hr class="my-6 border-t border-border">';
|
|
802
865
|
}
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
|
|
866
|
+
}
|
|
867
|
+
]
|
|
868
|
+
};
|
|
869
|
+
|
|
870
|
+
// src/extensions/core/image.ts
|
|
871
|
+
var ImageExtension = {
|
|
872
|
+
name: "image",
|
|
873
|
+
parseRules: [
|
|
874
|
+
{
|
|
875
|
+
name: "image",
|
|
876
|
+
pattern: /!\[([^\]]*)\]\(([^)]+?)(?:\s+"([^"]+)")?\)/,
|
|
877
|
+
render: (match) => ({
|
|
878
|
+
type: "image",
|
|
879
|
+
content: match[1] || "",
|
|
880
|
+
raw: match[0] || "",
|
|
881
|
+
attributes: {
|
|
882
|
+
alt: match[1] || "",
|
|
883
|
+
src: match[2] || "",
|
|
884
|
+
title: match[3] || ""
|
|
885
|
+
}
|
|
886
|
+
})
|
|
887
|
+
}
|
|
888
|
+
],
|
|
889
|
+
renderRules: [
|
|
890
|
+
{
|
|
891
|
+
type: "image",
|
|
806
892
|
render: (token) => {
|
|
807
|
-
const
|
|
808
|
-
const
|
|
809
|
-
|
|
810
|
-
|
|
893
|
+
const src = token.attributes?.src || "";
|
|
894
|
+
const alt = token.attributes?.alt || "";
|
|
895
|
+
const title = token.attributes?.title || "";
|
|
896
|
+
const titleAttr = title ? ` title="${escapeHtml(title)}"` : "";
|
|
897
|
+
const format = token.attributes?.format || "html";
|
|
898
|
+
if (format === "html") {
|
|
899
|
+
return `<img src="${escapeHtml(src)}" alt="${escapeHtml(alt)}"${titleAttr} style="max-width: 100%; height: auto; border-radius: 8px; margin: 16px 0;" loading="lazy" />`;
|
|
811
900
|
}
|
|
812
|
-
return `<
|
|
901
|
+
return `<img src="${escapeHtml(src)}" alt="${escapeHtml(alt)}"${titleAttr} class="max-w-full h-auto rounded-lg my-4" loading="lazy" />`;
|
|
813
902
|
}
|
|
814
|
-
}
|
|
815
|
-
|
|
903
|
+
}
|
|
904
|
+
]
|
|
905
|
+
};
|
|
906
|
+
|
|
907
|
+
// src/extensions/core/links.ts
|
|
908
|
+
var LinkExtension = {
|
|
909
|
+
name: "link",
|
|
910
|
+
parseRules: [
|
|
911
|
+
{
|
|
912
|
+
name: "link",
|
|
913
|
+
pattern: /\[(?!(?:button|embed):)([^\]]+)\]\(([^)]+)\)/,
|
|
914
|
+
render: (match) => ({
|
|
915
|
+
type: "link",
|
|
916
|
+
content: match[1] || "",
|
|
917
|
+
raw: match[0] || "",
|
|
918
|
+
attributes: {
|
|
919
|
+
href: match[2] || ""
|
|
920
|
+
}
|
|
921
|
+
})
|
|
922
|
+
}
|
|
923
|
+
],
|
|
924
|
+
renderRules: [
|
|
925
|
+
{
|
|
816
926
|
type: "link",
|
|
817
927
|
render: (token) => {
|
|
818
928
|
const href = token.attributes?.href || "#";
|
|
819
929
|
const escapedHref = escapeHtml(href);
|
|
820
930
|
const escapedText = escapeHtml(token.content);
|
|
821
|
-
|
|
931
|
+
const format = token.attributes?.format || "html";
|
|
932
|
+
if (format === "html") {
|
|
822
933
|
return `<a href="${escapedHref}" target="_blank" rel="noopener noreferrer">${escapedText}</a>`;
|
|
823
934
|
}
|
|
824
935
|
return `<a href="${escapedHref}" class="text-primary hover:underline inline-flex items-center gap-1" target="_blank" rel="noopener noreferrer">
|
|
@@ -830,47 +941,55 @@ var MarkdownRenderer = class {
|
|
|
830
941
|
</svg>
|
|
831
942
|
</a>`;
|
|
832
943
|
}
|
|
833
|
-
}
|
|
834
|
-
|
|
944
|
+
}
|
|
945
|
+
]
|
|
946
|
+
};
|
|
947
|
+
|
|
948
|
+
// src/extensions/core/lists.ts
|
|
949
|
+
var ListExtension = {
|
|
950
|
+
name: "list",
|
|
951
|
+
parseRules: [
|
|
952
|
+
{
|
|
953
|
+
name: "list-item",
|
|
954
|
+
pattern: /^(\s*)[-*+]\s+(.+)$/m,
|
|
955
|
+
render: (match) => ({
|
|
956
|
+
type: "list-item",
|
|
957
|
+
content: match[2] || "",
|
|
958
|
+
raw: match[0] || ""
|
|
959
|
+
})
|
|
960
|
+
}
|
|
961
|
+
],
|
|
962
|
+
renderRules: [
|
|
963
|
+
{
|
|
835
964
|
type: "list-item",
|
|
836
965
|
render: (token) => `<li>${escapeHtml(token.content)}</li>`
|
|
837
|
-
}
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
return escapeHtml(token.content);
|
|
853
|
-
}
|
|
854
|
-
});
|
|
855
|
-
this.addRule({
|
|
856
|
-
type: "paragraph",
|
|
857
|
-
render: (token) => {
|
|
858
|
-
if (!token.content) return "";
|
|
859
|
-
const content = token.content.trim();
|
|
860
|
-
if (!content) return "";
|
|
861
|
-
const processedContent = content.includes("<br>") ? content : escapeHtml(content);
|
|
862
|
-
if (this.config.format === "html") {
|
|
863
|
-
return `<p style="line-height: 1.75; margin-bottom: 16px;">${processedContent}</p>`;
|
|
966
|
+
}
|
|
967
|
+
]
|
|
968
|
+
};
|
|
969
|
+
var TaskListExtension = {
|
|
970
|
+
name: "task-list",
|
|
971
|
+
parseRules: [
|
|
972
|
+
{
|
|
973
|
+
name: "task-item",
|
|
974
|
+
pattern: /^(\s*)-\s*\[([ xX])\]\s*(.+)$/m,
|
|
975
|
+
render: (match) => ({
|
|
976
|
+
type: "task-item",
|
|
977
|
+
content: match[3] || "",
|
|
978
|
+
raw: match[0] || "",
|
|
979
|
+
attributes: {
|
|
980
|
+
checked: String((match[2] || "").toLowerCase() === "x")
|
|
864
981
|
}
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
982
|
+
})
|
|
983
|
+
}
|
|
984
|
+
],
|
|
985
|
+
renderRules: [
|
|
986
|
+
{
|
|
869
987
|
type: "task-item",
|
|
870
988
|
render: (token) => {
|
|
871
989
|
const isChecked = token.attributes?.checked === "true";
|
|
872
990
|
const escapedContent = escapeHtml(token.content);
|
|
873
|
-
|
|
991
|
+
const format = token.attributes?.format || "html";
|
|
992
|
+
if (format === "html") {
|
|
874
993
|
return `<div style="display: flex; align-items: center; gap: 8px; margin: 8px 0;">
|
|
875
994
|
<input type="checkbox" ${isChecked ? "checked" : ""} disabled style="margin: 0;" />
|
|
876
995
|
<span${isChecked ? ' style="text-decoration: line-through; color: #6b7280;"' : ""}>${escapedContent}</span>
|
|
@@ -882,44 +1001,65 @@ var MarkdownRenderer = class {
|
|
|
882
1001
|
<span${isChecked ? ' class="line-through text-muted-foreground"' : ""}>${escapedContent}</span>
|
|
883
1002
|
</div>`;
|
|
884
1003
|
}
|
|
885
|
-
}
|
|
886
|
-
|
|
887
|
-
|
|
1004
|
+
}
|
|
1005
|
+
]
|
|
1006
|
+
};
|
|
1007
|
+
|
|
1008
|
+
// src/extensions/core/paragraph.ts
|
|
1009
|
+
var ParagraphExtension = {
|
|
1010
|
+
name: "paragraph",
|
|
1011
|
+
parseRules: [],
|
|
1012
|
+
renderRules: [
|
|
1013
|
+
{
|
|
1014
|
+
type: "paragraph",
|
|
888
1015
|
render: (token) => {
|
|
889
|
-
|
|
890
|
-
const
|
|
891
|
-
|
|
892
|
-
const
|
|
893
|
-
|
|
894
|
-
|
|
1016
|
+
if (!token.content) return "";
|
|
1017
|
+
const content = token.content.trim();
|
|
1018
|
+
if (!content) return "";
|
|
1019
|
+
const processedContent = content.includes("<br>") ? content : escapeHtml(content);
|
|
1020
|
+
const format = token.attributes?.format || "html";
|
|
1021
|
+
if (format === "html") {
|
|
1022
|
+
return `<p style="line-height: 1.75; margin-bottom: 16px;">${processedContent}</p>`;
|
|
895
1023
|
}
|
|
896
|
-
return `<
|
|
1024
|
+
return `<p class="leading-7 mb-4">${processedContent}</p>`;
|
|
897
1025
|
}
|
|
898
|
-
}
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
1026
|
+
}
|
|
1027
|
+
]
|
|
1028
|
+
};
|
|
1029
|
+
|
|
1030
|
+
// src/extensions/core/text.ts
|
|
1031
|
+
var TextExtension = {
|
|
1032
|
+
name: "text",
|
|
1033
|
+
parseRules: [],
|
|
1034
|
+
renderRules: [
|
|
1035
|
+
{
|
|
1036
|
+
type: "text",
|
|
1037
|
+
render: (token) => {
|
|
1038
|
+
if (!token.content) return "";
|
|
1039
|
+
return escapeHtml(token.content);
|
|
906
1040
|
}
|
|
907
|
-
}
|
|
908
|
-
|
|
909
|
-
type: "line-break",
|
|
910
|
-
render: () => "<br>"
|
|
911
|
-
});
|
|
912
|
-
this.addRule({
|
|
913
|
-
type: "paragraph-break",
|
|
914
|
-
render: () => "</p><p>"
|
|
915
|
-
});
|
|
916
|
-
this.addRule({
|
|
917
|
-
type: "soft-break",
|
|
918
|
-
render: (token) => token.content || " "
|
|
919
|
-
});
|
|
920
|
-
}
|
|
1041
|
+
}
|
|
1042
|
+
]
|
|
921
1043
|
};
|
|
922
1044
|
|
|
1045
|
+
// src/extensions/core/index.ts
|
|
1046
|
+
var CoreExtensions = [
|
|
1047
|
+
TextExtension,
|
|
1048
|
+
HeadingExtension,
|
|
1049
|
+
BoldExtension,
|
|
1050
|
+
ItalicExtension,
|
|
1051
|
+
InlineCodeExtension,
|
|
1052
|
+
CodeBlockExtension,
|
|
1053
|
+
LinkExtension,
|
|
1054
|
+
ImageExtension,
|
|
1055
|
+
ListExtension,
|
|
1056
|
+
TaskListExtension,
|
|
1057
|
+
BlockquoteExtension,
|
|
1058
|
+
HorizontalRuleExtension,
|
|
1059
|
+
ParagraphExtension,
|
|
1060
|
+
LineBreakExtension
|
|
1061
|
+
];
|
|
1062
|
+
|
|
923
1063
|
// src/extensions/alert.ts
|
|
924
1064
|
var AlertExtension = {
|
|
925
1065
|
name: "alert",
|
|
@@ -999,26 +1139,19 @@ var ButtonExtension = {
|
|
|
999
1139
|
name: "button",
|
|
1000
1140
|
pattern: /\[button:([^\]]+)\]\(([^)]+)\)(?:\{([^}]+)\})?/,
|
|
1001
1141
|
render: (match) => {
|
|
1002
|
-
const
|
|
1003
|
-
const href = match[2] || "";
|
|
1004
|
-
const optionsString = match[3] || "";
|
|
1005
|
-
const options = optionsString.split(",").map((opt) => opt.trim()).filter(Boolean);
|
|
1006
|
-
const styleOptions = ["default", "primary", "secondary", "success", "danger", "outline", "ghost"];
|
|
1007
|
-
const style = options.find((opt) => styleOptions.includes(opt)) || "primary";
|
|
1008
|
-
const sizeOptions = ["sm", "md", "lg"];
|
|
1009
|
-
const size = options.find((opt) => sizeOptions.includes(opt)) || "md";
|
|
1010
|
-
const disabled = options.includes("disabled");
|
|
1011
|
-
const target = options.includes("self") ? "_self" : "_blank";
|
|
1142
|
+
const options = match[3] ? match[3].split(",").map((opt) => opt.trim()) : [];
|
|
1012
1143
|
return {
|
|
1013
1144
|
type: "button",
|
|
1014
|
-
content:
|
|
1145
|
+
content: match[1] || "",
|
|
1015
1146
|
raw: match[0] || "",
|
|
1016
1147
|
attributes: {
|
|
1017
|
-
href,
|
|
1018
|
-
style
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1148
|
+
href: match[2] || "",
|
|
1149
|
+
style: options.find(
|
|
1150
|
+
(opt) => ["default", "primary", "secondary", "success", "danger", "outline", "ghost"].includes(opt)
|
|
1151
|
+
) || "primary",
|
|
1152
|
+
size: options.find((opt) => ["sm", "md", "lg"].includes(opt)) || "md",
|
|
1153
|
+
disabled: String(options.includes("disabled")),
|
|
1154
|
+
target: options.includes("self") ? "_self" : "_blank"
|
|
1022
1155
|
}
|
|
1023
1156
|
};
|
|
1024
1157
|
}
|
|
@@ -1033,53 +1166,92 @@ var ButtonExtension = {
|
|
|
1033
1166
|
const size = token.attributes?.size || "md";
|
|
1034
1167
|
const disabled = token.attributes?.disabled === "true";
|
|
1035
1168
|
const target = token.attributes?.target || "_blank";
|
|
1036
|
-
const
|
|
1037
|
-
|
|
1169
|
+
const baseClasses = `
|
|
1170
|
+
inline-flex items-center justify-center font-medium rounded-lg
|
|
1171
|
+
transition-all duration-200 ease-out
|
|
1172
|
+
focus:outline-none focus:ring-2 focus:ring-offset-2
|
|
1173
|
+
disabled:opacity-50 disabled:cursor-not-allowed disabled:pointer-events-none
|
|
1174
|
+
transform hover:scale-[1.02] active:scale-[0.98]
|
|
1175
|
+
shadow-sm hover:shadow-md active:shadow-sm
|
|
1176
|
+
border border-transparent
|
|
1177
|
+
relative overflow-hidden
|
|
1178
|
+
before:absolute before:inset-0 before:rounded-lg
|
|
1179
|
+
before:bg-gradient-to-br before:from-white/20 before:to-transparent
|
|
1180
|
+
before:opacity-0 hover:before:opacity-100 before:transition-opacity before:duration-200
|
|
1181
|
+
`.replace(/\s+/g, " ").trim();
|
|
1182
|
+
const sizeClasses = {
|
|
1183
|
+
sm: "px-3 py-1.5 text-sm gap-1.5",
|
|
1184
|
+
md: "px-4 py-2 text-base gap-2",
|
|
1185
|
+
lg: "px-6 py-3 text-lg gap-2.5"
|
|
1186
|
+
};
|
|
1187
|
+
const styleClasses = {
|
|
1188
|
+
default: `
|
|
1189
|
+
bg-slate-600 text-white border-slate-500
|
|
1190
|
+
hover:bg-slate-700 hover:border-slate-400
|
|
1191
|
+
focus:ring-slate-500
|
|
1192
|
+
shadow-[0_1px_0_0_rgba(255,255,255,0.1)_inset,0_1px_2px_0_rgba(0,0,0,0.1)]
|
|
1193
|
+
hover:shadow-[0_1px_0_0_rgba(255,255,255,0.15)_inset,0_2px_4px_0_rgba(0,0,0,0.15)]
|
|
1194
|
+
`,
|
|
1195
|
+
primary: `
|
|
1196
|
+
bg-blue-600 text-white border-blue-500
|
|
1197
|
+
hover:bg-blue-700 hover:border-blue-400
|
|
1198
|
+
focus:ring-blue-500
|
|
1199
|
+
shadow-[0_1px_0_0_rgba(255,255,255,0.1)_inset,0_1px_2px_0_rgba(0,0,0,0.1)]
|
|
1200
|
+
hover:shadow-[0_1px_0_0_rgba(255,255,255,0.15)_inset,0_2px_4px_0_rgba(0,0,0,0.15)]
|
|
1201
|
+
`,
|
|
1202
|
+
secondary: `
|
|
1203
|
+
bg-gray-600 text-white border-gray-500
|
|
1204
|
+
hover:bg-gray-700 hover:border-gray-400
|
|
1205
|
+
focus:ring-gray-500
|
|
1206
|
+
shadow-[0_1px_0_0_rgba(255,255,255,0.1)_inset,0_1px_2px_0_rgba(0,0,0,0.1)]
|
|
1207
|
+
hover:shadow-[0_1px_0_0_rgba(255,255,255,0.15)_inset,0_2px_4px_0_rgba(0,0,0,0.15)]
|
|
1208
|
+
`,
|
|
1209
|
+
success: `
|
|
1210
|
+
bg-green-600 text-white border-green-500
|
|
1211
|
+
hover:bg-green-700 hover:border-green-400
|
|
1212
|
+
focus:ring-green-500
|
|
1213
|
+
shadow-[0_1px_0_0_rgba(255,255,255,0.1)_inset,0_1px_2px_0_rgba(0,0,0,0.1)]
|
|
1214
|
+
hover:shadow-[0_1px_0_0_rgba(255,255,255,0.15)_inset,0_2px_4px_0_rgba(0,0,0,0.15)]
|
|
1215
|
+
`,
|
|
1216
|
+
danger: `
|
|
1217
|
+
bg-red-600 text-white border-red-500
|
|
1218
|
+
hover:bg-red-700 hover:border-red-400
|
|
1219
|
+
focus:ring-red-500
|
|
1220
|
+
shadow-[0_1px_0_0_rgba(255,255,255,0.1)_inset,0_1px_2px_0_rgba(0,0,0,0.1)]
|
|
1221
|
+
hover:shadow-[0_1px_0_0_rgba(255,255,255,0.15)_inset,0_2px_4px_0_rgba(0,0,0,0.15)]
|
|
1222
|
+
`,
|
|
1223
|
+
outline: `
|
|
1224
|
+
bg-transparent text-blue-600 border-blue-600
|
|
1225
|
+
hover:bg-blue-50 hover:border-blue-700 hover:text-blue-700
|
|
1226
|
+
focus:ring-blue-500
|
|
1227
|
+
shadow-[0_0_0_1px_rgba(59,130,246,0.5)_inset]
|
|
1228
|
+
hover:shadow-[0_0_0_1px_rgba(29,78,216,0.6)_inset,0_1px_2px_0_rgba(0,0,0,0.05)]
|
|
1229
|
+
`,
|
|
1230
|
+
ghost: `
|
|
1231
|
+
bg-transparent text-gray-700 border-transparent
|
|
1232
|
+
hover:bg-gray-100 hover:text-gray-900
|
|
1233
|
+
focus:ring-gray-500
|
|
1234
|
+
shadow-none
|
|
1235
|
+
hover:shadow-[0_1px_2px_0_rgba(0,0,0,0.05)]
|
|
1236
|
+
`
|
|
1237
|
+
};
|
|
1238
|
+
const classes = `
|
|
1239
|
+
${baseClasses}
|
|
1240
|
+
${sizeClasses[size] || sizeClasses.md}
|
|
1241
|
+
${styleClasses[style] || styleClasses.primary}
|
|
1242
|
+
`.replace(/\s+/g, " ").trim();
|
|
1038
1243
|
const targetAttr = target === "_blank" ? ' target="_blank" rel="noopener noreferrer"' : target === "_self" ? ' target="_self"' : "";
|
|
1039
1244
|
const disabledAttr = disabled ? ' aria-disabled="true" tabindex="-1"' : "";
|
|
1040
|
-
const externalIcon = target === "_blank" && !disabled ?
|
|
1245
|
+
const externalIcon = target === "_blank" && !disabled ? `<svg class="w-4 h-4 ml-1 opacity-75" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
1246
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"/>
|
|
1247
|
+
</svg>` : "";
|
|
1041
1248
|
return `<a href="${href}" class="${classes}"${targetAttr}${disabledAttr}>
|
|
1042
|
-
|
|
1043
|
-
|
|
1249
|
+
<span class="relative z-10">${token.content}</span>${externalIcon}
|
|
1250
|
+
</a>`;
|
|
1044
1251
|
}
|
|
1045
1252
|
}
|
|
1046
1253
|
]
|
|
1047
1254
|
};
|
|
1048
|
-
function buildButtonClasses(style, size) {
|
|
1049
|
-
const base = [
|
|
1050
|
-
"inline-flex",
|
|
1051
|
-
"items-center",
|
|
1052
|
-
"justify-center",
|
|
1053
|
-
"font-medium",
|
|
1054
|
-
"rounded-lg",
|
|
1055
|
-
"transition-colors",
|
|
1056
|
-
"focus:outline-none",
|
|
1057
|
-
"focus:ring-2",
|
|
1058
|
-
"focus:ring-offset-2",
|
|
1059
|
-
"disabled:opacity-50",
|
|
1060
|
-
"disabled:cursor-not-allowed"
|
|
1061
|
-
];
|
|
1062
|
-
const sizes = {
|
|
1063
|
-
sm: ["px-3", "py-1.5", "text-sm"],
|
|
1064
|
-
md: ["px-4", "py-2", "text-base"],
|
|
1065
|
-
lg: ["px-6", "py-3", "text-lg"]
|
|
1066
|
-
};
|
|
1067
|
-
const styles = {
|
|
1068
|
-
default: ["bg-slate-600", "text-white", "hover:bg-slate-700", "focus:ring-slate-500"],
|
|
1069
|
-
primary: ["bg-blue-600", "text-white", "hover:bg-blue-700", "focus:ring-blue-500"],
|
|
1070
|
-
secondary: ["bg-gray-600", "text-white", "hover:bg-gray-700", "focus:ring-gray-500"],
|
|
1071
|
-
success: ["bg-green-600", "text-white", "hover:bg-green-700", "focus:ring-green-500"],
|
|
1072
|
-
danger: ["bg-red-600", "text-white", "hover:bg-red-700", "focus:ring-red-500"],
|
|
1073
|
-
outline: ["border", "border-blue-600", "text-blue-600", "hover:bg-blue-50", "focus:ring-blue-500"],
|
|
1074
|
-
ghost: ["text-gray-700", "hover:bg-gray-100", "focus:ring-gray-500"]
|
|
1075
|
-
};
|
|
1076
|
-
const allClasses = [
|
|
1077
|
-
...base,
|
|
1078
|
-
...sizes[size] ?? sizes.md ?? [],
|
|
1079
|
-
...styles[style] ?? styles.primary ?? []
|
|
1080
|
-
];
|
|
1081
|
-
return allClasses.join(" ");
|
|
1082
|
-
}
|
|
1083
1255
|
|
|
1084
1256
|
// src/extensions/embed.ts
|
|
1085
1257
|
var EmbedExtension = {
|
|
@@ -1157,8 +1329,7 @@ function renderYouTubeEmbed(url, options, classes) {
|
|
|
1157
1329
|
params.set("rel", "0");
|
|
1158
1330
|
params.set("modestbranding", "1");
|
|
1159
1331
|
const embedUrl = `https://www.youtube.com/embed/${videoId}?${params.toString()}`;
|
|
1160
|
-
return
|
|
1161
|
-
<div class="${classes}">
|
|
1332
|
+
return `<div class="${classes}">
|
|
1162
1333
|
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
|
|
1163
1334
|
<iframe
|
|
1164
1335
|
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0;"
|
|
@@ -1186,8 +1357,7 @@ function renderCodePenEmbed(url, options, classes) {
|
|
|
1186
1357
|
"editable": "true"
|
|
1187
1358
|
});
|
|
1188
1359
|
const embedUrl = `https://codepen.io/${user}/embed/${penId}?${embedParams.toString()}`;
|
|
1189
|
-
return
|
|
1190
|
-
<div class="${classes}">
|
|
1360
|
+
return `<div class="${classes}">
|
|
1191
1361
|
<iframe
|
|
1192
1362
|
height="${height}"
|
|
1193
1363
|
style="width: 100%; border: 0;"
|
|
@@ -1211,8 +1381,7 @@ function renderVimeoEmbed(url, options, classes) {
|
|
|
1211
1381
|
if (options.mute === "1") params.set("muted", "1");
|
|
1212
1382
|
if (options.loop === "1") params.set("loop", "1");
|
|
1213
1383
|
const embedUrl = `https://player.vimeo.com/video/${videoId}?${params.toString()}`;
|
|
1214
|
-
return
|
|
1215
|
-
<div class="${classes}">
|
|
1384
|
+
return `<div class="${classes}">
|
|
1216
1385
|
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
|
|
1217
1386
|
<iframe
|
|
1218
1387
|
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0;"
|
|
@@ -1228,8 +1397,7 @@ function renderVimeoEmbed(url, options, classes) {
|
|
|
1228
1397
|
function renderSpotifyEmbed(url, options, classes) {
|
|
1229
1398
|
const embedUrl = url.replace("open.spotify.com", "open.spotify.com/embed");
|
|
1230
1399
|
const height = options.height || "380";
|
|
1231
|
-
return
|
|
1232
|
-
<div class="${classes}">
|
|
1400
|
+
return `<div class="${classes}">
|
|
1233
1401
|
<iframe
|
|
1234
1402
|
style="border-radius: 12px;"
|
|
1235
1403
|
src="${embedUrl}"
|
|
@@ -1252,8 +1420,7 @@ function renderCodeSandboxEmbed(url, options, classes) {
|
|
|
1252
1420
|
if (!embedUrl.includes("?")) {
|
|
1253
1421
|
embedUrl += `?view=${view}`;
|
|
1254
1422
|
}
|
|
1255
|
-
return
|
|
1256
|
-
<div class="${classes}">
|
|
1423
|
+
return `<div class="${classes}">
|
|
1257
1424
|
<iframe
|
|
1258
1425
|
src="${embedUrl}"
|
|
1259
1426
|
style="width: 100%; height: ${height}px; border: 0; border-radius: 4px; overflow: hidden;"
|
|
@@ -1266,8 +1433,7 @@ function renderCodeSandboxEmbed(url, options, classes) {
|
|
|
1266
1433
|
function renderFigmaEmbed(url, options, classes) {
|
|
1267
1434
|
const embedUrl = `https://www.figma.com/embed?embed_host=share&url=${encodeURIComponent(url)}`;
|
|
1268
1435
|
const height = options.height || "450";
|
|
1269
|
-
return
|
|
1270
|
-
<div class="${classes}">
|
|
1436
|
+
return `<div class="${classes}">
|
|
1271
1437
|
<iframe
|
|
1272
1438
|
style="border: none;"
|
|
1273
1439
|
width="100%"
|
|
@@ -1278,8 +1444,7 @@ function renderFigmaEmbed(url, options, classes) {
|
|
|
1278
1444
|
</div>`;
|
|
1279
1445
|
}
|
|
1280
1446
|
function renderTwitterEmbed(url, _options, classes) {
|
|
1281
|
-
return
|
|
1282
|
-
<div class="${classes}">
|
|
1447
|
+
return `<div class="${classes}">
|
|
1283
1448
|
<div class="p-4">
|
|
1284
1449
|
<div class="flex items-center gap-3 mb-3">
|
|
1285
1450
|
<svg class="w-6 h-6 fill-current text-blue-500" viewBox="0 0 24 24">
|
|
@@ -1307,8 +1472,7 @@ function renderGitHubEmbed(url, _options, classes) {
|
|
|
1307
1472
|
if (!owner || !repo) {
|
|
1308
1473
|
return createErrorEmbed("Invalid GitHub URL", url, classes);
|
|
1309
1474
|
}
|
|
1310
|
-
return
|
|
1311
|
-
<div class="${classes}">
|
|
1475
|
+
return `<div class="${classes}">
|
|
1312
1476
|
<div class="p-4">
|
|
1313
1477
|
<div class="flex items-center gap-3 mb-3">
|
|
1314
1478
|
<svg class="w-6 h-6 fill-current" viewBox="0 0 24 24">
|
|
@@ -1331,8 +1495,7 @@ function renderGitHubEmbed(url, _options, classes) {
|
|
|
1331
1495
|
}
|
|
1332
1496
|
function renderGenericEmbed(url, _options, classes) {
|
|
1333
1497
|
const domain = extractDomain(url);
|
|
1334
|
-
return
|
|
1335
|
-
<div class="${classes}">
|
|
1498
|
+
return `<div class="${classes}">
|
|
1336
1499
|
<div class="p-4">
|
|
1337
1500
|
<div class="flex items-center gap-3 mb-3">
|
|
1338
1501
|
<div class="w-10 h-10 rounded-lg bg-muted flex items-center justify-center">
|
|
@@ -1356,8 +1519,7 @@ function renderGenericEmbed(url, _options, classes) {
|
|
|
1356
1519
|
</div>`;
|
|
1357
1520
|
}
|
|
1358
1521
|
function createErrorEmbed(error, url, classes) {
|
|
1359
|
-
return
|
|
1360
|
-
<div class="${classes}">
|
|
1522
|
+
return `<div class="${classes}">
|
|
1361
1523
|
<div class="p-4 text-destructive">
|
|
1362
1524
|
<div class="font-medium flex items-center gap-2">
|
|
1363
1525
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
@@ -1391,19 +1553,54 @@ var ChangerawrMarkdown = class {
|
|
|
1391
1553
|
this.extensions = /* @__PURE__ */ new Map();
|
|
1392
1554
|
this.parser = new MarkdownParser(config?.parser);
|
|
1393
1555
|
this.renderer = new MarkdownRenderer(config?.renderer);
|
|
1394
|
-
this.
|
|
1556
|
+
this.registerCoreExtensions();
|
|
1557
|
+
this.registerFeatureExtensions();
|
|
1395
1558
|
if (config?.extensions) {
|
|
1396
1559
|
config.extensions.forEach((extension) => {
|
|
1397
1560
|
this.registerExtension(extension);
|
|
1398
1561
|
});
|
|
1399
1562
|
}
|
|
1400
|
-
this.parser.setupDefaultRulesIfEmpty();
|
|
1401
1563
|
}
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1564
|
+
registerFeatureExtensions() {
|
|
1565
|
+
this.registerExtension(AlertExtension);
|
|
1566
|
+
this.registerExtension(ButtonExtension);
|
|
1567
|
+
this.registerExtension(EmbedExtension);
|
|
1568
|
+
}
|
|
1569
|
+
registerCoreExtensions() {
|
|
1570
|
+
CoreExtensions.forEach((extension) => {
|
|
1571
|
+
this.registerExtension(extension);
|
|
1572
|
+
});
|
|
1573
|
+
}
|
|
1405
1574
|
registerExtension(extension) {
|
|
1406
1575
|
try {
|
|
1576
|
+
if (!extension.name || typeof extension.name !== "string") {
|
|
1577
|
+
throw new Error("Extension must have a valid name");
|
|
1578
|
+
}
|
|
1579
|
+
if (!Array.isArray(extension.parseRules)) {
|
|
1580
|
+
throw new Error("Extension must have parseRules array");
|
|
1581
|
+
}
|
|
1582
|
+
if (!Array.isArray(extension.renderRules)) {
|
|
1583
|
+
throw new Error("Extension must have renderRules array");
|
|
1584
|
+
}
|
|
1585
|
+
extension.parseRules.forEach((rule, index) => {
|
|
1586
|
+
if (!rule.name || typeof rule.name !== "string") {
|
|
1587
|
+
throw new Error(`Parse rule ${index} must have a valid name`);
|
|
1588
|
+
}
|
|
1589
|
+
if (!rule.pattern || !(rule.pattern instanceof RegExp)) {
|
|
1590
|
+
throw new Error(`Parse rule ${index} must have a valid RegExp pattern`);
|
|
1591
|
+
}
|
|
1592
|
+
if (!rule.render || typeof rule.render !== "function") {
|
|
1593
|
+
throw new Error(`Parse rule ${index} must have a valid render function`);
|
|
1594
|
+
}
|
|
1595
|
+
});
|
|
1596
|
+
extension.renderRules.forEach((rule, index) => {
|
|
1597
|
+
if (!rule.type || typeof rule.type !== "string") {
|
|
1598
|
+
throw new Error(`Render rule ${index} must have a valid type`);
|
|
1599
|
+
}
|
|
1600
|
+
if (!rule.render || typeof rule.render !== "function") {
|
|
1601
|
+
throw new Error(`Render rule ${index} must have a valid render function`);
|
|
1602
|
+
}
|
|
1603
|
+
});
|
|
1407
1604
|
this.extensions.set(extension.name, extension);
|
|
1408
1605
|
extension.parseRules.forEach((rule) => {
|
|
1409
1606
|
this.parser.addRule(rule);
|
|
@@ -1424,9 +1621,6 @@ var ChangerawrMarkdown = class {
|
|
|
1424
1621
|
};
|
|
1425
1622
|
}
|
|
1426
1623
|
}
|
|
1427
|
-
/**
|
|
1428
|
-
* Unregister an extension
|
|
1429
|
-
*/
|
|
1430
1624
|
unregisterExtension(name) {
|
|
1431
1625
|
const extension = this.extensions.get(name);
|
|
1432
1626
|
if (!extension) {
|
|
@@ -1440,46 +1634,25 @@ var ChangerawrMarkdown = class {
|
|
|
1440
1634
|
return false;
|
|
1441
1635
|
}
|
|
1442
1636
|
}
|
|
1443
|
-
/**
|
|
1444
|
-
* Parse markdown content into tokens
|
|
1445
|
-
*/
|
|
1446
1637
|
parse(markdown3) {
|
|
1447
1638
|
return this.parser.parse(markdown3);
|
|
1448
1639
|
}
|
|
1449
|
-
/**
|
|
1450
|
-
* Render tokens to HTML
|
|
1451
|
-
*/
|
|
1452
1640
|
render(tokens) {
|
|
1453
1641
|
return this.renderer.render(tokens);
|
|
1454
1642
|
}
|
|
1455
|
-
/**
|
|
1456
|
-
* Parse and render markdown to HTML in one step
|
|
1457
|
-
*/
|
|
1458
1643
|
toHtml(markdown3) {
|
|
1459
1644
|
const tokens = this.parse(markdown3);
|
|
1460
1645
|
return this.render(tokens);
|
|
1461
1646
|
}
|
|
1462
|
-
/**
|
|
1463
|
-
* Get list of registered extensions
|
|
1464
|
-
*/
|
|
1465
1647
|
getExtensions() {
|
|
1466
1648
|
return Array.from(this.extensions.keys());
|
|
1467
1649
|
}
|
|
1468
|
-
/**
|
|
1469
|
-
* Check if extension is registered
|
|
1470
|
-
*/
|
|
1471
1650
|
hasExtension(name) {
|
|
1472
1651
|
return this.extensions.has(name);
|
|
1473
1652
|
}
|
|
1474
|
-
/**
|
|
1475
|
-
* Get parser warnings
|
|
1476
|
-
*/
|
|
1477
1653
|
getWarnings() {
|
|
1478
1654
|
return [...this.parser.getWarnings(), ...this.renderer.getWarnings()];
|
|
1479
1655
|
}
|
|
1480
|
-
/**
|
|
1481
|
-
* Get debug information from last render
|
|
1482
|
-
*/
|
|
1483
1656
|
getDebugInfo() {
|
|
1484
1657
|
return {
|
|
1485
1658
|
warnings: this.getWarnings(),
|
|
@@ -1489,9 +1662,6 @@ var ChangerawrMarkdown = class {
|
|
|
1489
1662
|
iterationCount: 0
|
|
1490
1663
|
};
|
|
1491
1664
|
}
|
|
1492
|
-
/**
|
|
1493
|
-
* Get performance metrics for the last operation
|
|
1494
|
-
*/
|
|
1495
1665
|
getPerformanceMetrics() {
|
|
1496
1666
|
return {
|
|
1497
1667
|
parseTime: 0,
|
|
@@ -1500,28 +1670,29 @@ var ChangerawrMarkdown = class {
|
|
|
1500
1670
|
tokenCount: 0
|
|
1501
1671
|
};
|
|
1502
1672
|
}
|
|
1503
|
-
/**
|
|
1504
|
-
* Register built-in extensions
|
|
1505
|
-
*/
|
|
1506
|
-
registerBuiltInExtensions() {
|
|
1507
|
-
this.registerExtension(AlertExtension);
|
|
1508
|
-
this.registerExtension(ButtonExtension);
|
|
1509
|
-
this.registerExtension(EmbedExtension);
|
|
1510
|
-
}
|
|
1511
|
-
/**
|
|
1512
|
-
* Rebuild parser and renderer with current extensions
|
|
1513
|
-
*/
|
|
1514
1673
|
rebuildParserAndRenderer() {
|
|
1515
1674
|
const parserConfig = this.parser.getConfig();
|
|
1516
1675
|
const rendererConfig = this.renderer.getConfig();
|
|
1517
1676
|
this.parser = new MarkdownParser(parserConfig);
|
|
1518
1677
|
this.renderer = new MarkdownRenderer(rendererConfig);
|
|
1519
1678
|
const extensionsToRegister = Array.from(this.extensions.values());
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1679
|
+
const featureExtensions = extensionsToRegister.filter(
|
|
1680
|
+
(ext) => ["alert", "button", "embed"].includes(ext.name)
|
|
1681
|
+
);
|
|
1682
|
+
const coreExtensions = extensionsToRegister.filter(
|
|
1683
|
+
(ext) => ["text", "heading", "bold", "italic", "code", "codeblock", "link", "image", "list", "task-list", "blockquote", "hr", "paragraph", "line-break"].includes(ext.name)
|
|
1684
|
+
);
|
|
1685
|
+
const customExtensions = extensionsToRegister.filter(
|
|
1686
|
+
(ext) => !["alert", "button", "embed", "text", "heading", "bold", "italic", "code", "codeblock", "link", "image", "list", "task-list", "blockquote", "hr", "paragraph", "line-break"].includes(ext.name)
|
|
1687
|
+
);
|
|
1688
|
+
[...featureExtensions, ...coreExtensions, ...customExtensions].forEach((extension) => {
|
|
1689
|
+
extension.parseRules.forEach((rule) => {
|
|
1690
|
+
this.parser.addRule(rule);
|
|
1691
|
+
});
|
|
1692
|
+
extension.renderRules.forEach((rule) => {
|
|
1693
|
+
this.renderer.addRule(rule);
|
|
1694
|
+
});
|
|
1523
1695
|
});
|
|
1524
|
-
this.parser.setupDefaultRulesIfEmpty();
|
|
1525
1696
|
}
|
|
1526
1697
|
};
|
|
1527
1698
|
var markdown = new ChangerawrMarkdown();
|
|
@@ -1951,8 +2122,7 @@ function createHTMLEngine(config) {
|
|
|
1951
2122
|
renderer: {
|
|
1952
2123
|
format: "html",
|
|
1953
2124
|
sanitize: true,
|
|
1954
|
-
allowUnsafeHtml: false
|
|
1955
|
-
...config?.parser
|
|
2125
|
+
allowUnsafeHtml: false
|
|
1956
2126
|
}
|
|
1957
2127
|
});
|
|
1958
2128
|
}
|
|
@@ -1962,8 +2132,7 @@ function createTailwindEngine(config) {
|
|
|
1962
2132
|
renderer: {
|
|
1963
2133
|
format: "tailwind",
|
|
1964
2134
|
sanitize: true,
|
|
1965
|
-
allowUnsafeHtml: false
|
|
1966
|
-
...config?.parser
|
|
2135
|
+
allowUnsafeHtml: false
|
|
1967
2136
|
}
|
|
1968
2137
|
});
|
|
1969
2138
|
}
|
|
@@ -1982,21 +2151,18 @@ function createDebugEngine(config) {
|
|
|
1982
2151
|
}
|
|
1983
2152
|
});
|
|
1984
2153
|
}
|
|
1985
|
-
function createMinimalEngine(
|
|
1986
|
-
const engine = new ChangerawrMarkdown(
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
if (engine.hasExtension("embed")) {
|
|
1998
|
-
engine.unregisterExtension("embed");
|
|
1999
|
-
}
|
|
2154
|
+
function createMinimalEngine(extensions = []) {
|
|
2155
|
+
const engine = new ChangerawrMarkdown();
|
|
2156
|
+
const defaultExtensions = engine.getExtensions();
|
|
2157
|
+
defaultExtensions.forEach((ext) => engine.unregisterExtension(ext));
|
|
2158
|
+
extensions.forEach((ext) => engine.registerExtension(ext));
|
|
2159
|
+
return engine;
|
|
2160
|
+
}
|
|
2161
|
+
function createCoreOnlyEngine(config) {
|
|
2162
|
+
const engine = new ChangerawrMarkdown(config);
|
|
2163
|
+
engine.unregisterExtension("alert");
|
|
2164
|
+
engine.unregisterExtension("button");
|
|
2165
|
+
engine.unregisterExtension("embed");
|
|
2000
2166
|
return engine;
|
|
2001
2167
|
}
|
|
2002
2168
|
function createCustomEngine(extensions, config) {
|
|
@@ -2020,6 +2186,7 @@ var markdown2 = {
|
|
|
2020
2186
|
createTailwindEngine,
|
|
2021
2187
|
createDebugEngine,
|
|
2022
2188
|
createMinimalEngine,
|
|
2189
|
+
createCoreOnlyEngine,
|
|
2023
2190
|
createCustomEngine,
|
|
2024
2191
|
// Standalone functions
|
|
2025
2192
|
renderCum,
|
|
@@ -2028,6 +2195,24 @@ var markdown2 = {
|
|
|
2028
2195
|
ChangerawrMarkdown,
|
|
2029
2196
|
// Extensions
|
|
2030
2197
|
extensions: {
|
|
2198
|
+
// All core extensions as a bundle
|
|
2199
|
+
core: CoreExtensions,
|
|
2200
|
+
// Individual core extensions
|
|
2201
|
+
Text: TextExtension,
|
|
2202
|
+
Heading: HeadingExtension,
|
|
2203
|
+
Bold: BoldExtension,
|
|
2204
|
+
Italic: ItalicExtension,
|
|
2205
|
+
InlineCode: InlineCodeExtension,
|
|
2206
|
+
CodeBlock: CodeBlockExtension,
|
|
2207
|
+
Link: LinkExtension,
|
|
2208
|
+
Image: ImageExtension,
|
|
2209
|
+
List: ListExtension,
|
|
2210
|
+
TaskList: TaskListExtension,
|
|
2211
|
+
Blockquote: BlockquoteExtension,
|
|
2212
|
+
HorizontalRule: HorizontalRuleExtension,
|
|
2213
|
+
Paragraph: ParagraphExtension,
|
|
2214
|
+
LineBreak: LineBreakExtension,
|
|
2215
|
+
// Feature extensions
|
|
2031
2216
|
Alert: AlertExtension,
|
|
2032
2217
|
Button: ButtonExtension,
|
|
2033
2218
|
Embed: EmbedExtension
|
|
@@ -2088,6 +2273,14 @@ var presets = {
|
|
|
2088
2273
|
sanitize: true
|
|
2089
2274
|
}
|
|
2090
2275
|
},
|
|
2276
|
+
/**
|
|
2277
|
+
* Core-only preset with just markdown basics
|
|
2278
|
+
*/
|
|
2279
|
+
coreOnly: {
|
|
2280
|
+
renderer: {
|
|
2281
|
+
format: "tailwind"
|
|
2282
|
+
}
|
|
2283
|
+
},
|
|
2091
2284
|
/**
|
|
2092
2285
|
* Performance preset with minimal processing
|
|
2093
2286
|
*/
|
|
@@ -2104,6 +2297,9 @@ var presets = {
|
|
|
2104
2297
|
};
|
|
2105
2298
|
function createEngineWithPreset(presetName, additionalConfig) {
|
|
2106
2299
|
const preset = presets[presetName];
|
|
2300
|
+
if (presetName === "coreOnly") {
|
|
2301
|
+
return createCoreOnlyEngine(additionalConfig);
|
|
2302
|
+
}
|
|
2107
2303
|
return new ChangerawrMarkdown({
|
|
2108
2304
|
...preset,
|
|
2109
2305
|
...additionalConfig
|
|
@@ -2111,17 +2307,33 @@ function createEngineWithPreset(presetName, additionalConfig) {
|
|
|
2111
2307
|
}
|
|
2112
2308
|
export {
|
|
2113
2309
|
AlertExtension,
|
|
2310
|
+
BlockquoteExtension,
|
|
2311
|
+
BoldExtension,
|
|
2114
2312
|
ButtonExtension,
|
|
2115
2313
|
ChangerawrMarkdown,
|
|
2314
|
+
CodeBlockExtension,
|
|
2315
|
+
CoreExtensions,
|
|
2116
2316
|
EmbedExtension,
|
|
2317
|
+
HeadingExtension,
|
|
2318
|
+
HorizontalRuleExtension,
|
|
2319
|
+
ImageExtension,
|
|
2320
|
+
InlineCodeExtension,
|
|
2321
|
+
ItalicExtension,
|
|
2322
|
+
LineBreakExtension,
|
|
2323
|
+
LinkExtension,
|
|
2324
|
+
ListExtension,
|
|
2117
2325
|
Logger,
|
|
2118
2326
|
MarkdownParser,
|
|
2119
2327
|
MarkdownRenderer,
|
|
2328
|
+
ParagraphExtension,
|
|
2120
2329
|
PerformanceTimer,
|
|
2330
|
+
TaskListExtension,
|
|
2331
|
+
TextExtension,
|
|
2121
2332
|
astToJSONString,
|
|
2122
2333
|
astToTokens,
|
|
2123
2334
|
basicSanitize,
|
|
2124
2335
|
compareTokens,
|
|
2336
|
+
createCoreOnlyEngine,
|
|
2125
2337
|
createCumEngine,
|
|
2126
2338
|
createCustomEngine,
|
|
2127
2339
|
createDebugEngine,
|