@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.js
CHANGED
|
@@ -31,17 +31,33 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
AlertExtension: () => AlertExtension,
|
|
34
|
+
BlockquoteExtension: () => BlockquoteExtension,
|
|
35
|
+
BoldExtension: () => BoldExtension,
|
|
34
36
|
ButtonExtension: () => ButtonExtension,
|
|
35
37
|
ChangerawrMarkdown: () => ChangerawrMarkdown,
|
|
38
|
+
CodeBlockExtension: () => CodeBlockExtension,
|
|
39
|
+
CoreExtensions: () => CoreExtensions,
|
|
36
40
|
EmbedExtension: () => EmbedExtension,
|
|
41
|
+
HeadingExtension: () => HeadingExtension,
|
|
42
|
+
HorizontalRuleExtension: () => HorizontalRuleExtension,
|
|
43
|
+
ImageExtension: () => ImageExtension,
|
|
44
|
+
InlineCodeExtension: () => InlineCodeExtension,
|
|
45
|
+
ItalicExtension: () => ItalicExtension,
|
|
46
|
+
LineBreakExtension: () => LineBreakExtension,
|
|
47
|
+
LinkExtension: () => LinkExtension,
|
|
48
|
+
ListExtension: () => ListExtension,
|
|
37
49
|
Logger: () => Logger,
|
|
38
50
|
MarkdownParser: () => MarkdownParser,
|
|
39
51
|
MarkdownRenderer: () => MarkdownRenderer,
|
|
52
|
+
ParagraphExtension: () => ParagraphExtension,
|
|
40
53
|
PerformanceTimer: () => PerformanceTimer,
|
|
54
|
+
TaskListExtension: () => TaskListExtension,
|
|
55
|
+
TextExtension: () => TextExtension,
|
|
41
56
|
astToJSONString: () => astToJSONString,
|
|
42
57
|
astToTokens: () => astToTokens,
|
|
43
58
|
basicSanitize: () => basicSanitize,
|
|
44
59
|
compareTokens: () => compareTokens,
|
|
60
|
+
createCoreOnlyEngine: () => createCoreOnlyEngine,
|
|
45
61
|
createCumEngine: () => createCumEngine,
|
|
46
62
|
createCustomEngine: () => createCustomEngine,
|
|
47
63
|
createDebugEngine: () => createDebugEngine,
|
|
@@ -95,39 +111,56 @@ var MarkdownParser = class {
|
|
|
95
111
|
constructor(config) {
|
|
96
112
|
this.rules = [];
|
|
97
113
|
this.warnings = [];
|
|
98
|
-
this.config =
|
|
114
|
+
this.config = {
|
|
115
|
+
debugMode: false,
|
|
116
|
+
maxIterations: 1e4,
|
|
117
|
+
validateMarkdown: false,
|
|
118
|
+
...config
|
|
119
|
+
};
|
|
99
120
|
}
|
|
100
121
|
addRule(rule) {
|
|
101
122
|
this.rules.push(rule);
|
|
102
123
|
this.rules.sort((a, b) => {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
if (
|
|
106
|
-
if (
|
|
107
|
-
|
|
108
|
-
|
|
124
|
+
const aFeatureExtension = ["alert", "button", "embed"].includes(a.name);
|
|
125
|
+
const bFeatureExtension = ["alert", "button", "embed"].includes(b.name);
|
|
126
|
+
if (aFeatureExtension && !bFeatureExtension) return -1;
|
|
127
|
+
if (!aFeatureExtension && bFeatureExtension) return 1;
|
|
128
|
+
const aCoreExtension = ["text", "heading", "bold", "italic", "code", "codeblock", "link", "image", "list", "task-list", "blockquote", "hr", "paragraph", "line-break"].includes(a.name);
|
|
129
|
+
const bCoreExtension = ["text", "heading", "bold", "italic", "code", "codeblock", "link", "image", "list", "task-list", "blockquote", "hr", "paragraph", "line-break"].includes(b.name);
|
|
130
|
+
if (aCoreExtension && !bCoreExtension) return -1;
|
|
131
|
+
if (!aCoreExtension && bCoreExtension) return 1;
|
|
132
|
+
if (a.name === "image" && b.name === "link") return -1;
|
|
133
|
+
if (a.name === "link" && b.name === "image") return 1;
|
|
134
|
+
if (a.name === "task-item" && b.name === "list-item") return -1;
|
|
135
|
+
if (a.name === "list-item" && b.name === "task-item") return 1;
|
|
136
|
+
if (a.name === "codeblock" && b.name === "code") return -1;
|
|
137
|
+
if (a.name === "code" && b.name === "codeblock") return 1;
|
|
138
|
+
if (a.name === "bold" && b.name === "italic") return -1;
|
|
139
|
+
if (a.name === "italic" && b.name === "bold") return 1;
|
|
109
140
|
return a.name.localeCompare(b.name);
|
|
110
141
|
});
|
|
111
142
|
}
|
|
112
|
-
setupDefaultRulesIfEmpty() {
|
|
113
|
-
const hasDefaultRules = this.rules.some(
|
|
114
|
-
(rule) => !["alert", "button", "embed"].includes(rule.name)
|
|
115
|
-
);
|
|
116
|
-
if (!hasDefaultRules) {
|
|
117
|
-
this.setupDefaultRules();
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
143
|
hasRule(name) {
|
|
121
144
|
return this.rules.some((rule) => rule.name === name);
|
|
122
145
|
}
|
|
123
146
|
parse(markdown3) {
|
|
124
147
|
this.warnings = [];
|
|
125
|
-
|
|
148
|
+
if (!markdown3.trim()) {
|
|
149
|
+
return [];
|
|
150
|
+
}
|
|
151
|
+
if (this.rules.length === 0) {
|
|
152
|
+
this.warnings.push("No parse rules registered - consider using CoreExtensions");
|
|
153
|
+
return [{
|
|
154
|
+
type: "text",
|
|
155
|
+
content: markdown3,
|
|
156
|
+
raw: markdown3
|
|
157
|
+
}];
|
|
158
|
+
}
|
|
126
159
|
const processedMarkdown = this.preprocessMarkdown(markdown3);
|
|
127
160
|
const tokens = [];
|
|
128
161
|
let remaining = processedMarkdown;
|
|
129
162
|
let iterationCount = 0;
|
|
130
|
-
const maxIterations = this.config.maxIterations ||
|
|
163
|
+
const maxIterations = this.config.maxIterations || 1e4;
|
|
131
164
|
while (remaining.length > 0 && iterationCount < maxIterations) {
|
|
132
165
|
iterationCount++;
|
|
133
166
|
let matched = false;
|
|
@@ -216,9 +249,6 @@ var MarkdownParser = class {
|
|
|
216
249
|
clearWarnings() {
|
|
217
250
|
this.warnings = [];
|
|
218
251
|
}
|
|
219
|
-
getIterationCount() {
|
|
220
|
-
return 0;
|
|
221
|
-
}
|
|
222
252
|
preprocessMarkdown(markdown3) {
|
|
223
253
|
if (this.config.validateMarkdown) {
|
|
224
254
|
this.validateMarkdown(markdown3);
|
|
@@ -273,161 +303,6 @@ var MarkdownParser = class {
|
|
|
273
303
|
}
|
|
274
304
|
return processed;
|
|
275
305
|
}
|
|
276
|
-
setupDefaultRules() {
|
|
277
|
-
this.addRule({
|
|
278
|
-
name: "heading",
|
|
279
|
-
pattern: /^(#{1,6})\s+(.+)$/m,
|
|
280
|
-
render: (match) => ({
|
|
281
|
-
type: "heading",
|
|
282
|
-
content: match[2]?.trim() || "",
|
|
283
|
-
raw: match[0] || "",
|
|
284
|
-
attributes: {
|
|
285
|
-
level: String(match[1]?.length || 1)
|
|
286
|
-
}
|
|
287
|
-
})
|
|
288
|
-
});
|
|
289
|
-
this.addRule({
|
|
290
|
-
name: "codeblock",
|
|
291
|
-
pattern: /```(\w+)?\s*\n([\s\S]*?)\n```/,
|
|
292
|
-
render: (match) => ({
|
|
293
|
-
type: "codeblock",
|
|
294
|
-
content: match[2] || "",
|
|
295
|
-
raw: match[0] || "",
|
|
296
|
-
attributes: {
|
|
297
|
-
language: match[1] || "text"
|
|
298
|
-
}
|
|
299
|
-
})
|
|
300
|
-
});
|
|
301
|
-
this.addRule({
|
|
302
|
-
name: "hard-break-backslash",
|
|
303
|
-
pattern: /\\\s*\n/,
|
|
304
|
-
render: (match) => ({
|
|
305
|
-
type: "line-break",
|
|
306
|
-
content: "",
|
|
307
|
-
raw: match[0] || ""
|
|
308
|
-
})
|
|
309
|
-
});
|
|
310
|
-
this.addRule({
|
|
311
|
-
name: "hard-break-spaces",
|
|
312
|
-
pattern: / +\n/,
|
|
313
|
-
render: (match) => ({
|
|
314
|
-
type: "line-break",
|
|
315
|
-
content: "",
|
|
316
|
-
raw: match[0] || ""
|
|
317
|
-
})
|
|
318
|
-
});
|
|
319
|
-
this.addRule({
|
|
320
|
-
name: "paragraph-break",
|
|
321
|
-
pattern: /\n\s*\n/,
|
|
322
|
-
render: (match) => ({
|
|
323
|
-
type: "paragraph-break",
|
|
324
|
-
content: "",
|
|
325
|
-
raw: match[0] || ""
|
|
326
|
-
})
|
|
327
|
-
});
|
|
328
|
-
this.addRule({
|
|
329
|
-
name: "bold",
|
|
330
|
-
pattern: /\*\*((?:(?!\*\*).)+)\*\*/,
|
|
331
|
-
render: (match) => ({
|
|
332
|
-
type: "bold",
|
|
333
|
-
content: match[1] || "",
|
|
334
|
-
raw: match[0] || ""
|
|
335
|
-
})
|
|
336
|
-
});
|
|
337
|
-
this.addRule({
|
|
338
|
-
name: "italic",
|
|
339
|
-
pattern: /\*((?:(?!\*).)+)\*/,
|
|
340
|
-
render: (match) => ({
|
|
341
|
-
type: "italic",
|
|
342
|
-
content: match[1] || "",
|
|
343
|
-
raw: match[0] || ""
|
|
344
|
-
})
|
|
345
|
-
});
|
|
346
|
-
this.addRule({
|
|
347
|
-
name: "code",
|
|
348
|
-
pattern: /`([^`]+)`/,
|
|
349
|
-
render: (match) => ({
|
|
350
|
-
type: "code",
|
|
351
|
-
content: match[1] || "",
|
|
352
|
-
raw: match[0] || ""
|
|
353
|
-
})
|
|
354
|
-
});
|
|
355
|
-
this.addRule({
|
|
356
|
-
name: "image",
|
|
357
|
-
pattern: /!\[([^\]]*)\]\(([^)]+?)(?:\s+"([^"]+)")?\)/,
|
|
358
|
-
render: (match) => ({
|
|
359
|
-
type: "image",
|
|
360
|
-
content: match[1] || "",
|
|
361
|
-
raw: match[0] || "",
|
|
362
|
-
attributes: {
|
|
363
|
-
alt: match[1] || "",
|
|
364
|
-
src: match[2] || "",
|
|
365
|
-
title: match[3] || ""
|
|
366
|
-
}
|
|
367
|
-
})
|
|
368
|
-
});
|
|
369
|
-
this.addRule({
|
|
370
|
-
name: "link",
|
|
371
|
-
pattern: /\[([^\]]+)\]\(([^)]+)\)/,
|
|
372
|
-
render: (match) => ({
|
|
373
|
-
type: "link",
|
|
374
|
-
content: match[1] || "",
|
|
375
|
-
raw: match[0] || "",
|
|
376
|
-
attributes: {
|
|
377
|
-
href: match[2] || ""
|
|
378
|
-
}
|
|
379
|
-
})
|
|
380
|
-
});
|
|
381
|
-
this.addRule({
|
|
382
|
-
name: "task-list",
|
|
383
|
-
pattern: /^(\s*)-\s*\[([ xX])\]\s*(.+)$/m,
|
|
384
|
-
render: (match) => ({
|
|
385
|
-
type: "task-item",
|
|
386
|
-
content: match[3] || "",
|
|
387
|
-
raw: match[0] || "",
|
|
388
|
-
attributes: {
|
|
389
|
-
checked: String((match[2] || "").toLowerCase() === "x")
|
|
390
|
-
}
|
|
391
|
-
})
|
|
392
|
-
});
|
|
393
|
-
this.addRule({
|
|
394
|
-
name: "list",
|
|
395
|
-
pattern: /^(\s*)[-*+]\s+(.+)$/m,
|
|
396
|
-
render: (match) => ({
|
|
397
|
-
type: "list-item",
|
|
398
|
-
content: match[2] || "",
|
|
399
|
-
raw: match[0] || ""
|
|
400
|
-
})
|
|
401
|
-
});
|
|
402
|
-
this.addRule({
|
|
403
|
-
name: "blockquote",
|
|
404
|
-
pattern: /^>\s+(.+)$/m,
|
|
405
|
-
render: (match) => ({
|
|
406
|
-
type: "blockquote",
|
|
407
|
-
content: match[1] || "",
|
|
408
|
-
raw: match[0] || ""
|
|
409
|
-
})
|
|
410
|
-
});
|
|
411
|
-
this.addRule({
|
|
412
|
-
name: "hr",
|
|
413
|
-
pattern: /^---$/m,
|
|
414
|
-
render: (match) => ({
|
|
415
|
-
type: "hr",
|
|
416
|
-
content: "",
|
|
417
|
-
raw: match[0] || ""
|
|
418
|
-
})
|
|
419
|
-
});
|
|
420
|
-
this.addRule({
|
|
421
|
-
name: "soft-break",
|
|
422
|
-
pattern: /\n/,
|
|
423
|
-
render: (match) => ({
|
|
424
|
-
type: "soft-break",
|
|
425
|
-
content: " ",
|
|
426
|
-
// Convert to space for inline text
|
|
427
|
-
raw: match[0] || ""
|
|
428
|
-
})
|
|
429
|
-
});
|
|
430
|
-
}
|
|
431
306
|
};
|
|
432
307
|
|
|
433
308
|
// src/utils.ts
|
|
@@ -746,7 +621,6 @@ var MarkdownRenderer = class {
|
|
|
746
621
|
debugMode: false,
|
|
747
622
|
...config
|
|
748
623
|
};
|
|
749
|
-
this.setupDefaultRules();
|
|
750
624
|
}
|
|
751
625
|
addRule(rule) {
|
|
752
626
|
this.rules.set(rule.type, rule);
|
|
@@ -756,28 +630,20 @@ var MarkdownRenderer = class {
|
|
|
756
630
|
}
|
|
757
631
|
render(tokens) {
|
|
758
632
|
this.warnings = [];
|
|
759
|
-
const
|
|
633
|
+
const tokensWithFormat = tokens.map((token) => ({
|
|
634
|
+
...token,
|
|
635
|
+
attributes: {
|
|
636
|
+
...token.attributes,
|
|
637
|
+
format: this.config.format
|
|
638
|
+
}
|
|
639
|
+
}));
|
|
640
|
+
const htmlParts = tokensWithFormat.map((token) => this.renderToken(token));
|
|
760
641
|
const combinedHtml = htmlParts.join("");
|
|
761
642
|
if (this.config.sanitize && !this.config.allowUnsafeHtml) {
|
|
762
643
|
return sanitizeHtml(combinedHtml);
|
|
763
644
|
}
|
|
764
645
|
return combinedHtml;
|
|
765
646
|
}
|
|
766
|
-
getWarnings() {
|
|
767
|
-
return [...this.warnings];
|
|
768
|
-
}
|
|
769
|
-
getConfig() {
|
|
770
|
-
return { ...this.config };
|
|
771
|
-
}
|
|
772
|
-
updateConfig(config) {
|
|
773
|
-
this.config = { ...this.config, ...config };
|
|
774
|
-
}
|
|
775
|
-
setDebugMode(enabled) {
|
|
776
|
-
this.config.debugMode = enabled;
|
|
777
|
-
}
|
|
778
|
-
clearWarnings() {
|
|
779
|
-
this.warnings = [];
|
|
780
|
-
}
|
|
781
647
|
renderToken(token) {
|
|
782
648
|
const rule = this.rules.get(token.type);
|
|
783
649
|
if (rule) {
|
|
@@ -789,9 +655,6 @@ var MarkdownRenderer = class {
|
|
|
789
655
|
return this.createErrorBlock(`Render error for ${token.type}: ${errorMessage}`);
|
|
790
656
|
}
|
|
791
657
|
}
|
|
792
|
-
if (token.type === "text") {
|
|
793
|
-
return escapeHtml(token.content || token.raw || "");
|
|
794
|
-
}
|
|
795
658
|
if (this.config.debugMode) {
|
|
796
659
|
return this.createDebugBlock(token);
|
|
797
660
|
}
|
|
@@ -819,15 +682,234 @@ var MarkdownRenderer = class {
|
|
|
819
682
|
<strong>Content:</strong> ${escapeHtml(token.content || token.raw || "")}
|
|
820
683
|
</div>`;
|
|
821
684
|
}
|
|
822
|
-
|
|
823
|
-
this.
|
|
685
|
+
getWarnings() {
|
|
686
|
+
return [...this.warnings];
|
|
687
|
+
}
|
|
688
|
+
getConfig() {
|
|
689
|
+
return { ...this.config };
|
|
690
|
+
}
|
|
691
|
+
updateConfig(config) {
|
|
692
|
+
this.config = { ...this.config, ...config };
|
|
693
|
+
}
|
|
694
|
+
setDebugMode(enabled) {
|
|
695
|
+
this.config.debugMode = enabled;
|
|
696
|
+
}
|
|
697
|
+
clearWarnings() {
|
|
698
|
+
this.warnings = [];
|
|
699
|
+
}
|
|
700
|
+
};
|
|
701
|
+
|
|
702
|
+
// src/extensions/core/blockquote.ts
|
|
703
|
+
var BlockquoteExtension = {
|
|
704
|
+
name: "blockquote",
|
|
705
|
+
parseRules: [
|
|
706
|
+
{
|
|
707
|
+
name: "blockquote",
|
|
708
|
+
pattern: /^>\s+(.+)$/m,
|
|
709
|
+
render: (match) => ({
|
|
710
|
+
type: "blockquote",
|
|
711
|
+
content: match[1] || "",
|
|
712
|
+
raw: match[0] || ""
|
|
713
|
+
})
|
|
714
|
+
}
|
|
715
|
+
],
|
|
716
|
+
renderRules: [
|
|
717
|
+
{
|
|
718
|
+
type: "blockquote",
|
|
719
|
+
render: (token) => {
|
|
720
|
+
const content = escapeHtml(token.content);
|
|
721
|
+
const format = token.attributes?.format || "html";
|
|
722
|
+
if (format === "html") {
|
|
723
|
+
return `<blockquote style="border-left: 2px solid #d1d5db; padding: 8px 0 8px 16px; margin: 16px 0; font-style: italic; color: #6b7280;">${content}</blockquote>`;
|
|
724
|
+
}
|
|
725
|
+
return `<blockquote class="pl-4 py-2 border-l-2 border-border italic text-muted-foreground my-4">${content}</blockquote>`;
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
]
|
|
729
|
+
};
|
|
730
|
+
|
|
731
|
+
// src/extensions/core/breaks.ts
|
|
732
|
+
var LineBreakExtension = {
|
|
733
|
+
name: "line-break",
|
|
734
|
+
parseRules: [
|
|
735
|
+
{
|
|
736
|
+
name: "hard-break-backslash",
|
|
737
|
+
pattern: /\\\s*\n/,
|
|
738
|
+
render: (match) => ({
|
|
739
|
+
type: "line-break",
|
|
740
|
+
content: "",
|
|
741
|
+
raw: match[0] || ""
|
|
742
|
+
})
|
|
743
|
+
},
|
|
744
|
+
{
|
|
745
|
+
name: "hard-break-spaces",
|
|
746
|
+
pattern: / +\n/,
|
|
747
|
+
render: (match) => ({
|
|
748
|
+
type: "line-break",
|
|
749
|
+
content: "",
|
|
750
|
+
raw: match[0] || ""
|
|
751
|
+
})
|
|
752
|
+
}
|
|
753
|
+
],
|
|
754
|
+
renderRules: [
|
|
755
|
+
{
|
|
756
|
+
type: "line-break",
|
|
757
|
+
render: () => "<br>"
|
|
758
|
+
},
|
|
759
|
+
{
|
|
760
|
+
type: "paragraph-break",
|
|
761
|
+
render: () => "</p><p>"
|
|
762
|
+
},
|
|
763
|
+
{
|
|
764
|
+
type: "soft-break",
|
|
765
|
+
render: (token) => token.content || " "
|
|
766
|
+
}
|
|
767
|
+
]
|
|
768
|
+
};
|
|
769
|
+
|
|
770
|
+
// src/extensions/core/code.ts
|
|
771
|
+
var InlineCodeExtension = {
|
|
772
|
+
name: "inline-code",
|
|
773
|
+
parseRules: [
|
|
774
|
+
{
|
|
775
|
+
name: "code",
|
|
776
|
+
pattern: /`([^`]+)`/,
|
|
777
|
+
render: (match) => ({
|
|
778
|
+
type: "code",
|
|
779
|
+
content: match[1] || "",
|
|
780
|
+
raw: match[0] || ""
|
|
781
|
+
})
|
|
782
|
+
}
|
|
783
|
+
],
|
|
784
|
+
renderRules: [
|
|
785
|
+
{
|
|
786
|
+
type: "code",
|
|
787
|
+
render: (token) => {
|
|
788
|
+
const content = escapeHtml(token.content);
|
|
789
|
+
const format = token.attributes?.format;
|
|
790
|
+
if (format === "html") {
|
|
791
|
+
return `<code style="background-color: #f3f4f6; padding: 2px 6px; border-radius: 4px; font-family: monospace; font-size: 0.875rem;">${content}</code>`;
|
|
792
|
+
}
|
|
793
|
+
return `<code class="bg-muted px-1.5 py-0.5 rounded text-sm font-mono">${content}</code>`;
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
]
|
|
797
|
+
};
|
|
798
|
+
var CodeBlockExtension = {
|
|
799
|
+
name: "codeblock",
|
|
800
|
+
parseRules: [
|
|
801
|
+
{
|
|
802
|
+
name: "codeblock",
|
|
803
|
+
pattern: /```(\w+)?\s*\n([\s\S]*?)\n```/,
|
|
804
|
+
render: (match) => ({
|
|
805
|
+
type: "codeblock",
|
|
806
|
+
content: match[2] || "",
|
|
807
|
+
raw: match[0] || "",
|
|
808
|
+
attributes: {
|
|
809
|
+
language: match[1] || "text"
|
|
810
|
+
}
|
|
811
|
+
})
|
|
812
|
+
}
|
|
813
|
+
],
|
|
814
|
+
renderRules: [
|
|
815
|
+
{
|
|
816
|
+
type: "codeblock",
|
|
817
|
+
render: (token) => {
|
|
818
|
+
const language = token.attributes?.language || "text";
|
|
819
|
+
const escapedCode = escapeHtml(token.content);
|
|
820
|
+
const format = token.attributes?.format || "html";
|
|
821
|
+
if (format === "html") {
|
|
822
|
+
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>`;
|
|
823
|
+
}
|
|
824
|
+
return `<pre class="bg-muted p-4 rounded-md overflow-x-auto my-4"><code class="language-${escapeHtml(language)}">${escapedCode}</code></pre>`;
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
]
|
|
828
|
+
};
|
|
829
|
+
|
|
830
|
+
// src/extensions/core/emphasis.ts
|
|
831
|
+
var BoldExtension = {
|
|
832
|
+
name: "bold",
|
|
833
|
+
parseRules: [
|
|
834
|
+
{
|
|
835
|
+
name: "bold",
|
|
836
|
+
pattern: /\*\*((?:(?!\*\*).)+)\*\*/,
|
|
837
|
+
render: (match) => ({
|
|
838
|
+
type: "bold",
|
|
839
|
+
content: match[1] || "",
|
|
840
|
+
raw: match[0] || ""
|
|
841
|
+
})
|
|
842
|
+
}
|
|
843
|
+
],
|
|
844
|
+
renderRules: [
|
|
845
|
+
{
|
|
846
|
+
type: "bold",
|
|
847
|
+
render: (token) => {
|
|
848
|
+
const content = escapeHtml(token.content);
|
|
849
|
+
const format = token.attributes?.format;
|
|
850
|
+
if (format === "html") {
|
|
851
|
+
return `<strong>${content}</strong>`;
|
|
852
|
+
}
|
|
853
|
+
return `<strong class="font-bold">${content}</strong>`;
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
]
|
|
857
|
+
};
|
|
858
|
+
var ItalicExtension = {
|
|
859
|
+
name: "italic",
|
|
860
|
+
parseRules: [
|
|
861
|
+
{
|
|
862
|
+
name: "italic",
|
|
863
|
+
pattern: /\*((?:(?!\*).)+)\*/,
|
|
864
|
+
render: (match) => ({
|
|
865
|
+
type: "italic",
|
|
866
|
+
content: match[1] || "",
|
|
867
|
+
raw: match[0] || ""
|
|
868
|
+
})
|
|
869
|
+
}
|
|
870
|
+
],
|
|
871
|
+
renderRules: [
|
|
872
|
+
{
|
|
873
|
+
type: "italic",
|
|
874
|
+
render: (token) => {
|
|
875
|
+
const content = escapeHtml(token.content);
|
|
876
|
+
const format = token.attributes?.format;
|
|
877
|
+
if (format === "html") {
|
|
878
|
+
return `<em>${content}</em>`;
|
|
879
|
+
}
|
|
880
|
+
return `<em class="italic">${content}</em>`;
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
]
|
|
884
|
+
};
|
|
885
|
+
|
|
886
|
+
// src/extensions/core/heading.ts
|
|
887
|
+
var HeadingExtension = {
|
|
888
|
+
name: "heading",
|
|
889
|
+
parseRules: [
|
|
890
|
+
{
|
|
891
|
+
name: "heading",
|
|
892
|
+
pattern: /^(#{1,6})\s+(.+)$/m,
|
|
893
|
+
render: (match) => ({
|
|
894
|
+
type: "heading",
|
|
895
|
+
content: match[2]?.trim() || "",
|
|
896
|
+
raw: match[0] || "",
|
|
897
|
+
attributes: {
|
|
898
|
+
level: String(match[1]?.length || 1)
|
|
899
|
+
}
|
|
900
|
+
})
|
|
901
|
+
}
|
|
902
|
+
],
|
|
903
|
+
renderRules: [
|
|
904
|
+
{
|
|
824
905
|
type: "heading",
|
|
825
906
|
render: (token) => {
|
|
826
907
|
const level = parseInt(token.attributes?.level || "1");
|
|
827
908
|
const text = token.content;
|
|
828
909
|
const id = generateId(text);
|
|
829
910
|
const escapedContent = escapeHtml(text);
|
|
830
|
-
|
|
911
|
+
const format = token.attributes?.format || "html";
|
|
912
|
+
if (format === "html") {
|
|
831
913
|
return `<h${level} id="${id}">${escapedContent}</h${level}>`;
|
|
832
914
|
}
|
|
833
915
|
let headingClasses = "group relative flex items-center gap-2";
|
|
@@ -854,61 +936,108 @@ var MarkdownRenderer = class {
|
|
|
854
936
|
return `<h${level} id="${id}" class="${headingClasses}">
|
|
855
937
|
${escapedContent}
|
|
856
938
|
<a href="#${id}" class="opacity-0 group-hover:opacity-100 text-muted-foreground transition-opacity">
|
|
857
|
-
<svg width="16" height="16" viewBox="0 0
|
|
858
|
-
|
|
859
|
-
|
|
939
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
940
|
+
<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/>
|
|
941
|
+
<path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/>
|
|
942
|
+
</svg>
|
|
860
943
|
</a>
|
|
861
944
|
</h${level}>`;
|
|
862
945
|
}
|
|
863
|
-
}
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
this.addRule({
|
|
885
|
-
type: "code",
|
|
946
|
+
}
|
|
947
|
+
]
|
|
948
|
+
};
|
|
949
|
+
|
|
950
|
+
// src/extensions/core/hr.ts
|
|
951
|
+
var HorizontalRuleExtension = {
|
|
952
|
+
name: "hr",
|
|
953
|
+
parseRules: [
|
|
954
|
+
{
|
|
955
|
+
name: "hr",
|
|
956
|
+
pattern: /^---$/m,
|
|
957
|
+
render: (match) => ({
|
|
958
|
+
type: "hr",
|
|
959
|
+
content: "",
|
|
960
|
+
raw: match[0] || ""
|
|
961
|
+
})
|
|
962
|
+
}
|
|
963
|
+
],
|
|
964
|
+
renderRules: [
|
|
965
|
+
{
|
|
966
|
+
type: "hr",
|
|
886
967
|
render: (token) => {
|
|
887
|
-
const
|
|
888
|
-
if (
|
|
889
|
-
return
|
|
968
|
+
const format = token.attributes?.format;
|
|
969
|
+
if (format === "html") {
|
|
970
|
+
return '<hr style="margin: 24px 0; border: none; border-top: 1px solid #d1d5db;">';
|
|
890
971
|
}
|
|
891
|
-
return
|
|
972
|
+
return '<hr class="my-6 border-t border-border">';
|
|
892
973
|
}
|
|
893
|
-
}
|
|
894
|
-
|
|
895
|
-
|
|
974
|
+
}
|
|
975
|
+
]
|
|
976
|
+
};
|
|
977
|
+
|
|
978
|
+
// src/extensions/core/image.ts
|
|
979
|
+
var ImageExtension = {
|
|
980
|
+
name: "image",
|
|
981
|
+
parseRules: [
|
|
982
|
+
{
|
|
983
|
+
name: "image",
|
|
984
|
+
pattern: /!\[([^\]]*)\]\(([^)]+?)(?:\s+"([^"]+)")?\)/,
|
|
985
|
+
render: (match) => ({
|
|
986
|
+
type: "image",
|
|
987
|
+
content: match[1] || "",
|
|
988
|
+
raw: match[0] || "",
|
|
989
|
+
attributes: {
|
|
990
|
+
alt: match[1] || "",
|
|
991
|
+
src: match[2] || "",
|
|
992
|
+
title: match[3] || ""
|
|
993
|
+
}
|
|
994
|
+
})
|
|
995
|
+
}
|
|
996
|
+
],
|
|
997
|
+
renderRules: [
|
|
998
|
+
{
|
|
999
|
+
type: "image",
|
|
896
1000
|
render: (token) => {
|
|
897
|
-
const
|
|
898
|
-
const
|
|
899
|
-
|
|
900
|
-
|
|
1001
|
+
const src = token.attributes?.src || "";
|
|
1002
|
+
const alt = token.attributes?.alt || "";
|
|
1003
|
+
const title = token.attributes?.title || "";
|
|
1004
|
+
const titleAttr = title ? ` title="${escapeHtml(title)}"` : "";
|
|
1005
|
+
const format = token.attributes?.format || "html";
|
|
1006
|
+
if (format === "html") {
|
|
1007
|
+
return `<img src="${escapeHtml(src)}" alt="${escapeHtml(alt)}"${titleAttr} style="max-width: 100%; height: auto; border-radius: 8px; margin: 16px 0;" loading="lazy" />`;
|
|
901
1008
|
}
|
|
902
|
-
return `<
|
|
1009
|
+
return `<img src="${escapeHtml(src)}" alt="${escapeHtml(alt)}"${titleAttr} class="max-w-full h-auto rounded-lg my-4" loading="lazy" />`;
|
|
903
1010
|
}
|
|
904
|
-
}
|
|
905
|
-
|
|
1011
|
+
}
|
|
1012
|
+
]
|
|
1013
|
+
};
|
|
1014
|
+
|
|
1015
|
+
// src/extensions/core/links.ts
|
|
1016
|
+
var LinkExtension = {
|
|
1017
|
+
name: "link",
|
|
1018
|
+
parseRules: [
|
|
1019
|
+
{
|
|
1020
|
+
name: "link",
|
|
1021
|
+
pattern: /\[(?!(?:button|embed):)([^\]]+)\]\(([^)]+)\)/,
|
|
1022
|
+
render: (match) => ({
|
|
1023
|
+
type: "link",
|
|
1024
|
+
content: match[1] || "",
|
|
1025
|
+
raw: match[0] || "",
|
|
1026
|
+
attributes: {
|
|
1027
|
+
href: match[2] || ""
|
|
1028
|
+
}
|
|
1029
|
+
})
|
|
1030
|
+
}
|
|
1031
|
+
],
|
|
1032
|
+
renderRules: [
|
|
1033
|
+
{
|
|
906
1034
|
type: "link",
|
|
907
1035
|
render: (token) => {
|
|
908
1036
|
const href = token.attributes?.href || "#";
|
|
909
1037
|
const escapedHref = escapeHtml(href);
|
|
910
1038
|
const escapedText = escapeHtml(token.content);
|
|
911
|
-
|
|
1039
|
+
const format = token.attributes?.format || "html";
|
|
1040
|
+
if (format === "html") {
|
|
912
1041
|
return `<a href="${escapedHref}" target="_blank" rel="noopener noreferrer">${escapedText}</a>`;
|
|
913
1042
|
}
|
|
914
1043
|
return `<a href="${escapedHref}" class="text-primary hover:underline inline-flex items-center gap-1" target="_blank" rel="noopener noreferrer">
|
|
@@ -920,47 +1049,55 @@ var MarkdownRenderer = class {
|
|
|
920
1049
|
</svg>
|
|
921
1050
|
</a>`;
|
|
922
1051
|
}
|
|
923
|
-
}
|
|
924
|
-
|
|
1052
|
+
}
|
|
1053
|
+
]
|
|
1054
|
+
};
|
|
1055
|
+
|
|
1056
|
+
// src/extensions/core/lists.ts
|
|
1057
|
+
var ListExtension = {
|
|
1058
|
+
name: "list",
|
|
1059
|
+
parseRules: [
|
|
1060
|
+
{
|
|
1061
|
+
name: "list-item",
|
|
1062
|
+
pattern: /^(\s*)[-*+]\s+(.+)$/m,
|
|
1063
|
+
render: (match) => ({
|
|
1064
|
+
type: "list-item",
|
|
1065
|
+
content: match[2] || "",
|
|
1066
|
+
raw: match[0] || ""
|
|
1067
|
+
})
|
|
1068
|
+
}
|
|
1069
|
+
],
|
|
1070
|
+
renderRules: [
|
|
1071
|
+
{
|
|
925
1072
|
type: "list-item",
|
|
926
1073
|
render: (token) => `<li>${escapeHtml(token.content)}</li>`
|
|
927
|
-
}
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
return escapeHtml(token.content);
|
|
943
|
-
}
|
|
944
|
-
});
|
|
945
|
-
this.addRule({
|
|
946
|
-
type: "paragraph",
|
|
947
|
-
render: (token) => {
|
|
948
|
-
if (!token.content) return "";
|
|
949
|
-
const content = token.content.trim();
|
|
950
|
-
if (!content) return "";
|
|
951
|
-
const processedContent = content.includes("<br>") ? content : escapeHtml(content);
|
|
952
|
-
if (this.config.format === "html") {
|
|
953
|
-
return `<p style="line-height: 1.75; margin-bottom: 16px;">${processedContent}</p>`;
|
|
1074
|
+
}
|
|
1075
|
+
]
|
|
1076
|
+
};
|
|
1077
|
+
var TaskListExtension = {
|
|
1078
|
+
name: "task-list",
|
|
1079
|
+
parseRules: [
|
|
1080
|
+
{
|
|
1081
|
+
name: "task-item",
|
|
1082
|
+
pattern: /^(\s*)-\s*\[([ xX])\]\s*(.+)$/m,
|
|
1083
|
+
render: (match) => ({
|
|
1084
|
+
type: "task-item",
|
|
1085
|
+
content: match[3] || "",
|
|
1086
|
+
raw: match[0] || "",
|
|
1087
|
+
attributes: {
|
|
1088
|
+
checked: String((match[2] || "").toLowerCase() === "x")
|
|
954
1089
|
}
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
1090
|
+
})
|
|
1091
|
+
}
|
|
1092
|
+
],
|
|
1093
|
+
renderRules: [
|
|
1094
|
+
{
|
|
959
1095
|
type: "task-item",
|
|
960
1096
|
render: (token) => {
|
|
961
1097
|
const isChecked = token.attributes?.checked === "true";
|
|
962
1098
|
const escapedContent = escapeHtml(token.content);
|
|
963
|
-
|
|
1099
|
+
const format = token.attributes?.format || "html";
|
|
1100
|
+
if (format === "html") {
|
|
964
1101
|
return `<div style="display: flex; align-items: center; gap: 8px; margin: 8px 0;">
|
|
965
1102
|
<input type="checkbox" ${isChecked ? "checked" : ""} disabled style="margin: 0;" />
|
|
966
1103
|
<span${isChecked ? ' style="text-decoration: line-through; color: #6b7280;"' : ""}>${escapedContent}</span>
|
|
@@ -972,44 +1109,65 @@ var MarkdownRenderer = class {
|
|
|
972
1109
|
<span${isChecked ? ' class="line-through text-muted-foreground"' : ""}>${escapedContent}</span>
|
|
973
1110
|
</div>`;
|
|
974
1111
|
}
|
|
975
|
-
}
|
|
976
|
-
|
|
977
|
-
|
|
1112
|
+
}
|
|
1113
|
+
]
|
|
1114
|
+
};
|
|
1115
|
+
|
|
1116
|
+
// src/extensions/core/paragraph.ts
|
|
1117
|
+
var ParagraphExtension = {
|
|
1118
|
+
name: "paragraph",
|
|
1119
|
+
parseRules: [],
|
|
1120
|
+
renderRules: [
|
|
1121
|
+
{
|
|
1122
|
+
type: "paragraph",
|
|
978
1123
|
render: (token) => {
|
|
979
|
-
|
|
980
|
-
const
|
|
981
|
-
|
|
982
|
-
const
|
|
983
|
-
|
|
984
|
-
|
|
1124
|
+
if (!token.content) return "";
|
|
1125
|
+
const content = token.content.trim();
|
|
1126
|
+
if (!content) return "";
|
|
1127
|
+
const processedContent = content.includes("<br>") ? content : escapeHtml(content);
|
|
1128
|
+
const format = token.attributes?.format || "html";
|
|
1129
|
+
if (format === "html") {
|
|
1130
|
+
return `<p style="line-height: 1.75; margin-bottom: 16px;">${processedContent}</p>`;
|
|
985
1131
|
}
|
|
986
|
-
return `<
|
|
1132
|
+
return `<p class="leading-7 mb-4">${processedContent}</p>`;
|
|
987
1133
|
}
|
|
988
|
-
}
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
1134
|
+
}
|
|
1135
|
+
]
|
|
1136
|
+
};
|
|
1137
|
+
|
|
1138
|
+
// src/extensions/core/text.ts
|
|
1139
|
+
var TextExtension = {
|
|
1140
|
+
name: "text",
|
|
1141
|
+
parseRules: [],
|
|
1142
|
+
renderRules: [
|
|
1143
|
+
{
|
|
1144
|
+
type: "text",
|
|
1145
|
+
render: (token) => {
|
|
1146
|
+
if (!token.content) return "";
|
|
1147
|
+
return escapeHtml(token.content);
|
|
996
1148
|
}
|
|
997
|
-
}
|
|
998
|
-
|
|
999
|
-
type: "line-break",
|
|
1000
|
-
render: () => "<br>"
|
|
1001
|
-
});
|
|
1002
|
-
this.addRule({
|
|
1003
|
-
type: "paragraph-break",
|
|
1004
|
-
render: () => "</p><p>"
|
|
1005
|
-
});
|
|
1006
|
-
this.addRule({
|
|
1007
|
-
type: "soft-break",
|
|
1008
|
-
render: (token) => token.content || " "
|
|
1009
|
-
});
|
|
1010
|
-
}
|
|
1149
|
+
}
|
|
1150
|
+
]
|
|
1011
1151
|
};
|
|
1012
1152
|
|
|
1153
|
+
// src/extensions/core/index.ts
|
|
1154
|
+
var CoreExtensions = [
|
|
1155
|
+
TextExtension,
|
|
1156
|
+
HeadingExtension,
|
|
1157
|
+
BoldExtension,
|
|
1158
|
+
ItalicExtension,
|
|
1159
|
+
InlineCodeExtension,
|
|
1160
|
+
CodeBlockExtension,
|
|
1161
|
+
LinkExtension,
|
|
1162
|
+
ImageExtension,
|
|
1163
|
+
ListExtension,
|
|
1164
|
+
TaskListExtension,
|
|
1165
|
+
BlockquoteExtension,
|
|
1166
|
+
HorizontalRuleExtension,
|
|
1167
|
+
ParagraphExtension,
|
|
1168
|
+
LineBreakExtension
|
|
1169
|
+
];
|
|
1170
|
+
|
|
1013
1171
|
// src/extensions/alert.ts
|
|
1014
1172
|
var AlertExtension = {
|
|
1015
1173
|
name: "alert",
|
|
@@ -1089,26 +1247,19 @@ var ButtonExtension = {
|
|
|
1089
1247
|
name: "button",
|
|
1090
1248
|
pattern: /\[button:([^\]]+)\]\(([^)]+)\)(?:\{([^}]+)\})?/,
|
|
1091
1249
|
render: (match) => {
|
|
1092
|
-
const
|
|
1093
|
-
const href = match[2] || "";
|
|
1094
|
-
const optionsString = match[3] || "";
|
|
1095
|
-
const options = optionsString.split(",").map((opt) => opt.trim()).filter(Boolean);
|
|
1096
|
-
const styleOptions = ["default", "primary", "secondary", "success", "danger", "outline", "ghost"];
|
|
1097
|
-
const style = options.find((opt) => styleOptions.includes(opt)) || "primary";
|
|
1098
|
-
const sizeOptions = ["sm", "md", "lg"];
|
|
1099
|
-
const size = options.find((opt) => sizeOptions.includes(opt)) || "md";
|
|
1100
|
-
const disabled = options.includes("disabled");
|
|
1101
|
-
const target = options.includes("self") ? "_self" : "_blank";
|
|
1250
|
+
const options = match[3] ? match[3].split(",").map((opt) => opt.trim()) : [];
|
|
1102
1251
|
return {
|
|
1103
1252
|
type: "button",
|
|
1104
|
-
content:
|
|
1253
|
+
content: match[1] || "",
|
|
1105
1254
|
raw: match[0] || "",
|
|
1106
1255
|
attributes: {
|
|
1107
|
-
href,
|
|
1108
|
-
style
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1256
|
+
href: match[2] || "",
|
|
1257
|
+
style: options.find(
|
|
1258
|
+
(opt) => ["default", "primary", "secondary", "success", "danger", "outline", "ghost"].includes(opt)
|
|
1259
|
+
) || "primary",
|
|
1260
|
+
size: options.find((opt) => ["sm", "md", "lg"].includes(opt)) || "md",
|
|
1261
|
+
disabled: String(options.includes("disabled")),
|
|
1262
|
+
target: options.includes("self") ? "_self" : "_blank"
|
|
1112
1263
|
}
|
|
1113
1264
|
};
|
|
1114
1265
|
}
|
|
@@ -1123,53 +1274,92 @@ var ButtonExtension = {
|
|
|
1123
1274
|
const size = token.attributes?.size || "md";
|
|
1124
1275
|
const disabled = token.attributes?.disabled === "true";
|
|
1125
1276
|
const target = token.attributes?.target || "_blank";
|
|
1126
|
-
const
|
|
1127
|
-
|
|
1277
|
+
const baseClasses = `
|
|
1278
|
+
inline-flex items-center justify-center font-medium rounded-lg
|
|
1279
|
+
transition-all duration-200 ease-out
|
|
1280
|
+
focus:outline-none focus:ring-2 focus:ring-offset-2
|
|
1281
|
+
disabled:opacity-50 disabled:cursor-not-allowed disabled:pointer-events-none
|
|
1282
|
+
transform hover:scale-[1.02] active:scale-[0.98]
|
|
1283
|
+
shadow-sm hover:shadow-md active:shadow-sm
|
|
1284
|
+
border border-transparent
|
|
1285
|
+
relative overflow-hidden
|
|
1286
|
+
before:absolute before:inset-0 before:rounded-lg
|
|
1287
|
+
before:bg-gradient-to-br before:from-white/20 before:to-transparent
|
|
1288
|
+
before:opacity-0 hover:before:opacity-100 before:transition-opacity before:duration-200
|
|
1289
|
+
`.replace(/\s+/g, " ").trim();
|
|
1290
|
+
const sizeClasses = {
|
|
1291
|
+
sm: "px-3 py-1.5 text-sm gap-1.5",
|
|
1292
|
+
md: "px-4 py-2 text-base gap-2",
|
|
1293
|
+
lg: "px-6 py-3 text-lg gap-2.5"
|
|
1294
|
+
};
|
|
1295
|
+
const styleClasses = {
|
|
1296
|
+
default: `
|
|
1297
|
+
bg-slate-600 text-white border-slate-500
|
|
1298
|
+
hover:bg-slate-700 hover:border-slate-400
|
|
1299
|
+
focus:ring-slate-500
|
|
1300
|
+
shadow-[0_1px_0_0_rgba(255,255,255,0.1)_inset,0_1px_2px_0_rgba(0,0,0,0.1)]
|
|
1301
|
+
hover:shadow-[0_1px_0_0_rgba(255,255,255,0.15)_inset,0_2px_4px_0_rgba(0,0,0,0.15)]
|
|
1302
|
+
`,
|
|
1303
|
+
primary: `
|
|
1304
|
+
bg-blue-600 text-white border-blue-500
|
|
1305
|
+
hover:bg-blue-700 hover:border-blue-400
|
|
1306
|
+
focus:ring-blue-500
|
|
1307
|
+
shadow-[0_1px_0_0_rgba(255,255,255,0.1)_inset,0_1px_2px_0_rgba(0,0,0,0.1)]
|
|
1308
|
+
hover:shadow-[0_1px_0_0_rgba(255,255,255,0.15)_inset,0_2px_4px_0_rgba(0,0,0,0.15)]
|
|
1309
|
+
`,
|
|
1310
|
+
secondary: `
|
|
1311
|
+
bg-gray-600 text-white border-gray-500
|
|
1312
|
+
hover:bg-gray-700 hover:border-gray-400
|
|
1313
|
+
focus:ring-gray-500
|
|
1314
|
+
shadow-[0_1px_0_0_rgba(255,255,255,0.1)_inset,0_1px_2px_0_rgba(0,0,0,0.1)]
|
|
1315
|
+
hover:shadow-[0_1px_0_0_rgba(255,255,255,0.15)_inset,0_2px_4px_0_rgba(0,0,0,0.15)]
|
|
1316
|
+
`,
|
|
1317
|
+
success: `
|
|
1318
|
+
bg-green-600 text-white border-green-500
|
|
1319
|
+
hover:bg-green-700 hover:border-green-400
|
|
1320
|
+
focus:ring-green-500
|
|
1321
|
+
shadow-[0_1px_0_0_rgba(255,255,255,0.1)_inset,0_1px_2px_0_rgba(0,0,0,0.1)]
|
|
1322
|
+
hover:shadow-[0_1px_0_0_rgba(255,255,255,0.15)_inset,0_2px_4px_0_rgba(0,0,0,0.15)]
|
|
1323
|
+
`,
|
|
1324
|
+
danger: `
|
|
1325
|
+
bg-red-600 text-white border-red-500
|
|
1326
|
+
hover:bg-red-700 hover:border-red-400
|
|
1327
|
+
focus:ring-red-500
|
|
1328
|
+
shadow-[0_1px_0_0_rgba(255,255,255,0.1)_inset,0_1px_2px_0_rgba(0,0,0,0.1)]
|
|
1329
|
+
hover:shadow-[0_1px_0_0_rgba(255,255,255,0.15)_inset,0_2px_4px_0_rgba(0,0,0,0.15)]
|
|
1330
|
+
`,
|
|
1331
|
+
outline: `
|
|
1332
|
+
bg-transparent text-blue-600 border-blue-600
|
|
1333
|
+
hover:bg-blue-50 hover:border-blue-700 hover:text-blue-700
|
|
1334
|
+
focus:ring-blue-500
|
|
1335
|
+
shadow-[0_0_0_1px_rgba(59,130,246,0.5)_inset]
|
|
1336
|
+
hover:shadow-[0_0_0_1px_rgba(29,78,216,0.6)_inset,0_1px_2px_0_rgba(0,0,0,0.05)]
|
|
1337
|
+
`,
|
|
1338
|
+
ghost: `
|
|
1339
|
+
bg-transparent text-gray-700 border-transparent
|
|
1340
|
+
hover:bg-gray-100 hover:text-gray-900
|
|
1341
|
+
focus:ring-gray-500
|
|
1342
|
+
shadow-none
|
|
1343
|
+
hover:shadow-[0_1px_2px_0_rgba(0,0,0,0.05)]
|
|
1344
|
+
`
|
|
1345
|
+
};
|
|
1346
|
+
const classes = `
|
|
1347
|
+
${baseClasses}
|
|
1348
|
+
${sizeClasses[size] || sizeClasses.md}
|
|
1349
|
+
${styleClasses[style] || styleClasses.primary}
|
|
1350
|
+
`.replace(/\s+/g, " ").trim();
|
|
1128
1351
|
const targetAttr = target === "_blank" ? ' target="_blank" rel="noopener noreferrer"' : target === "_self" ? ' target="_self"' : "";
|
|
1129
1352
|
const disabledAttr = disabled ? ' aria-disabled="true" tabindex="-1"' : "";
|
|
1130
|
-
const externalIcon = target === "_blank" && !disabled ?
|
|
1353
|
+
const externalIcon = target === "_blank" && !disabled ? `<svg class="w-4 h-4 ml-1 opacity-75" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
1354
|
+
<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"/>
|
|
1355
|
+
</svg>` : "";
|
|
1131
1356
|
return `<a href="${href}" class="${classes}"${targetAttr}${disabledAttr}>
|
|
1132
|
-
|
|
1133
|
-
|
|
1357
|
+
<span class="relative z-10">${token.content}</span>${externalIcon}
|
|
1358
|
+
</a>`;
|
|
1134
1359
|
}
|
|
1135
1360
|
}
|
|
1136
1361
|
]
|
|
1137
1362
|
};
|
|
1138
|
-
function buildButtonClasses(style, size) {
|
|
1139
|
-
const base = [
|
|
1140
|
-
"inline-flex",
|
|
1141
|
-
"items-center",
|
|
1142
|
-
"justify-center",
|
|
1143
|
-
"font-medium",
|
|
1144
|
-
"rounded-lg",
|
|
1145
|
-
"transition-colors",
|
|
1146
|
-
"focus:outline-none",
|
|
1147
|
-
"focus:ring-2",
|
|
1148
|
-
"focus:ring-offset-2",
|
|
1149
|
-
"disabled:opacity-50",
|
|
1150
|
-
"disabled:cursor-not-allowed"
|
|
1151
|
-
];
|
|
1152
|
-
const sizes = {
|
|
1153
|
-
sm: ["px-3", "py-1.5", "text-sm"],
|
|
1154
|
-
md: ["px-4", "py-2", "text-base"],
|
|
1155
|
-
lg: ["px-6", "py-3", "text-lg"]
|
|
1156
|
-
};
|
|
1157
|
-
const styles = {
|
|
1158
|
-
default: ["bg-slate-600", "text-white", "hover:bg-slate-700", "focus:ring-slate-500"],
|
|
1159
|
-
primary: ["bg-blue-600", "text-white", "hover:bg-blue-700", "focus:ring-blue-500"],
|
|
1160
|
-
secondary: ["bg-gray-600", "text-white", "hover:bg-gray-700", "focus:ring-gray-500"],
|
|
1161
|
-
success: ["bg-green-600", "text-white", "hover:bg-green-700", "focus:ring-green-500"],
|
|
1162
|
-
danger: ["bg-red-600", "text-white", "hover:bg-red-700", "focus:ring-red-500"],
|
|
1163
|
-
outline: ["border", "border-blue-600", "text-blue-600", "hover:bg-blue-50", "focus:ring-blue-500"],
|
|
1164
|
-
ghost: ["text-gray-700", "hover:bg-gray-100", "focus:ring-gray-500"]
|
|
1165
|
-
};
|
|
1166
|
-
const allClasses = [
|
|
1167
|
-
...base,
|
|
1168
|
-
...sizes[size] ?? sizes.md ?? [],
|
|
1169
|
-
...styles[style] ?? styles.primary ?? []
|
|
1170
|
-
];
|
|
1171
|
-
return allClasses.join(" ");
|
|
1172
|
-
}
|
|
1173
1363
|
|
|
1174
1364
|
// src/extensions/embed.ts
|
|
1175
1365
|
var EmbedExtension = {
|
|
@@ -1247,8 +1437,7 @@ function renderYouTubeEmbed(url, options, classes) {
|
|
|
1247
1437
|
params.set("rel", "0");
|
|
1248
1438
|
params.set("modestbranding", "1");
|
|
1249
1439
|
const embedUrl = `https://www.youtube.com/embed/${videoId}?${params.toString()}`;
|
|
1250
|
-
return
|
|
1251
|
-
<div class="${classes}">
|
|
1440
|
+
return `<div class="${classes}">
|
|
1252
1441
|
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
|
|
1253
1442
|
<iframe
|
|
1254
1443
|
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0;"
|
|
@@ -1276,8 +1465,7 @@ function renderCodePenEmbed(url, options, classes) {
|
|
|
1276
1465
|
"editable": "true"
|
|
1277
1466
|
});
|
|
1278
1467
|
const embedUrl = `https://codepen.io/${user}/embed/${penId}?${embedParams.toString()}`;
|
|
1279
|
-
return
|
|
1280
|
-
<div class="${classes}">
|
|
1468
|
+
return `<div class="${classes}">
|
|
1281
1469
|
<iframe
|
|
1282
1470
|
height="${height}"
|
|
1283
1471
|
style="width: 100%; border: 0;"
|
|
@@ -1301,8 +1489,7 @@ function renderVimeoEmbed(url, options, classes) {
|
|
|
1301
1489
|
if (options.mute === "1") params.set("muted", "1");
|
|
1302
1490
|
if (options.loop === "1") params.set("loop", "1");
|
|
1303
1491
|
const embedUrl = `https://player.vimeo.com/video/${videoId}?${params.toString()}`;
|
|
1304
|
-
return
|
|
1305
|
-
<div class="${classes}">
|
|
1492
|
+
return `<div class="${classes}">
|
|
1306
1493
|
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
|
|
1307
1494
|
<iframe
|
|
1308
1495
|
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 0;"
|
|
@@ -1318,8 +1505,7 @@ function renderVimeoEmbed(url, options, classes) {
|
|
|
1318
1505
|
function renderSpotifyEmbed(url, options, classes) {
|
|
1319
1506
|
const embedUrl = url.replace("open.spotify.com", "open.spotify.com/embed");
|
|
1320
1507
|
const height = options.height || "380";
|
|
1321
|
-
return
|
|
1322
|
-
<div class="${classes}">
|
|
1508
|
+
return `<div class="${classes}">
|
|
1323
1509
|
<iframe
|
|
1324
1510
|
style="border-radius: 12px;"
|
|
1325
1511
|
src="${embedUrl}"
|
|
@@ -1342,8 +1528,7 @@ function renderCodeSandboxEmbed(url, options, classes) {
|
|
|
1342
1528
|
if (!embedUrl.includes("?")) {
|
|
1343
1529
|
embedUrl += `?view=${view}`;
|
|
1344
1530
|
}
|
|
1345
|
-
return
|
|
1346
|
-
<div class="${classes}">
|
|
1531
|
+
return `<div class="${classes}">
|
|
1347
1532
|
<iframe
|
|
1348
1533
|
src="${embedUrl}"
|
|
1349
1534
|
style="width: 100%; height: ${height}px; border: 0; border-radius: 4px; overflow: hidden;"
|
|
@@ -1356,8 +1541,7 @@ function renderCodeSandboxEmbed(url, options, classes) {
|
|
|
1356
1541
|
function renderFigmaEmbed(url, options, classes) {
|
|
1357
1542
|
const embedUrl = `https://www.figma.com/embed?embed_host=share&url=${encodeURIComponent(url)}`;
|
|
1358
1543
|
const height = options.height || "450";
|
|
1359
|
-
return
|
|
1360
|
-
<div class="${classes}">
|
|
1544
|
+
return `<div class="${classes}">
|
|
1361
1545
|
<iframe
|
|
1362
1546
|
style="border: none;"
|
|
1363
1547
|
width="100%"
|
|
@@ -1368,8 +1552,7 @@ function renderFigmaEmbed(url, options, classes) {
|
|
|
1368
1552
|
</div>`;
|
|
1369
1553
|
}
|
|
1370
1554
|
function renderTwitterEmbed(url, _options, classes) {
|
|
1371
|
-
return
|
|
1372
|
-
<div class="${classes}">
|
|
1555
|
+
return `<div class="${classes}">
|
|
1373
1556
|
<div class="p-4">
|
|
1374
1557
|
<div class="flex items-center gap-3 mb-3">
|
|
1375
1558
|
<svg class="w-6 h-6 fill-current text-blue-500" viewBox="0 0 24 24">
|
|
@@ -1397,8 +1580,7 @@ function renderGitHubEmbed(url, _options, classes) {
|
|
|
1397
1580
|
if (!owner || !repo) {
|
|
1398
1581
|
return createErrorEmbed("Invalid GitHub URL", url, classes);
|
|
1399
1582
|
}
|
|
1400
|
-
return
|
|
1401
|
-
<div class="${classes}">
|
|
1583
|
+
return `<div class="${classes}">
|
|
1402
1584
|
<div class="p-4">
|
|
1403
1585
|
<div class="flex items-center gap-3 mb-3">
|
|
1404
1586
|
<svg class="w-6 h-6 fill-current" viewBox="0 0 24 24">
|
|
@@ -1421,8 +1603,7 @@ function renderGitHubEmbed(url, _options, classes) {
|
|
|
1421
1603
|
}
|
|
1422
1604
|
function renderGenericEmbed(url, _options, classes) {
|
|
1423
1605
|
const domain = extractDomain(url);
|
|
1424
|
-
return
|
|
1425
|
-
<div class="${classes}">
|
|
1606
|
+
return `<div class="${classes}">
|
|
1426
1607
|
<div class="p-4">
|
|
1427
1608
|
<div class="flex items-center gap-3 mb-3">
|
|
1428
1609
|
<div class="w-10 h-10 rounded-lg bg-muted flex items-center justify-center">
|
|
@@ -1446,8 +1627,7 @@ function renderGenericEmbed(url, _options, classes) {
|
|
|
1446
1627
|
</div>`;
|
|
1447
1628
|
}
|
|
1448
1629
|
function createErrorEmbed(error, url, classes) {
|
|
1449
|
-
return
|
|
1450
|
-
<div class="${classes}">
|
|
1630
|
+
return `<div class="${classes}">
|
|
1451
1631
|
<div class="p-4 text-destructive">
|
|
1452
1632
|
<div class="font-medium flex items-center gap-2">
|
|
1453
1633
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
@@ -1481,19 +1661,54 @@ var ChangerawrMarkdown = class {
|
|
|
1481
1661
|
this.extensions = /* @__PURE__ */ new Map();
|
|
1482
1662
|
this.parser = new MarkdownParser(config?.parser);
|
|
1483
1663
|
this.renderer = new MarkdownRenderer(config?.renderer);
|
|
1484
|
-
this.
|
|
1664
|
+
this.registerCoreExtensions();
|
|
1665
|
+
this.registerFeatureExtensions();
|
|
1485
1666
|
if (config?.extensions) {
|
|
1486
1667
|
config.extensions.forEach((extension) => {
|
|
1487
1668
|
this.registerExtension(extension);
|
|
1488
1669
|
});
|
|
1489
1670
|
}
|
|
1490
|
-
this.parser.setupDefaultRulesIfEmpty();
|
|
1491
1671
|
}
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1672
|
+
registerFeatureExtensions() {
|
|
1673
|
+
this.registerExtension(AlertExtension);
|
|
1674
|
+
this.registerExtension(ButtonExtension);
|
|
1675
|
+
this.registerExtension(EmbedExtension);
|
|
1676
|
+
}
|
|
1677
|
+
registerCoreExtensions() {
|
|
1678
|
+
CoreExtensions.forEach((extension) => {
|
|
1679
|
+
this.registerExtension(extension);
|
|
1680
|
+
});
|
|
1681
|
+
}
|
|
1495
1682
|
registerExtension(extension) {
|
|
1496
1683
|
try {
|
|
1684
|
+
if (!extension.name || typeof extension.name !== "string") {
|
|
1685
|
+
throw new Error("Extension must have a valid name");
|
|
1686
|
+
}
|
|
1687
|
+
if (!Array.isArray(extension.parseRules)) {
|
|
1688
|
+
throw new Error("Extension must have parseRules array");
|
|
1689
|
+
}
|
|
1690
|
+
if (!Array.isArray(extension.renderRules)) {
|
|
1691
|
+
throw new Error("Extension must have renderRules array");
|
|
1692
|
+
}
|
|
1693
|
+
extension.parseRules.forEach((rule, index) => {
|
|
1694
|
+
if (!rule.name || typeof rule.name !== "string") {
|
|
1695
|
+
throw new Error(`Parse rule ${index} must have a valid name`);
|
|
1696
|
+
}
|
|
1697
|
+
if (!rule.pattern || !(rule.pattern instanceof RegExp)) {
|
|
1698
|
+
throw new Error(`Parse rule ${index} must have a valid RegExp pattern`);
|
|
1699
|
+
}
|
|
1700
|
+
if (!rule.render || typeof rule.render !== "function") {
|
|
1701
|
+
throw new Error(`Parse rule ${index} must have a valid render function`);
|
|
1702
|
+
}
|
|
1703
|
+
});
|
|
1704
|
+
extension.renderRules.forEach((rule, index) => {
|
|
1705
|
+
if (!rule.type || typeof rule.type !== "string") {
|
|
1706
|
+
throw new Error(`Render rule ${index} must have a valid type`);
|
|
1707
|
+
}
|
|
1708
|
+
if (!rule.render || typeof rule.render !== "function") {
|
|
1709
|
+
throw new Error(`Render rule ${index} must have a valid render function`);
|
|
1710
|
+
}
|
|
1711
|
+
});
|
|
1497
1712
|
this.extensions.set(extension.name, extension);
|
|
1498
1713
|
extension.parseRules.forEach((rule) => {
|
|
1499
1714
|
this.parser.addRule(rule);
|
|
@@ -1514,9 +1729,6 @@ var ChangerawrMarkdown = class {
|
|
|
1514
1729
|
};
|
|
1515
1730
|
}
|
|
1516
1731
|
}
|
|
1517
|
-
/**
|
|
1518
|
-
* Unregister an extension
|
|
1519
|
-
*/
|
|
1520
1732
|
unregisterExtension(name) {
|
|
1521
1733
|
const extension = this.extensions.get(name);
|
|
1522
1734
|
if (!extension) {
|
|
@@ -1530,46 +1742,25 @@ var ChangerawrMarkdown = class {
|
|
|
1530
1742
|
return false;
|
|
1531
1743
|
}
|
|
1532
1744
|
}
|
|
1533
|
-
/**
|
|
1534
|
-
* Parse markdown content into tokens
|
|
1535
|
-
*/
|
|
1536
1745
|
parse(markdown3) {
|
|
1537
1746
|
return this.parser.parse(markdown3);
|
|
1538
1747
|
}
|
|
1539
|
-
/**
|
|
1540
|
-
* Render tokens to HTML
|
|
1541
|
-
*/
|
|
1542
1748
|
render(tokens) {
|
|
1543
1749
|
return this.renderer.render(tokens);
|
|
1544
1750
|
}
|
|
1545
|
-
/**
|
|
1546
|
-
* Parse and render markdown to HTML in one step
|
|
1547
|
-
*/
|
|
1548
1751
|
toHtml(markdown3) {
|
|
1549
1752
|
const tokens = this.parse(markdown3);
|
|
1550
1753
|
return this.render(tokens);
|
|
1551
1754
|
}
|
|
1552
|
-
/**
|
|
1553
|
-
* Get list of registered extensions
|
|
1554
|
-
*/
|
|
1555
1755
|
getExtensions() {
|
|
1556
1756
|
return Array.from(this.extensions.keys());
|
|
1557
1757
|
}
|
|
1558
|
-
/**
|
|
1559
|
-
* Check if extension is registered
|
|
1560
|
-
*/
|
|
1561
1758
|
hasExtension(name) {
|
|
1562
1759
|
return this.extensions.has(name);
|
|
1563
1760
|
}
|
|
1564
|
-
/**
|
|
1565
|
-
* Get parser warnings
|
|
1566
|
-
*/
|
|
1567
1761
|
getWarnings() {
|
|
1568
1762
|
return [...this.parser.getWarnings(), ...this.renderer.getWarnings()];
|
|
1569
1763
|
}
|
|
1570
|
-
/**
|
|
1571
|
-
* Get debug information from last render
|
|
1572
|
-
*/
|
|
1573
1764
|
getDebugInfo() {
|
|
1574
1765
|
return {
|
|
1575
1766
|
warnings: this.getWarnings(),
|
|
@@ -1579,9 +1770,6 @@ var ChangerawrMarkdown = class {
|
|
|
1579
1770
|
iterationCount: 0
|
|
1580
1771
|
};
|
|
1581
1772
|
}
|
|
1582
|
-
/**
|
|
1583
|
-
* Get performance metrics for the last operation
|
|
1584
|
-
*/
|
|
1585
1773
|
getPerformanceMetrics() {
|
|
1586
1774
|
return {
|
|
1587
1775
|
parseTime: 0,
|
|
@@ -1590,28 +1778,29 @@ var ChangerawrMarkdown = class {
|
|
|
1590
1778
|
tokenCount: 0
|
|
1591
1779
|
};
|
|
1592
1780
|
}
|
|
1593
|
-
/**
|
|
1594
|
-
* Register built-in extensions
|
|
1595
|
-
*/
|
|
1596
|
-
registerBuiltInExtensions() {
|
|
1597
|
-
this.registerExtension(AlertExtension);
|
|
1598
|
-
this.registerExtension(ButtonExtension);
|
|
1599
|
-
this.registerExtension(EmbedExtension);
|
|
1600
|
-
}
|
|
1601
|
-
/**
|
|
1602
|
-
* Rebuild parser and renderer with current extensions
|
|
1603
|
-
*/
|
|
1604
1781
|
rebuildParserAndRenderer() {
|
|
1605
1782
|
const parserConfig = this.parser.getConfig();
|
|
1606
1783
|
const rendererConfig = this.renderer.getConfig();
|
|
1607
1784
|
this.parser = new MarkdownParser(parserConfig);
|
|
1608
1785
|
this.renderer = new MarkdownRenderer(rendererConfig);
|
|
1609
1786
|
const extensionsToRegister = Array.from(this.extensions.values());
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1787
|
+
const featureExtensions = extensionsToRegister.filter(
|
|
1788
|
+
(ext) => ["alert", "button", "embed"].includes(ext.name)
|
|
1789
|
+
);
|
|
1790
|
+
const coreExtensions = extensionsToRegister.filter(
|
|
1791
|
+
(ext) => ["text", "heading", "bold", "italic", "code", "codeblock", "link", "image", "list", "task-list", "blockquote", "hr", "paragraph", "line-break"].includes(ext.name)
|
|
1792
|
+
);
|
|
1793
|
+
const customExtensions = extensionsToRegister.filter(
|
|
1794
|
+
(ext) => !["alert", "button", "embed", "text", "heading", "bold", "italic", "code", "codeblock", "link", "image", "list", "task-list", "blockquote", "hr", "paragraph", "line-break"].includes(ext.name)
|
|
1795
|
+
);
|
|
1796
|
+
[...featureExtensions, ...coreExtensions, ...customExtensions].forEach((extension) => {
|
|
1797
|
+
extension.parseRules.forEach((rule) => {
|
|
1798
|
+
this.parser.addRule(rule);
|
|
1799
|
+
});
|
|
1800
|
+
extension.renderRules.forEach((rule) => {
|
|
1801
|
+
this.renderer.addRule(rule);
|
|
1802
|
+
});
|
|
1613
1803
|
});
|
|
1614
|
-
this.parser.setupDefaultRulesIfEmpty();
|
|
1615
1804
|
}
|
|
1616
1805
|
};
|
|
1617
1806
|
var markdown = new ChangerawrMarkdown();
|
|
@@ -2041,8 +2230,7 @@ function createHTMLEngine(config) {
|
|
|
2041
2230
|
renderer: {
|
|
2042
2231
|
format: "html",
|
|
2043
2232
|
sanitize: true,
|
|
2044
|
-
allowUnsafeHtml: false
|
|
2045
|
-
...config?.parser
|
|
2233
|
+
allowUnsafeHtml: false
|
|
2046
2234
|
}
|
|
2047
2235
|
});
|
|
2048
2236
|
}
|
|
@@ -2052,8 +2240,7 @@ function createTailwindEngine(config) {
|
|
|
2052
2240
|
renderer: {
|
|
2053
2241
|
format: "tailwind",
|
|
2054
2242
|
sanitize: true,
|
|
2055
|
-
allowUnsafeHtml: false
|
|
2056
|
-
...config?.parser
|
|
2243
|
+
allowUnsafeHtml: false
|
|
2057
2244
|
}
|
|
2058
2245
|
});
|
|
2059
2246
|
}
|
|
@@ -2072,21 +2259,18 @@ function createDebugEngine(config) {
|
|
|
2072
2259
|
}
|
|
2073
2260
|
});
|
|
2074
2261
|
}
|
|
2075
|
-
function createMinimalEngine(
|
|
2076
|
-
const engine = new ChangerawrMarkdown(
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
if (engine.hasExtension("embed")) {
|
|
2088
|
-
engine.unregisterExtension("embed");
|
|
2089
|
-
}
|
|
2262
|
+
function createMinimalEngine(extensions = []) {
|
|
2263
|
+
const engine = new ChangerawrMarkdown();
|
|
2264
|
+
const defaultExtensions = engine.getExtensions();
|
|
2265
|
+
defaultExtensions.forEach((ext) => engine.unregisterExtension(ext));
|
|
2266
|
+
extensions.forEach((ext) => engine.registerExtension(ext));
|
|
2267
|
+
return engine;
|
|
2268
|
+
}
|
|
2269
|
+
function createCoreOnlyEngine(config) {
|
|
2270
|
+
const engine = new ChangerawrMarkdown(config);
|
|
2271
|
+
engine.unregisterExtension("alert");
|
|
2272
|
+
engine.unregisterExtension("button");
|
|
2273
|
+
engine.unregisterExtension("embed");
|
|
2090
2274
|
return engine;
|
|
2091
2275
|
}
|
|
2092
2276
|
function createCustomEngine(extensions, config) {
|
|
@@ -2110,6 +2294,7 @@ var markdown2 = {
|
|
|
2110
2294
|
createTailwindEngine,
|
|
2111
2295
|
createDebugEngine,
|
|
2112
2296
|
createMinimalEngine,
|
|
2297
|
+
createCoreOnlyEngine,
|
|
2113
2298
|
createCustomEngine,
|
|
2114
2299
|
// Standalone functions
|
|
2115
2300
|
renderCum,
|
|
@@ -2118,6 +2303,24 @@ var markdown2 = {
|
|
|
2118
2303
|
ChangerawrMarkdown,
|
|
2119
2304
|
// Extensions
|
|
2120
2305
|
extensions: {
|
|
2306
|
+
// All core extensions as a bundle
|
|
2307
|
+
core: CoreExtensions,
|
|
2308
|
+
// Individual core extensions
|
|
2309
|
+
Text: TextExtension,
|
|
2310
|
+
Heading: HeadingExtension,
|
|
2311
|
+
Bold: BoldExtension,
|
|
2312
|
+
Italic: ItalicExtension,
|
|
2313
|
+
InlineCode: InlineCodeExtension,
|
|
2314
|
+
CodeBlock: CodeBlockExtension,
|
|
2315
|
+
Link: LinkExtension,
|
|
2316
|
+
Image: ImageExtension,
|
|
2317
|
+
List: ListExtension,
|
|
2318
|
+
TaskList: TaskListExtension,
|
|
2319
|
+
Blockquote: BlockquoteExtension,
|
|
2320
|
+
HorizontalRule: HorizontalRuleExtension,
|
|
2321
|
+
Paragraph: ParagraphExtension,
|
|
2322
|
+
LineBreak: LineBreakExtension,
|
|
2323
|
+
// Feature extensions
|
|
2121
2324
|
Alert: AlertExtension,
|
|
2122
2325
|
Button: ButtonExtension,
|
|
2123
2326
|
Embed: EmbedExtension
|
|
@@ -2178,6 +2381,14 @@ var presets = {
|
|
|
2178
2381
|
sanitize: true
|
|
2179
2382
|
}
|
|
2180
2383
|
},
|
|
2384
|
+
/**
|
|
2385
|
+
* Core-only preset with just markdown basics
|
|
2386
|
+
*/
|
|
2387
|
+
coreOnly: {
|
|
2388
|
+
renderer: {
|
|
2389
|
+
format: "tailwind"
|
|
2390
|
+
}
|
|
2391
|
+
},
|
|
2181
2392
|
/**
|
|
2182
2393
|
* Performance preset with minimal processing
|
|
2183
2394
|
*/
|
|
@@ -2194,6 +2405,9 @@ var presets = {
|
|
|
2194
2405
|
};
|
|
2195
2406
|
function createEngineWithPreset(presetName, additionalConfig) {
|
|
2196
2407
|
const preset = presets[presetName];
|
|
2408
|
+
if (presetName === "coreOnly") {
|
|
2409
|
+
return createCoreOnlyEngine(additionalConfig);
|
|
2410
|
+
}
|
|
2197
2411
|
return new ChangerawrMarkdown({
|
|
2198
2412
|
...preset,
|
|
2199
2413
|
...additionalConfig
|
|
@@ -2202,17 +2416,33 @@ function createEngineWithPreset(presetName, additionalConfig) {
|
|
|
2202
2416
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2203
2417
|
0 && (module.exports = {
|
|
2204
2418
|
AlertExtension,
|
|
2419
|
+
BlockquoteExtension,
|
|
2420
|
+
BoldExtension,
|
|
2205
2421
|
ButtonExtension,
|
|
2206
2422
|
ChangerawrMarkdown,
|
|
2423
|
+
CodeBlockExtension,
|
|
2424
|
+
CoreExtensions,
|
|
2207
2425
|
EmbedExtension,
|
|
2426
|
+
HeadingExtension,
|
|
2427
|
+
HorizontalRuleExtension,
|
|
2428
|
+
ImageExtension,
|
|
2429
|
+
InlineCodeExtension,
|
|
2430
|
+
ItalicExtension,
|
|
2431
|
+
LineBreakExtension,
|
|
2432
|
+
LinkExtension,
|
|
2433
|
+
ListExtension,
|
|
2208
2434
|
Logger,
|
|
2209
2435
|
MarkdownParser,
|
|
2210
2436
|
MarkdownRenderer,
|
|
2437
|
+
ParagraphExtension,
|
|
2211
2438
|
PerformanceTimer,
|
|
2439
|
+
TaskListExtension,
|
|
2440
|
+
TextExtension,
|
|
2212
2441
|
astToJSONString,
|
|
2213
2442
|
astToTokens,
|
|
2214
2443
|
basicSanitize,
|
|
2215
2444
|
compareTokens,
|
|
2445
|
+
createCoreOnlyEngine,
|
|
2216
2446
|
createCumEngine,
|
|
2217
2447
|
createCustomEngine,
|
|
2218
2448
|
createDebugEngine,
|