@changerawr/markdown 1.1.7 → 1.1.9
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/dist/index.d.mts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +153 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +153 -14
- package/dist/index.mjs.map +1 -1
- package/dist/react/index.js +153 -14
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +153 -14
- package/dist/react/index.mjs.map +1 -1
- package/dist/standalone.browser.js +178 -26
- package/dist/standalone.js +153 -14
- package/dist/standalone.js.map +1 -1
- package/dist/standalone.mjs +153 -14
- package/dist/standalone.mjs.map +1 -1
- package/package.json +1 -1
package/dist/react/index.js
CHANGED
|
@@ -530,20 +530,59 @@ var MarkdownRenderer = class {
|
|
|
530
530
|
format: this.config.format
|
|
531
531
|
}
|
|
532
532
|
}));
|
|
533
|
-
const
|
|
533
|
+
const groupedTokens = this.groupListItems(tokensWithFormat);
|
|
534
|
+
const htmlParts = groupedTokens.map((token) => this.renderToken(token));
|
|
534
535
|
const combinedHtml = htmlParts.join("");
|
|
535
536
|
if (this.config.sanitize && !this.config.allowUnsafeHtml) {
|
|
536
537
|
return sanitizeHtml(combinedHtml);
|
|
537
538
|
}
|
|
538
539
|
return combinedHtml;
|
|
539
540
|
}
|
|
541
|
+
groupListItems(tokens) {
|
|
542
|
+
const result = [];
|
|
543
|
+
let i = 0;
|
|
544
|
+
while (i < tokens.length) {
|
|
545
|
+
const token = tokens[i];
|
|
546
|
+
const isListItem = token?.type === "list-item" || token?.type === "ordered-list-item" || token?.type === "task-item";
|
|
547
|
+
if (isListItem) {
|
|
548
|
+
const listItems = [];
|
|
549
|
+
const firstItemType = token.type;
|
|
550
|
+
const isOrdered = firstItemType === "ordered-list-item";
|
|
551
|
+
while (i < tokens.length) {
|
|
552
|
+
const item = tokens[i];
|
|
553
|
+
if (!item) break;
|
|
554
|
+
const itemType = item.type;
|
|
555
|
+
const isSameListType = isOrdered && itemType === "ordered-list-item" || !isOrdered && (itemType === "list-item" || itemType === "task-item");
|
|
556
|
+
if (isSameListType) {
|
|
557
|
+
listItems.push(item);
|
|
558
|
+
i++;
|
|
559
|
+
} else {
|
|
560
|
+
break;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
const wrappedList = {
|
|
564
|
+
type: isOrdered ? "ol" : "ul",
|
|
565
|
+
content: "",
|
|
566
|
+
raw: "",
|
|
567
|
+
children: listItems,
|
|
568
|
+
attributes: { format: this.config.format }
|
|
569
|
+
};
|
|
570
|
+
wrappedList._isWrapped = true;
|
|
571
|
+
result.push(wrappedList);
|
|
572
|
+
} else {
|
|
573
|
+
result.push(token);
|
|
574
|
+
i++;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
return result;
|
|
578
|
+
}
|
|
540
579
|
renderToken(token) {
|
|
541
580
|
const rule = this.rules.get(token.type);
|
|
542
581
|
if (rule) {
|
|
543
582
|
try {
|
|
544
583
|
let tokenToRender = token;
|
|
545
584
|
if (token.children && token.children.length > 0) {
|
|
546
|
-
const renderedChildren = this.render(token.children);
|
|
585
|
+
const renderedChildren = token.type === "ul" || token.type === "ol" ? token.children.map((child) => this.renderToken(child)).join("") : this.render(token.children);
|
|
547
586
|
tokenToRender = {
|
|
548
587
|
...token,
|
|
549
588
|
attributes: {
|
|
@@ -1044,7 +1083,8 @@ var ImageExtension = {
|
|
|
1044
1083
|
attributes: {
|
|
1045
1084
|
alt: match[1] || "",
|
|
1046
1085
|
src: match[2] || "",
|
|
1047
|
-
|
|
1086
|
+
caption: match[3] || ""
|
|
1087
|
+
// Renamed from 'title' to 'caption' for clarity
|
|
1048
1088
|
}
|
|
1049
1089
|
})
|
|
1050
1090
|
}
|
|
@@ -1055,13 +1095,24 @@ var ImageExtension = {
|
|
|
1055
1095
|
render: (token) => {
|
|
1056
1096
|
const src = token.attributes?.src || "";
|
|
1057
1097
|
const alt = token.attributes?.alt || "";
|
|
1058
|
-
const
|
|
1059
|
-
const titleAttr = title ? ` title="${escapeHtml(title)}"` : "";
|
|
1098
|
+
const caption = token.attributes?.caption || "";
|
|
1060
1099
|
const format = token.attributes?.format || "html";
|
|
1100
|
+
if (caption) {
|
|
1101
|
+
if (format === "html") {
|
|
1102
|
+
return `<figure style="margin: 16px 0; text-align: center;">
|
|
1103
|
+
<img src="${escapeHtml(src)}" alt="${escapeHtml(alt)}" style="max-width: 100%; height: auto; border-radius: 8px;" loading="lazy" />
|
|
1104
|
+
<figcaption style="margin-top: 8px; font-size: 14px; color: #6b7280; font-style: italic;">${escapeHtml(caption)}</figcaption>
|
|
1105
|
+
</figure>`;
|
|
1106
|
+
}
|
|
1107
|
+
return `<figure class="my-4 text-center">
|
|
1108
|
+
<img src="${escapeHtml(src)}" alt="${escapeHtml(alt)}" class="max-w-full h-auto rounded-lg" loading="lazy" />
|
|
1109
|
+
<figcaption class="mt-2 text-sm text-gray-500 italic">${escapeHtml(caption)}</figcaption>
|
|
1110
|
+
</figure>`;
|
|
1111
|
+
}
|
|
1061
1112
|
if (format === "html") {
|
|
1062
|
-
return `<img src="${escapeHtml(src)}" alt="${escapeHtml(alt)}"
|
|
1113
|
+
return `<img src="${escapeHtml(src)}" alt="${escapeHtml(alt)}" style="max-width: 100%; height: auto; border-radius: 8px; margin: 16px 0;" loading="lazy" />`;
|
|
1063
1114
|
}
|
|
1064
|
-
return `<img src="${escapeHtml(src)}" alt="${escapeHtml(alt)}"
|
|
1115
|
+
return `<img src="${escapeHtml(src)}" alt="${escapeHtml(alt)}" class="max-w-full h-auto rounded-lg my-4" loading="lazy" />`;
|
|
1065
1116
|
}
|
|
1066
1117
|
}
|
|
1067
1118
|
]
|
|
@@ -1113,16 +1164,57 @@ var ListExtension = {
|
|
|
1113
1164
|
name: "list",
|
|
1114
1165
|
parseRules: [
|
|
1115
1166
|
{
|
|
1116
|
-
name: "list-item",
|
|
1167
|
+
name: "unordered-list-item",
|
|
1117
1168
|
pattern: /^(\s*)[-*+]\s+(.+)$/m,
|
|
1118
1169
|
render: (match) => ({
|
|
1119
1170
|
type: "list-item",
|
|
1120
1171
|
content: match[2] || "",
|
|
1121
|
-
raw: match[0] || ""
|
|
1172
|
+
raw: match[0] || "",
|
|
1173
|
+
attributes: {
|
|
1174
|
+
indent: match[1]?.length || 0,
|
|
1175
|
+
ordered: false,
|
|
1176
|
+
marker: match[1] ? match[0].match(/[-*+]/)?.[0] : "-"
|
|
1177
|
+
}
|
|
1178
|
+
})
|
|
1179
|
+
},
|
|
1180
|
+
{
|
|
1181
|
+
name: "ordered-list-item",
|
|
1182
|
+
pattern: /^(\s*)(\d+)\.\s+(.+)$/m,
|
|
1183
|
+
render: (match) => ({
|
|
1184
|
+
type: "ordered-list-item",
|
|
1185
|
+
content: match[3] || "",
|
|
1186
|
+
raw: match[0] || "",
|
|
1187
|
+
attributes: {
|
|
1188
|
+
indent: match[1]?.length || 0,
|
|
1189
|
+
ordered: true,
|
|
1190
|
+
number: parseInt(match[2] || "1")
|
|
1191
|
+
}
|
|
1122
1192
|
})
|
|
1123
1193
|
}
|
|
1124
1194
|
],
|
|
1125
1195
|
renderRules: [
|
|
1196
|
+
{
|
|
1197
|
+
type: "ul",
|
|
1198
|
+
render: (token) => {
|
|
1199
|
+
const format = token.attributes?.format || "tailwind";
|
|
1200
|
+
const content = token.attributes?.renderedChildren || "";
|
|
1201
|
+
if (format === "html") {
|
|
1202
|
+
return `<ul style="margin: 8px 0; padding-left: 24px; list-style: disc;">${content}</ul>`;
|
|
1203
|
+
}
|
|
1204
|
+
return `<ul class="my-2 pl-6 list-disc">${content}</ul>`;
|
|
1205
|
+
}
|
|
1206
|
+
},
|
|
1207
|
+
{
|
|
1208
|
+
type: "ol",
|
|
1209
|
+
render: (token) => {
|
|
1210
|
+
const format = token.attributes?.format || "tailwind";
|
|
1211
|
+
const content = token.attributes?.renderedChildren || "";
|
|
1212
|
+
if (format === "html") {
|
|
1213
|
+
return `<ol style="margin: 8px 0; padding-left: 24px; list-style: decimal;">${content}</ol>`;
|
|
1214
|
+
}
|
|
1215
|
+
return `<ol class="my-2 pl-6 list-decimal">${content}</ol>`;
|
|
1216
|
+
}
|
|
1217
|
+
},
|
|
1126
1218
|
{
|
|
1127
1219
|
type: "list-item",
|
|
1128
1220
|
render: (token) => {
|
|
@@ -1133,6 +1225,17 @@ var ListExtension = {
|
|
|
1133
1225
|
}
|
|
1134
1226
|
return `<li>${content}</li>`;
|
|
1135
1227
|
}
|
|
1228
|
+
},
|
|
1229
|
+
{
|
|
1230
|
+
type: "ordered-list-item",
|
|
1231
|
+
render: (token) => {
|
|
1232
|
+
const format = token.attributes?.format || "tailwind";
|
|
1233
|
+
const content = token.attributes?.renderedChildren || escapeHtml(token.content);
|
|
1234
|
+
if (format === "html") {
|
|
1235
|
+
return `<li>${content}</li>`;
|
|
1236
|
+
}
|
|
1237
|
+
return `<li>${content}</li>`;
|
|
1238
|
+
}
|
|
1136
1239
|
}
|
|
1137
1240
|
]
|
|
1138
1241
|
};
|
|
@@ -1147,6 +1250,7 @@ var TaskListExtension = {
|
|
|
1147
1250
|
content: match[3] || "",
|
|
1148
1251
|
raw: match[0] || "",
|
|
1149
1252
|
attributes: {
|
|
1253
|
+
indent: match[1]?.length || 0,
|
|
1150
1254
|
checked: String((match[2] || "").toLowerCase() === "x")
|
|
1151
1255
|
}
|
|
1152
1256
|
})
|
|
@@ -1159,15 +1263,20 @@ var TaskListExtension = {
|
|
|
1159
1263
|
const isChecked = token.attributes?.checked === "true";
|
|
1160
1264
|
const content = token.attributes?.renderedChildren || escapeHtml(token.content);
|
|
1161
1265
|
const format = token.attributes?.format || "html";
|
|
1266
|
+
const checkmark = `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="flex-shrink: 0; margin-top: 2px;"><polyline points="20 6 9 17 4 12"></polyline></svg>`;
|
|
1267
|
+
const checkbox = `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="flex-shrink: 0; margin-top: 2px;"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect></svg>`;
|
|
1162
1268
|
if (format === "html") {
|
|
1163
|
-
return `<div style="display: flex; align-items:
|
|
1164
|
-
<
|
|
1269
|
+
return `<div style="display: flex; align-items: flex-start; gap: 8px; margin: 8px 0;">
|
|
1270
|
+
<div style="color: ${isChecked ? "#10b981" : "#9ca3af"}; margin-top: 2px;">
|
|
1271
|
+
${isChecked ? checkmark : checkbox}
|
|
1272
|
+
</div>
|
|
1165
1273
|
<span${isChecked ? ' style="text-decoration: line-through; color: #6b7280;"' : ""}>${content}</span>
|
|
1166
1274
|
</div>`;
|
|
1167
1275
|
}
|
|
1168
|
-
return `<div class="flex items-
|
|
1169
|
-
<
|
|
1170
|
-
|
|
1276
|
+
return `<div class="flex items-start gap-2 my-2 task-list-item">
|
|
1277
|
+
<div class="${isChecked ? "text-green-600" : "text-gray-400"} flex-shrink-0 mt-0.5">
|
|
1278
|
+
${isChecked ? checkmark : checkbox}
|
|
1279
|
+
</div>
|
|
1171
1280
|
<span${isChecked ? ' class="line-through text-muted-foreground"' : ""}>${content}</span>
|
|
1172
1281
|
</div>`;
|
|
1173
1282
|
}
|
|
@@ -1212,6 +1321,35 @@ var TextExtension = {
|
|
|
1212
1321
|
]
|
|
1213
1322
|
};
|
|
1214
1323
|
|
|
1324
|
+
// src/extensions/core/strikethrough.ts
|
|
1325
|
+
var StrikethroughExtension = {
|
|
1326
|
+
name: "strikethrough",
|
|
1327
|
+
parseRules: [
|
|
1328
|
+
{
|
|
1329
|
+
name: "strikethrough",
|
|
1330
|
+
pattern: /~~((?:(?!~~).)+)~~/,
|
|
1331
|
+
render: (match) => ({
|
|
1332
|
+
type: "strikethrough",
|
|
1333
|
+
content: match[1] || "",
|
|
1334
|
+
raw: match[0] || ""
|
|
1335
|
+
})
|
|
1336
|
+
}
|
|
1337
|
+
],
|
|
1338
|
+
renderRules: [
|
|
1339
|
+
{
|
|
1340
|
+
type: "strikethrough",
|
|
1341
|
+
render: (token) => {
|
|
1342
|
+
const content = escapeHtml(token.content);
|
|
1343
|
+
const format = token.attributes?.format;
|
|
1344
|
+
if (format === "html") {
|
|
1345
|
+
return `<del style="text-decoration: line-through; color: #6b7280;">${content}</del>`;
|
|
1346
|
+
}
|
|
1347
|
+
return `<del class="line-through text-gray-500">${content}</del>`;
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
]
|
|
1351
|
+
};
|
|
1352
|
+
|
|
1215
1353
|
// src/extensions/core/index.ts
|
|
1216
1354
|
var CoreExtensions = [
|
|
1217
1355
|
TextExtension,
|
|
@@ -1226,6 +1364,7 @@ var CoreExtensions = [
|
|
|
1226
1364
|
TaskListExtension,
|
|
1227
1365
|
BlockquoteExtension,
|
|
1228
1366
|
HorizontalRuleExtension,
|
|
1367
|
+
StrikethroughExtension,
|
|
1229
1368
|
ParagraphExtension,
|
|
1230
1369
|
LineBreakExtension
|
|
1231
1370
|
];
|