@changerawr/markdown 1.0.5 → 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 +128 -10
- package/dist/index.d.mts +63 -47
- package/dist/index.d.ts +63 -47
- package/dist/index.js +677 -447
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +661 -447
- 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 -431
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +604 -431
- package/dist/react/index.mjs.map +1 -1
- package/dist/standalone.browser.js +610 -435
- 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
|
@@ -3,39 +3,56 @@ var MarkdownParser = class {
|
|
|
3
3
|
constructor(config) {
|
|
4
4
|
this.rules = [];
|
|
5
5
|
this.warnings = [];
|
|
6
|
-
this.config =
|
|
6
|
+
this.config = {
|
|
7
|
+
debugMode: false,
|
|
8
|
+
maxIterations: 1e4,
|
|
9
|
+
validateMarkdown: false,
|
|
10
|
+
...config
|
|
11
|
+
};
|
|
7
12
|
}
|
|
8
13
|
addRule(rule) {
|
|
9
14
|
this.rules.push(rule);
|
|
10
15
|
this.rules.sort((a, b) => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
if (
|
|
14
|
-
if (
|
|
15
|
-
|
|
16
|
-
|
|
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;
|
|
17
32
|
return a.name.localeCompare(b.name);
|
|
18
33
|
});
|
|
19
34
|
}
|
|
20
|
-
setupDefaultRulesIfEmpty() {
|
|
21
|
-
const hasDefaultRules = this.rules.some(
|
|
22
|
-
(rule) => !["alert", "button", "embed"].includes(rule.name)
|
|
23
|
-
);
|
|
24
|
-
if (!hasDefaultRules) {
|
|
25
|
-
this.setupDefaultRules();
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
35
|
hasRule(name) {
|
|
29
36
|
return this.rules.some((rule) => rule.name === name);
|
|
30
37
|
}
|
|
31
38
|
parse(markdown3) {
|
|
32
39
|
this.warnings = [];
|
|
33
|
-
|
|
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
|
+
}
|
|
34
51
|
const processedMarkdown = this.preprocessMarkdown(markdown3);
|
|
35
52
|
const tokens = [];
|
|
36
53
|
let remaining = processedMarkdown;
|
|
37
54
|
let iterationCount = 0;
|
|
38
|
-
const maxIterations = this.config.maxIterations ||
|
|
55
|
+
const maxIterations = this.config.maxIterations || 1e4;
|
|
39
56
|
while (remaining.length > 0 && iterationCount < maxIterations) {
|
|
40
57
|
iterationCount++;
|
|
41
58
|
let matched = false;
|
|
@@ -124,9 +141,6 @@ var MarkdownParser = class {
|
|
|
124
141
|
clearWarnings() {
|
|
125
142
|
this.warnings = [];
|
|
126
143
|
}
|
|
127
|
-
getIterationCount() {
|
|
128
|
-
return 0;
|
|
129
|
-
}
|
|
130
144
|
preprocessMarkdown(markdown3) {
|
|
131
145
|
if (this.config.validateMarkdown) {
|
|
132
146
|
this.validateMarkdown(markdown3);
|
|
@@ -181,161 +195,6 @@ var MarkdownParser = class {
|
|
|
181
195
|
}
|
|
182
196
|
return processed;
|
|
183
197
|
}
|
|
184
|
-
setupDefaultRules() {
|
|
185
|
-
this.addRule({
|
|
186
|
-
name: "heading",
|
|
187
|
-
pattern: /^(#{1,6})\s+(.+)$/m,
|
|
188
|
-
render: (match) => ({
|
|
189
|
-
type: "heading",
|
|
190
|
-
content: match[2]?.trim() || "",
|
|
191
|
-
raw: match[0] || "",
|
|
192
|
-
attributes: {
|
|
193
|
-
level: String(match[1]?.length || 1)
|
|
194
|
-
}
|
|
195
|
-
})
|
|
196
|
-
});
|
|
197
|
-
this.addRule({
|
|
198
|
-
name: "codeblock",
|
|
199
|
-
pattern: /```(\w+)?\s*\n([\s\S]*?)\n```/,
|
|
200
|
-
render: (match) => ({
|
|
201
|
-
type: "codeblock",
|
|
202
|
-
content: match[2] || "",
|
|
203
|
-
raw: match[0] || "",
|
|
204
|
-
attributes: {
|
|
205
|
-
language: match[1] || "text"
|
|
206
|
-
}
|
|
207
|
-
})
|
|
208
|
-
});
|
|
209
|
-
this.addRule({
|
|
210
|
-
name: "hard-break-backslash",
|
|
211
|
-
pattern: /\\\s*\n/,
|
|
212
|
-
render: (match) => ({
|
|
213
|
-
type: "line-break",
|
|
214
|
-
content: "",
|
|
215
|
-
raw: match[0] || ""
|
|
216
|
-
})
|
|
217
|
-
});
|
|
218
|
-
this.addRule({
|
|
219
|
-
name: "hard-break-spaces",
|
|
220
|
-
pattern: / +\n/,
|
|
221
|
-
render: (match) => ({
|
|
222
|
-
type: "line-break",
|
|
223
|
-
content: "",
|
|
224
|
-
raw: match[0] || ""
|
|
225
|
-
})
|
|
226
|
-
});
|
|
227
|
-
this.addRule({
|
|
228
|
-
name: "paragraph-break",
|
|
229
|
-
pattern: /\n\s*\n/,
|
|
230
|
-
render: (match) => ({
|
|
231
|
-
type: "paragraph-break",
|
|
232
|
-
content: "",
|
|
233
|
-
raw: match[0] || ""
|
|
234
|
-
})
|
|
235
|
-
});
|
|
236
|
-
this.addRule({
|
|
237
|
-
name: "bold",
|
|
238
|
-
pattern: /\*\*((?:(?!\*\*).)+)\*\*/,
|
|
239
|
-
render: (match) => ({
|
|
240
|
-
type: "bold",
|
|
241
|
-
content: match[1] || "",
|
|
242
|
-
raw: match[0] || ""
|
|
243
|
-
})
|
|
244
|
-
});
|
|
245
|
-
this.addRule({
|
|
246
|
-
name: "italic",
|
|
247
|
-
pattern: /\*((?:(?!\*).)+)\*/,
|
|
248
|
-
render: (match) => ({
|
|
249
|
-
type: "italic",
|
|
250
|
-
content: match[1] || "",
|
|
251
|
-
raw: match[0] || ""
|
|
252
|
-
})
|
|
253
|
-
});
|
|
254
|
-
this.addRule({
|
|
255
|
-
name: "code",
|
|
256
|
-
pattern: /`([^`]+)`/,
|
|
257
|
-
render: (match) => ({
|
|
258
|
-
type: "code",
|
|
259
|
-
content: match[1] || "",
|
|
260
|
-
raw: match[0] || ""
|
|
261
|
-
})
|
|
262
|
-
});
|
|
263
|
-
this.addRule({
|
|
264
|
-
name: "image",
|
|
265
|
-
pattern: /!\[([^\]]*)\]\(([^)]+?)(?:\s+"([^"]+)")?\)/,
|
|
266
|
-
render: (match) => ({
|
|
267
|
-
type: "image",
|
|
268
|
-
content: match[1] || "",
|
|
269
|
-
raw: match[0] || "",
|
|
270
|
-
attributes: {
|
|
271
|
-
alt: match[1] || "",
|
|
272
|
-
src: match[2] || "",
|
|
273
|
-
title: match[3] || ""
|
|
274
|
-
}
|
|
275
|
-
})
|
|
276
|
-
});
|
|
277
|
-
this.addRule({
|
|
278
|
-
name: "link",
|
|
279
|
-
pattern: /\[([^\]]+)\]\(([^)]+)\)/,
|
|
280
|
-
render: (match) => ({
|
|
281
|
-
type: "link",
|
|
282
|
-
content: match[1] || "",
|
|
283
|
-
raw: match[0] || "",
|
|
284
|
-
attributes: {
|
|
285
|
-
href: match[2] || ""
|
|
286
|
-
}
|
|
287
|
-
})
|
|
288
|
-
});
|
|
289
|
-
this.addRule({
|
|
290
|
-
name: "task-list",
|
|
291
|
-
pattern: /^(\s*)-\s*\[([ xX])\]\s*(.+)$/m,
|
|
292
|
-
render: (match) => ({
|
|
293
|
-
type: "task-item",
|
|
294
|
-
content: match[3] || "",
|
|
295
|
-
raw: match[0] || "",
|
|
296
|
-
attributes: {
|
|
297
|
-
checked: String((match[2] || "").toLowerCase() === "x")
|
|
298
|
-
}
|
|
299
|
-
})
|
|
300
|
-
});
|
|
301
|
-
this.addRule({
|
|
302
|
-
name: "list",
|
|
303
|
-
pattern: /^(\s*)[-*+]\s+(.+)$/m,
|
|
304
|
-
render: (match) => ({
|
|
305
|
-
type: "list-item",
|
|
306
|
-
content: match[2] || "",
|
|
307
|
-
raw: match[0] || ""
|
|
308
|
-
})
|
|
309
|
-
});
|
|
310
|
-
this.addRule({
|
|
311
|
-
name: "blockquote",
|
|
312
|
-
pattern: /^>\s+(.+)$/m,
|
|
313
|
-
render: (match) => ({
|
|
314
|
-
type: "blockquote",
|
|
315
|
-
content: match[1] || "",
|
|
316
|
-
raw: match[0] || ""
|
|
317
|
-
})
|
|
318
|
-
});
|
|
319
|
-
this.addRule({
|
|
320
|
-
name: "hr",
|
|
321
|
-
pattern: /^---$/m,
|
|
322
|
-
render: (match) => ({
|
|
323
|
-
type: "hr",
|
|
324
|
-
content: "",
|
|
325
|
-
raw: match[0] || ""
|
|
326
|
-
})
|
|
327
|
-
});
|
|
328
|
-
this.addRule({
|
|
329
|
-
name: "soft-break",
|
|
330
|
-
pattern: /\n/,
|
|
331
|
-
render: (match) => ({
|
|
332
|
-
type: "soft-break",
|
|
333
|
-
content: " ",
|
|
334
|
-
// Convert to space for inline text
|
|
335
|
-
raw: match[0] || ""
|
|
336
|
-
})
|
|
337
|
-
});
|
|
338
|
-
}
|
|
339
198
|
};
|
|
340
199
|
|
|
341
200
|
// src/utils.ts
|
|
@@ -654,7 +513,6 @@ var MarkdownRenderer = class {
|
|
|
654
513
|
debugMode: false,
|
|
655
514
|
...config
|
|
656
515
|
};
|
|
657
|
-
this.setupDefaultRules();
|
|
658
516
|
}
|
|
659
517
|
addRule(rule) {
|
|
660
518
|
this.rules.set(rule.type, rule);
|
|
@@ -664,28 +522,20 @@ var MarkdownRenderer = class {
|
|
|
664
522
|
}
|
|
665
523
|
render(tokens) {
|
|
666
524
|
this.warnings = [];
|
|
667
|
-
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));
|
|
668
533
|
const combinedHtml = htmlParts.join("");
|
|
669
534
|
if (this.config.sanitize && !this.config.allowUnsafeHtml) {
|
|
670
535
|
return sanitizeHtml(combinedHtml);
|
|
671
536
|
}
|
|
672
537
|
return combinedHtml;
|
|
673
538
|
}
|
|
674
|
-
getWarnings() {
|
|
675
|
-
return [...this.warnings];
|
|
676
|
-
}
|
|
677
|
-
getConfig() {
|
|
678
|
-
return { ...this.config };
|
|
679
|
-
}
|
|
680
|
-
updateConfig(config) {
|
|
681
|
-
this.config = { ...this.config, ...config };
|
|
682
|
-
}
|
|
683
|
-
setDebugMode(enabled) {
|
|
684
|
-
this.config.debugMode = enabled;
|
|
685
|
-
}
|
|
686
|
-
clearWarnings() {
|
|
687
|
-
this.warnings = [];
|
|
688
|
-
}
|
|
689
539
|
renderToken(token) {
|
|
690
540
|
const rule = this.rules.get(token.type);
|
|
691
541
|
if (rule) {
|
|
@@ -697,9 +547,6 @@ var MarkdownRenderer = class {
|
|
|
697
547
|
return this.createErrorBlock(`Render error for ${token.type}: ${errorMessage}`);
|
|
698
548
|
}
|
|
699
549
|
}
|
|
700
|
-
if (token.type === "text") {
|
|
701
|
-
return escapeHtml(token.content || token.raw || "");
|
|
702
|
-
}
|
|
703
550
|
if (this.config.debugMode) {
|
|
704
551
|
return this.createDebugBlock(token);
|
|
705
552
|
}
|
|
@@ -727,15 +574,234 @@ var MarkdownRenderer = class {
|
|
|
727
574
|
<strong>Content:</strong> ${escapeHtml(token.content || token.raw || "")}
|
|
728
575
|
</div>`;
|
|
729
576
|
}
|
|
730
|
-
|
|
731
|
-
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
|
+
{
|
|
732
797
|
type: "heading",
|
|
733
798
|
render: (token) => {
|
|
734
799
|
const level = parseInt(token.attributes?.level || "1");
|
|
735
800
|
const text = token.content;
|
|
736
801
|
const id = generateId(text);
|
|
737
802
|
const escapedContent = escapeHtml(text);
|
|
738
|
-
|
|
803
|
+
const format = token.attributes?.format || "html";
|
|
804
|
+
if (format === "html") {
|
|
739
805
|
return `<h${level} id="${id}">${escapedContent}</h${level}>`;
|
|
740
806
|
}
|
|
741
807
|
let headingClasses = "group relative flex items-center gap-2";
|
|
@@ -762,61 +828,108 @@ var MarkdownRenderer = class {
|
|
|
762
828
|
return `<h${level} id="${id}" class="${headingClasses}">
|
|
763
829
|
${escapedContent}
|
|
764
830
|
<a href="#${id}" class="opacity-0 group-hover:opacity-100 text-muted-foreground transition-opacity">
|
|
765
|
-
<svg width="16" height="16" viewBox="0 0
|
|
766
|
-
|
|
767
|
-
|
|
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>
|
|
768
835
|
</a>
|
|
769
836
|
</h${level}>`;
|
|
770
837
|
}
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
this.addRule({
|
|
793
|
-
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",
|
|
794
859
|
render: (token) => {
|
|
795
|
-
const
|
|
796
|
-
if (
|
|
797
|
-
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;">';
|
|
798
863
|
}
|
|
799
|
-
return
|
|
864
|
+
return '<hr class="my-6 border-t border-border">';
|
|
800
865
|
}
|
|
801
|
-
}
|
|
802
|
-
|
|
803
|
-
|
|
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",
|
|
804
892
|
render: (token) => {
|
|
805
|
-
const
|
|
806
|
-
const
|
|
807
|
-
|
|
808
|
-
|
|
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" />`;
|
|
809
900
|
}
|
|
810
|
-
return `<
|
|
901
|
+
return `<img src="${escapeHtml(src)}" alt="${escapeHtml(alt)}"${titleAttr} class="max-w-full h-auto rounded-lg my-4" loading="lazy" />`;
|
|
811
902
|
}
|
|
812
|
-
}
|
|
813
|
-
|
|
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
|
+
{
|
|
814
926
|
type: "link",
|
|
815
927
|
render: (token) => {
|
|
816
928
|
const href = token.attributes?.href || "#";
|
|
817
929
|
const escapedHref = escapeHtml(href);
|
|
818
930
|
const escapedText = escapeHtml(token.content);
|
|
819
|
-
|
|
931
|
+
const format = token.attributes?.format || "html";
|
|
932
|
+
if (format === "html") {
|
|
820
933
|
return `<a href="${escapedHref}" target="_blank" rel="noopener noreferrer">${escapedText}</a>`;
|
|
821
934
|
}
|
|
822
935
|
return `<a href="${escapedHref}" class="text-primary hover:underline inline-flex items-center gap-1" target="_blank" rel="noopener noreferrer">
|
|
@@ -828,47 +941,55 @@ var MarkdownRenderer = class {
|
|
|
828
941
|
</svg>
|
|
829
942
|
</a>`;
|
|
830
943
|
}
|
|
831
|
-
}
|
|
832
|
-
|
|
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
|
+
{
|
|
833
964
|
type: "list-item",
|
|
834
965
|
render: (token) => `<li>${escapeHtml(token.content)}</li>`
|
|
835
|
-
}
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
return escapeHtml(token.content);
|
|
851
|
-
}
|
|
852
|
-
});
|
|
853
|
-
this.addRule({
|
|
854
|
-
type: "paragraph",
|
|
855
|
-
render: (token) => {
|
|
856
|
-
if (!token.content) return "";
|
|
857
|
-
const content = token.content.trim();
|
|
858
|
-
if (!content) return "";
|
|
859
|
-
const processedContent = content.includes("<br>") ? content : escapeHtml(content);
|
|
860
|
-
if (this.config.format === "html") {
|
|
861
|
-
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")
|
|
862
981
|
}
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
982
|
+
})
|
|
983
|
+
}
|
|
984
|
+
],
|
|
985
|
+
renderRules: [
|
|
986
|
+
{
|
|
867
987
|
type: "task-item",
|
|
868
988
|
render: (token) => {
|
|
869
989
|
const isChecked = token.attributes?.checked === "true";
|
|
870
990
|
const escapedContent = escapeHtml(token.content);
|
|
871
|
-
|
|
991
|
+
const format = token.attributes?.format || "html";
|
|
992
|
+
if (format === "html") {
|
|
872
993
|
return `<div style="display: flex; align-items: center; gap: 8px; margin: 8px 0;">
|
|
873
994
|
<input type="checkbox" ${isChecked ? "checked" : ""} disabled style="margin: 0;" />
|
|
874
995
|
<span${isChecked ? ' style="text-decoration: line-through; color: #6b7280;"' : ""}>${escapedContent}</span>
|
|
@@ -880,44 +1001,65 @@ var MarkdownRenderer = class {
|
|
|
880
1001
|
<span${isChecked ? ' class="line-through text-muted-foreground"' : ""}>${escapedContent}</span>
|
|
881
1002
|
</div>`;
|
|
882
1003
|
}
|
|
883
|
-
}
|
|
884
|
-
|
|
885
|
-
|
|
1004
|
+
}
|
|
1005
|
+
]
|
|
1006
|
+
};
|
|
1007
|
+
|
|
1008
|
+
// src/extensions/core/paragraph.ts
|
|
1009
|
+
var ParagraphExtension = {
|
|
1010
|
+
name: "paragraph",
|
|
1011
|
+
parseRules: [],
|
|
1012
|
+
renderRules: [
|
|
1013
|
+
{
|
|
1014
|
+
type: "paragraph",
|
|
886
1015
|
render: (token) => {
|
|
887
|
-
|
|
888
|
-
const
|
|
889
|
-
|
|
890
|
-
const
|
|
891
|
-
|
|
892
|
-
|
|
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>`;
|
|
893
1023
|
}
|
|
894
|
-
return `<
|
|
1024
|
+
return `<p class="leading-7 mb-4">${processedContent}</p>`;
|
|
895
1025
|
}
|
|
896
|
-
}
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
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);
|
|
904
1040
|
}
|
|
905
|
-
}
|
|
906
|
-
|
|
907
|
-
type: "line-break",
|
|
908
|
-
render: () => "<br>"
|
|
909
|
-
});
|
|
910
|
-
this.addRule({
|
|
911
|
-
type: "paragraph-break",
|
|
912
|
-
render: () => "</p><p>"
|
|
913
|
-
});
|
|
914
|
-
this.addRule({
|
|
915
|
-
type: "soft-break",
|
|
916
|
-
render: (token) => token.content || " "
|
|
917
|
-
});
|
|
918
|
-
}
|
|
1041
|
+
}
|
|
1042
|
+
]
|
|
919
1043
|
};
|
|
920
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
|
+
|
|
921
1063
|
// src/extensions/alert.ts
|
|
922
1064
|
var AlertExtension = {
|
|
923
1065
|
name: "alert",
|
|
@@ -997,26 +1139,19 @@ var ButtonExtension = {
|
|
|
997
1139
|
name: "button",
|
|
998
1140
|
pattern: /\[button:([^\]]+)\]\(([^)]+)\)(?:\{([^}]+)\})?/,
|
|
999
1141
|
render: (match) => {
|
|
1000
|
-
const
|
|
1001
|
-
const href = match[2] || "";
|
|
1002
|
-
const optionsString = match[3] || "";
|
|
1003
|
-
const options = optionsString.split(",").map((opt) => opt.trim()).filter(Boolean);
|
|
1004
|
-
const styleOptions = ["default", "primary", "secondary", "success", "danger", "outline", "ghost"];
|
|
1005
|
-
const style = options.find((opt) => styleOptions.includes(opt)) || "primary";
|
|
1006
|
-
const sizeOptions = ["sm", "md", "lg"];
|
|
1007
|
-
const size = options.find((opt) => sizeOptions.includes(opt)) || "md";
|
|
1008
|
-
const disabled = options.includes("disabled");
|
|
1009
|
-
const target = options.includes("self") ? "_self" : "_blank";
|
|
1142
|
+
const options = match[3] ? match[3].split(",").map((opt) => opt.trim()) : [];
|
|
1010
1143
|
return {
|
|
1011
1144
|
type: "button",
|
|
1012
|
-
content:
|
|
1145
|
+
content: match[1] || "",
|
|
1013
1146
|
raw: match[0] || "",
|
|
1014
1147
|
attributes: {
|
|
1015
|
-
href,
|
|
1016
|
-
style
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
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"
|
|
1020
1155
|
}
|
|
1021
1156
|
};
|
|
1022
1157
|
}
|
|
@@ -1031,53 +1166,92 @@ var ButtonExtension = {
|
|
|
1031
1166
|
const size = token.attributes?.size || "md";
|
|
1032
1167
|
const disabled = token.attributes?.disabled === "true";
|
|
1033
1168
|
const target = token.attributes?.target || "_blank";
|
|
1034
|
-
const
|
|
1035
|
-
|
|
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();
|
|
1036
1243
|
const targetAttr = target === "_blank" ? ' target="_blank" rel="noopener noreferrer"' : target === "_self" ? ' target="_self"' : "";
|
|
1037
1244
|
const disabledAttr = disabled ? ' aria-disabled="true" tabindex="-1"' : "";
|
|
1038
|
-
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>` : "";
|
|
1039
1248
|
return `<a href="${href}" class="${classes}"${targetAttr}${disabledAttr}>
|
|
1040
|
-
|
|
1041
|
-
|
|
1249
|
+
<span class="relative z-10">${token.content}</span>${externalIcon}
|
|
1250
|
+
</a>`;
|
|
1042
1251
|
}
|
|
1043
1252
|
}
|
|
1044
1253
|
]
|
|
1045
1254
|
};
|
|
1046
|
-
function buildButtonClasses(style, size) {
|
|
1047
|
-
const base = [
|
|
1048
|
-
"inline-flex",
|
|
1049
|
-
"items-center",
|
|
1050
|
-
"justify-center",
|
|
1051
|
-
"font-medium",
|
|
1052
|
-
"rounded-lg",
|
|
1053
|
-
"transition-colors",
|
|
1054
|
-
"focus:outline-none",
|
|
1055
|
-
"focus:ring-2",
|
|
1056
|
-
"focus:ring-offset-2",
|
|
1057
|
-
"disabled:opacity-50",
|
|
1058
|
-
"disabled:cursor-not-allowed"
|
|
1059
|
-
];
|
|
1060
|
-
const sizes = {
|
|
1061
|
-
sm: ["px-3", "py-1.5", "text-sm"],
|
|
1062
|
-
md: ["px-4", "py-2", "text-base"],
|
|
1063
|
-
lg: ["px-6", "py-3", "text-lg"]
|
|
1064
|
-
};
|
|
1065
|
-
const styles = {
|
|
1066
|
-
default: ["bg-slate-600", "text-white", "hover:bg-slate-700", "focus:ring-slate-500"],
|
|
1067
|
-
primary: ["bg-blue-600", "text-white", "hover:bg-blue-700", "focus:ring-blue-500"],
|
|
1068
|
-
secondary: ["bg-gray-600", "text-white", "hover:bg-gray-700", "focus:ring-gray-500"],
|
|
1069
|
-
success: ["bg-green-600", "text-white", "hover:bg-green-700", "focus:ring-green-500"],
|
|
1070
|
-
danger: ["bg-red-600", "text-white", "hover:bg-red-700", "focus:ring-red-500"],
|
|
1071
|
-
outline: ["border", "border-blue-600", "text-blue-600", "hover:bg-blue-50", "focus:ring-blue-500"],
|
|
1072
|
-
ghost: ["text-gray-700", "hover:bg-gray-100", "focus:ring-gray-500"]
|
|
1073
|
-
};
|
|
1074
|
-
const allClasses = [
|
|
1075
|
-
...base,
|
|
1076
|
-
...sizes[size] ?? sizes.md ?? [],
|
|
1077
|
-
...styles[style] ?? styles.primary ?? []
|
|
1078
|
-
];
|
|
1079
|
-
return allClasses.join(" ");
|
|
1080
|
-
}
|
|
1081
1255
|
|
|
1082
1256
|
// src/extensions/embed.ts
|
|
1083
1257
|
var EmbedExtension = {
|
|
@@ -1155,8 +1329,7 @@ function renderYouTubeEmbed(url, options, classes) {
|
|
|
1155
1329
|
params.set("rel", "0");
|
|
1156
1330
|
params.set("modestbranding", "1");
|
|
1157
1331
|
const embedUrl = `https://www.youtube.com/embed/${videoId}?${params.toString()}`;
|
|
1158
|
-
return
|
|
1159
|
-
<div class="${classes}">
|
|
1332
|
+
return `<div class="${classes}">
|
|
1160
1333
|
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
|
|
1161
1334
|
<iframe
|
|
1162
1335
|
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0;"
|
|
@@ -1184,8 +1357,7 @@ function renderCodePenEmbed(url, options, classes) {
|
|
|
1184
1357
|
"editable": "true"
|
|
1185
1358
|
});
|
|
1186
1359
|
const embedUrl = `https://codepen.io/${user}/embed/${penId}?${embedParams.toString()}`;
|
|
1187
|
-
return
|
|
1188
|
-
<div class="${classes}">
|
|
1360
|
+
return `<div class="${classes}">
|
|
1189
1361
|
<iframe
|
|
1190
1362
|
height="${height}"
|
|
1191
1363
|
style="width: 100%; border: 0;"
|
|
@@ -1209,8 +1381,7 @@ function renderVimeoEmbed(url, options, classes) {
|
|
|
1209
1381
|
if (options.mute === "1") params.set("muted", "1");
|
|
1210
1382
|
if (options.loop === "1") params.set("loop", "1");
|
|
1211
1383
|
const embedUrl = `https://player.vimeo.com/video/${videoId}?${params.toString()}`;
|
|
1212
|
-
return
|
|
1213
|
-
<div class="${classes}">
|
|
1384
|
+
return `<div class="${classes}">
|
|
1214
1385
|
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
|
|
1215
1386
|
<iframe
|
|
1216
1387
|
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0;"
|
|
@@ -1226,8 +1397,7 @@ function renderVimeoEmbed(url, options, classes) {
|
|
|
1226
1397
|
function renderSpotifyEmbed(url, options, classes) {
|
|
1227
1398
|
const embedUrl = url.replace("open.spotify.com", "open.spotify.com/embed");
|
|
1228
1399
|
const height = options.height || "380";
|
|
1229
|
-
return
|
|
1230
|
-
<div class="${classes}">
|
|
1400
|
+
return `<div class="${classes}">
|
|
1231
1401
|
<iframe
|
|
1232
1402
|
style="border-radius: 12px;"
|
|
1233
1403
|
src="${embedUrl}"
|
|
@@ -1250,8 +1420,7 @@ function renderCodeSandboxEmbed(url, options, classes) {
|
|
|
1250
1420
|
if (!embedUrl.includes("?")) {
|
|
1251
1421
|
embedUrl += `?view=${view}`;
|
|
1252
1422
|
}
|
|
1253
|
-
return
|
|
1254
|
-
<div class="${classes}">
|
|
1423
|
+
return `<div class="${classes}">
|
|
1255
1424
|
<iframe
|
|
1256
1425
|
src="${embedUrl}"
|
|
1257
1426
|
style="width: 100%; height: ${height}px; border: 0; border-radius: 4px; overflow: hidden;"
|
|
@@ -1264,8 +1433,7 @@ function renderCodeSandboxEmbed(url, options, classes) {
|
|
|
1264
1433
|
function renderFigmaEmbed(url, options, classes) {
|
|
1265
1434
|
const embedUrl = `https://www.figma.com/embed?embed_host=share&url=${encodeURIComponent(url)}`;
|
|
1266
1435
|
const height = options.height || "450";
|
|
1267
|
-
return
|
|
1268
|
-
<div class="${classes}">
|
|
1436
|
+
return `<div class="${classes}">
|
|
1269
1437
|
<iframe
|
|
1270
1438
|
style="border: none;"
|
|
1271
1439
|
width="100%"
|
|
@@ -1276,8 +1444,7 @@ function renderFigmaEmbed(url, options, classes) {
|
|
|
1276
1444
|
</div>`;
|
|
1277
1445
|
}
|
|
1278
1446
|
function renderTwitterEmbed(url, _options, classes) {
|
|
1279
|
-
return
|
|
1280
|
-
<div class="${classes}">
|
|
1447
|
+
return `<div class="${classes}">
|
|
1281
1448
|
<div class="p-4">
|
|
1282
1449
|
<div class="flex items-center gap-3 mb-3">
|
|
1283
1450
|
<svg class="w-6 h-6 fill-current text-blue-500" viewBox="0 0 24 24">
|
|
@@ -1305,8 +1472,7 @@ function renderGitHubEmbed(url, _options, classes) {
|
|
|
1305
1472
|
if (!owner || !repo) {
|
|
1306
1473
|
return createErrorEmbed("Invalid GitHub URL", url, classes);
|
|
1307
1474
|
}
|
|
1308
|
-
return
|
|
1309
|
-
<div class="${classes}">
|
|
1475
|
+
return `<div class="${classes}">
|
|
1310
1476
|
<div class="p-4">
|
|
1311
1477
|
<div class="flex items-center gap-3 mb-3">
|
|
1312
1478
|
<svg class="w-6 h-6 fill-current" viewBox="0 0 24 24">
|
|
@@ -1329,8 +1495,7 @@ function renderGitHubEmbed(url, _options, classes) {
|
|
|
1329
1495
|
}
|
|
1330
1496
|
function renderGenericEmbed(url, _options, classes) {
|
|
1331
1497
|
const domain = extractDomain(url);
|
|
1332
|
-
return
|
|
1333
|
-
<div class="${classes}">
|
|
1498
|
+
return `<div class="${classes}">
|
|
1334
1499
|
<div class="p-4">
|
|
1335
1500
|
<div class="flex items-center gap-3 mb-3">
|
|
1336
1501
|
<div class="w-10 h-10 rounded-lg bg-muted flex items-center justify-center">
|
|
@@ -1354,8 +1519,7 @@ function renderGenericEmbed(url, _options, classes) {
|
|
|
1354
1519
|
</div>`;
|
|
1355
1520
|
}
|
|
1356
1521
|
function createErrorEmbed(error, url, classes) {
|
|
1357
|
-
return
|
|
1358
|
-
<div class="${classes}">
|
|
1522
|
+
return `<div class="${classes}">
|
|
1359
1523
|
<div class="p-4 text-destructive">
|
|
1360
1524
|
<div class="font-medium flex items-center gap-2">
|
|
1361
1525
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
@@ -1389,19 +1553,54 @@ var ChangerawrMarkdown = class {
|
|
|
1389
1553
|
this.extensions = /* @__PURE__ */ new Map();
|
|
1390
1554
|
this.parser = new MarkdownParser(config?.parser);
|
|
1391
1555
|
this.renderer = new MarkdownRenderer(config?.renderer);
|
|
1392
|
-
this.
|
|
1556
|
+
this.registerCoreExtensions();
|
|
1557
|
+
this.registerFeatureExtensions();
|
|
1393
1558
|
if (config?.extensions) {
|
|
1394
1559
|
config.extensions.forEach((extension) => {
|
|
1395
1560
|
this.registerExtension(extension);
|
|
1396
1561
|
});
|
|
1397
1562
|
}
|
|
1398
|
-
this.parser.setupDefaultRulesIfEmpty();
|
|
1399
1563
|
}
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
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
|
+
}
|
|
1403
1574
|
registerExtension(extension) {
|
|
1404
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
|
+
});
|
|
1405
1604
|
this.extensions.set(extension.name, extension);
|
|
1406
1605
|
extension.parseRules.forEach((rule) => {
|
|
1407
1606
|
this.parser.addRule(rule);
|
|
@@ -1422,9 +1621,6 @@ var ChangerawrMarkdown = class {
|
|
|
1422
1621
|
};
|
|
1423
1622
|
}
|
|
1424
1623
|
}
|
|
1425
|
-
/**
|
|
1426
|
-
* Unregister an extension
|
|
1427
|
-
*/
|
|
1428
1624
|
unregisterExtension(name) {
|
|
1429
1625
|
const extension = this.extensions.get(name);
|
|
1430
1626
|
if (!extension) {
|
|
@@ -1438,46 +1634,25 @@ var ChangerawrMarkdown = class {
|
|
|
1438
1634
|
return false;
|
|
1439
1635
|
}
|
|
1440
1636
|
}
|
|
1441
|
-
/**
|
|
1442
|
-
* Parse markdown content into tokens
|
|
1443
|
-
*/
|
|
1444
1637
|
parse(markdown3) {
|
|
1445
1638
|
return this.parser.parse(markdown3);
|
|
1446
1639
|
}
|
|
1447
|
-
/**
|
|
1448
|
-
* Render tokens to HTML
|
|
1449
|
-
*/
|
|
1450
1640
|
render(tokens) {
|
|
1451
1641
|
return this.renderer.render(tokens);
|
|
1452
1642
|
}
|
|
1453
|
-
/**
|
|
1454
|
-
* Parse and render markdown to HTML in one step
|
|
1455
|
-
*/
|
|
1456
1643
|
toHtml(markdown3) {
|
|
1457
1644
|
const tokens = this.parse(markdown3);
|
|
1458
1645
|
return this.render(tokens);
|
|
1459
1646
|
}
|
|
1460
|
-
/**
|
|
1461
|
-
* Get list of registered extensions
|
|
1462
|
-
*/
|
|
1463
1647
|
getExtensions() {
|
|
1464
1648
|
return Array.from(this.extensions.keys());
|
|
1465
1649
|
}
|
|
1466
|
-
/**
|
|
1467
|
-
* Check if extension is registered
|
|
1468
|
-
*/
|
|
1469
1650
|
hasExtension(name) {
|
|
1470
1651
|
return this.extensions.has(name);
|
|
1471
1652
|
}
|
|
1472
|
-
/**
|
|
1473
|
-
* Get parser warnings
|
|
1474
|
-
*/
|
|
1475
1653
|
getWarnings() {
|
|
1476
1654
|
return [...this.parser.getWarnings(), ...this.renderer.getWarnings()];
|
|
1477
1655
|
}
|
|
1478
|
-
/**
|
|
1479
|
-
* Get debug information from last render
|
|
1480
|
-
*/
|
|
1481
1656
|
getDebugInfo() {
|
|
1482
1657
|
return {
|
|
1483
1658
|
warnings: this.getWarnings(),
|
|
@@ -1487,9 +1662,6 @@ var ChangerawrMarkdown = class {
|
|
|
1487
1662
|
iterationCount: 0
|
|
1488
1663
|
};
|
|
1489
1664
|
}
|
|
1490
|
-
/**
|
|
1491
|
-
* Get performance metrics for the last operation
|
|
1492
|
-
*/
|
|
1493
1665
|
getPerformanceMetrics() {
|
|
1494
1666
|
return {
|
|
1495
1667
|
parseTime: 0,
|
|
@@ -1498,28 +1670,29 @@ var ChangerawrMarkdown = class {
|
|
|
1498
1670
|
tokenCount: 0
|
|
1499
1671
|
};
|
|
1500
1672
|
}
|
|
1501
|
-
/**
|
|
1502
|
-
* Register built-in extensions
|
|
1503
|
-
*/
|
|
1504
|
-
registerBuiltInExtensions() {
|
|
1505
|
-
this.registerExtension(AlertExtension);
|
|
1506
|
-
this.registerExtension(ButtonExtension);
|
|
1507
|
-
this.registerExtension(EmbedExtension);
|
|
1508
|
-
}
|
|
1509
|
-
/**
|
|
1510
|
-
* Rebuild parser and renderer with current extensions
|
|
1511
|
-
*/
|
|
1512
1673
|
rebuildParserAndRenderer() {
|
|
1513
1674
|
const parserConfig = this.parser.getConfig();
|
|
1514
1675
|
const rendererConfig = this.renderer.getConfig();
|
|
1515
1676
|
this.parser = new MarkdownParser(parserConfig);
|
|
1516
1677
|
this.renderer = new MarkdownRenderer(rendererConfig);
|
|
1517
1678
|
const extensionsToRegister = Array.from(this.extensions.values());
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
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
|
+
});
|
|
1521
1695
|
});
|
|
1522
|
-
this.parser.setupDefaultRulesIfEmpty();
|
|
1523
1696
|
}
|
|
1524
1697
|
};
|
|
1525
1698
|
var markdown = new ChangerawrMarkdown();
|
|
@@ -1949,8 +2122,7 @@ function createHTMLEngine(config) {
|
|
|
1949
2122
|
renderer: {
|
|
1950
2123
|
format: "html",
|
|
1951
2124
|
sanitize: true,
|
|
1952
|
-
allowUnsafeHtml: false
|
|
1953
|
-
...config?.parser
|
|
2125
|
+
allowUnsafeHtml: false
|
|
1954
2126
|
}
|
|
1955
2127
|
});
|
|
1956
2128
|
}
|
|
@@ -1960,8 +2132,7 @@ function createTailwindEngine(config) {
|
|
|
1960
2132
|
renderer: {
|
|
1961
2133
|
format: "tailwind",
|
|
1962
2134
|
sanitize: true,
|
|
1963
|
-
allowUnsafeHtml: false
|
|
1964
|
-
...config?.parser
|
|
2135
|
+
allowUnsafeHtml: false
|
|
1965
2136
|
}
|
|
1966
2137
|
});
|
|
1967
2138
|
}
|
|
@@ -1980,21 +2151,18 @@ function createDebugEngine(config) {
|
|
|
1980
2151
|
}
|
|
1981
2152
|
});
|
|
1982
2153
|
}
|
|
1983
|
-
function createMinimalEngine(
|
|
1984
|
-
const engine = new ChangerawrMarkdown(
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
if (engine.hasExtension("embed")) {
|
|
1996
|
-
engine.unregisterExtension("embed");
|
|
1997
|
-
}
|
|
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");
|
|
1998
2166
|
return engine;
|
|
1999
2167
|
}
|
|
2000
2168
|
function createCustomEngine(extensions, config) {
|
|
@@ -2018,6 +2186,7 @@ var markdown2 = {
|
|
|
2018
2186
|
createTailwindEngine,
|
|
2019
2187
|
createDebugEngine,
|
|
2020
2188
|
createMinimalEngine,
|
|
2189
|
+
createCoreOnlyEngine,
|
|
2021
2190
|
createCustomEngine,
|
|
2022
2191
|
// Standalone functions
|
|
2023
2192
|
renderCum,
|
|
@@ -2026,6 +2195,24 @@ var markdown2 = {
|
|
|
2026
2195
|
ChangerawrMarkdown,
|
|
2027
2196
|
// Extensions
|
|
2028
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
|
|
2029
2216
|
Alert: AlertExtension,
|
|
2030
2217
|
Button: ButtonExtension,
|
|
2031
2218
|
Embed: EmbedExtension
|
|
@@ -2086,6 +2273,14 @@ var presets = {
|
|
|
2086
2273
|
sanitize: true
|
|
2087
2274
|
}
|
|
2088
2275
|
},
|
|
2276
|
+
/**
|
|
2277
|
+
* Core-only preset with just markdown basics
|
|
2278
|
+
*/
|
|
2279
|
+
coreOnly: {
|
|
2280
|
+
renderer: {
|
|
2281
|
+
format: "tailwind"
|
|
2282
|
+
}
|
|
2283
|
+
},
|
|
2089
2284
|
/**
|
|
2090
2285
|
* Performance preset with minimal processing
|
|
2091
2286
|
*/
|
|
@@ -2102,6 +2297,9 @@ var presets = {
|
|
|
2102
2297
|
};
|
|
2103
2298
|
function createEngineWithPreset(presetName, additionalConfig) {
|
|
2104
2299
|
const preset = presets[presetName];
|
|
2300
|
+
if (presetName === "coreOnly") {
|
|
2301
|
+
return createCoreOnlyEngine(additionalConfig);
|
|
2302
|
+
}
|
|
2105
2303
|
return new ChangerawrMarkdown({
|
|
2106
2304
|
...preset,
|
|
2107
2305
|
...additionalConfig
|
|
@@ -2109,17 +2307,33 @@ function createEngineWithPreset(presetName, additionalConfig) {
|
|
|
2109
2307
|
}
|
|
2110
2308
|
export {
|
|
2111
2309
|
AlertExtension,
|
|
2310
|
+
BlockquoteExtension,
|
|
2311
|
+
BoldExtension,
|
|
2112
2312
|
ButtonExtension,
|
|
2113
2313
|
ChangerawrMarkdown,
|
|
2314
|
+
CodeBlockExtension,
|
|
2315
|
+
CoreExtensions,
|
|
2114
2316
|
EmbedExtension,
|
|
2317
|
+
HeadingExtension,
|
|
2318
|
+
HorizontalRuleExtension,
|
|
2319
|
+
ImageExtension,
|
|
2320
|
+
InlineCodeExtension,
|
|
2321
|
+
ItalicExtension,
|
|
2322
|
+
LineBreakExtension,
|
|
2323
|
+
LinkExtension,
|
|
2324
|
+
ListExtension,
|
|
2115
2325
|
Logger,
|
|
2116
2326
|
MarkdownParser,
|
|
2117
2327
|
MarkdownRenderer,
|
|
2328
|
+
ParagraphExtension,
|
|
2118
2329
|
PerformanceTimer,
|
|
2330
|
+
TaskListExtension,
|
|
2331
|
+
TextExtension,
|
|
2119
2332
|
astToJSONString,
|
|
2120
2333
|
astToTokens,
|
|
2121
2334
|
basicSanitize,
|
|
2122
2335
|
compareTokens,
|
|
2336
|
+
createCoreOnlyEngine,
|
|
2123
2337
|
createCumEngine,
|
|
2124
2338
|
createCustomEngine,
|
|
2125
2339
|
createDebugEngine,
|