@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/index.mjs
CHANGED
|
@@ -565,20 +565,59 @@ var MarkdownRenderer = class {
|
|
|
565
565
|
format: this.config.format
|
|
566
566
|
}
|
|
567
567
|
}));
|
|
568
|
-
const
|
|
568
|
+
const groupedTokens = this.groupListItems(tokensWithFormat);
|
|
569
|
+
const htmlParts = groupedTokens.map((token) => this.renderToken(token));
|
|
569
570
|
const combinedHtml = htmlParts.join("");
|
|
570
571
|
if (this.config.sanitize && !this.config.allowUnsafeHtml) {
|
|
571
572
|
return sanitizeHtml(combinedHtml);
|
|
572
573
|
}
|
|
573
574
|
return combinedHtml;
|
|
574
575
|
}
|
|
576
|
+
groupListItems(tokens) {
|
|
577
|
+
const result = [];
|
|
578
|
+
let i = 0;
|
|
579
|
+
while (i < tokens.length) {
|
|
580
|
+
const token = tokens[i];
|
|
581
|
+
const isListItem = token?.type === "list-item" || token?.type === "ordered-list-item" || token?.type === "task-item";
|
|
582
|
+
if (isListItem) {
|
|
583
|
+
const listItems = [];
|
|
584
|
+
const firstItemType = token.type;
|
|
585
|
+
const isOrdered = firstItemType === "ordered-list-item";
|
|
586
|
+
while (i < tokens.length) {
|
|
587
|
+
const item = tokens[i];
|
|
588
|
+
if (!item) break;
|
|
589
|
+
const itemType = item.type;
|
|
590
|
+
const isSameListType = isOrdered && itemType === "ordered-list-item" || !isOrdered && (itemType === "list-item" || itemType === "task-item");
|
|
591
|
+
if (isSameListType) {
|
|
592
|
+
listItems.push(item);
|
|
593
|
+
i++;
|
|
594
|
+
} else {
|
|
595
|
+
break;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
const wrappedList = {
|
|
599
|
+
type: isOrdered ? "ol" : "ul",
|
|
600
|
+
content: "",
|
|
601
|
+
raw: "",
|
|
602
|
+
children: listItems,
|
|
603
|
+
attributes: { format: this.config.format }
|
|
604
|
+
};
|
|
605
|
+
wrappedList._isWrapped = true;
|
|
606
|
+
result.push(wrappedList);
|
|
607
|
+
} else {
|
|
608
|
+
result.push(token);
|
|
609
|
+
i++;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
return result;
|
|
613
|
+
}
|
|
575
614
|
renderToken(token) {
|
|
576
615
|
const rule = this.rules.get(token.type);
|
|
577
616
|
if (rule) {
|
|
578
617
|
try {
|
|
579
618
|
let tokenToRender = token;
|
|
580
619
|
if (token.children && token.children.length > 0) {
|
|
581
|
-
const renderedChildren = this.render(token.children);
|
|
620
|
+
const renderedChildren = token.type === "ul" || token.type === "ol" ? token.children.map((child) => this.renderToken(child)).join("") : this.render(token.children);
|
|
582
621
|
tokenToRender = {
|
|
583
622
|
...token,
|
|
584
623
|
attributes: {
|
|
@@ -1096,7 +1135,8 @@ var ImageExtension = {
|
|
|
1096
1135
|
attributes: {
|
|
1097
1136
|
alt: match[1] || "",
|
|
1098
1137
|
src: match[2] || "",
|
|
1099
|
-
|
|
1138
|
+
caption: match[3] || ""
|
|
1139
|
+
// Renamed from 'title' to 'caption' for clarity
|
|
1100
1140
|
}
|
|
1101
1141
|
})
|
|
1102
1142
|
}
|
|
@@ -1107,13 +1147,24 @@ var ImageExtension = {
|
|
|
1107
1147
|
render: (token) => {
|
|
1108
1148
|
const src = token.attributes?.src || "";
|
|
1109
1149
|
const alt = token.attributes?.alt || "";
|
|
1110
|
-
const
|
|
1111
|
-
const titleAttr = title ? ` title="${escapeHtml(title)}"` : "";
|
|
1150
|
+
const caption = token.attributes?.caption || "";
|
|
1112
1151
|
const format = token.attributes?.format || "html";
|
|
1152
|
+
if (caption) {
|
|
1153
|
+
if (format === "html") {
|
|
1154
|
+
return `<figure style="margin: 16px 0; text-align: center;">
|
|
1155
|
+
<img src="${escapeHtml(src)}" alt="${escapeHtml(alt)}" style="max-width: 100%; height: auto; border-radius: 8px;" loading="lazy" />
|
|
1156
|
+
<figcaption style="margin-top: 8px; font-size: 14px; color: #6b7280; font-style: italic;">${escapeHtml(caption)}</figcaption>
|
|
1157
|
+
</figure>`;
|
|
1158
|
+
}
|
|
1159
|
+
return `<figure class="my-4 text-center">
|
|
1160
|
+
<img src="${escapeHtml(src)}" alt="${escapeHtml(alt)}" class="max-w-full h-auto rounded-lg" loading="lazy" />
|
|
1161
|
+
<figcaption class="mt-2 text-sm text-gray-500 italic">${escapeHtml(caption)}</figcaption>
|
|
1162
|
+
</figure>`;
|
|
1163
|
+
}
|
|
1113
1164
|
if (format === "html") {
|
|
1114
|
-
return `<img src="${escapeHtml(src)}" alt="${escapeHtml(alt)}"
|
|
1165
|
+
return `<img src="${escapeHtml(src)}" alt="${escapeHtml(alt)}" style="max-width: 100%; height: auto; border-radius: 8px; margin: 16px 0;" loading="lazy" />`;
|
|
1115
1166
|
}
|
|
1116
|
-
return `<img src="${escapeHtml(src)}" alt="${escapeHtml(alt)}"
|
|
1167
|
+
return `<img src="${escapeHtml(src)}" alt="${escapeHtml(alt)}" class="max-w-full h-auto rounded-lg my-4" loading="lazy" />`;
|
|
1117
1168
|
}
|
|
1118
1169
|
}
|
|
1119
1170
|
]
|
|
@@ -1165,16 +1216,57 @@ var ListExtension = {
|
|
|
1165
1216
|
name: "list",
|
|
1166
1217
|
parseRules: [
|
|
1167
1218
|
{
|
|
1168
|
-
name: "list-item",
|
|
1219
|
+
name: "unordered-list-item",
|
|
1169
1220
|
pattern: /^(\s*)[-*+]\s+(.+)$/m,
|
|
1170
1221
|
render: (match) => ({
|
|
1171
1222
|
type: "list-item",
|
|
1172
1223
|
content: match[2] || "",
|
|
1173
|
-
raw: match[0] || ""
|
|
1224
|
+
raw: match[0] || "",
|
|
1225
|
+
attributes: {
|
|
1226
|
+
indent: match[1]?.length || 0,
|
|
1227
|
+
ordered: false,
|
|
1228
|
+
marker: match[1] ? match[0].match(/[-*+]/)?.[0] : "-"
|
|
1229
|
+
}
|
|
1230
|
+
})
|
|
1231
|
+
},
|
|
1232
|
+
{
|
|
1233
|
+
name: "ordered-list-item",
|
|
1234
|
+
pattern: /^(\s*)(\d+)\.\s+(.+)$/m,
|
|
1235
|
+
render: (match) => ({
|
|
1236
|
+
type: "ordered-list-item",
|
|
1237
|
+
content: match[3] || "",
|
|
1238
|
+
raw: match[0] || "",
|
|
1239
|
+
attributes: {
|
|
1240
|
+
indent: match[1]?.length || 0,
|
|
1241
|
+
ordered: true,
|
|
1242
|
+
number: parseInt(match[2] || "1")
|
|
1243
|
+
}
|
|
1174
1244
|
})
|
|
1175
1245
|
}
|
|
1176
1246
|
],
|
|
1177
1247
|
renderRules: [
|
|
1248
|
+
{
|
|
1249
|
+
type: "ul",
|
|
1250
|
+
render: (token) => {
|
|
1251
|
+
const format = token.attributes?.format || "tailwind";
|
|
1252
|
+
const content = token.attributes?.renderedChildren || "";
|
|
1253
|
+
if (format === "html") {
|
|
1254
|
+
return `<ul style="margin: 8px 0; padding-left: 24px; list-style: disc;">${content}</ul>`;
|
|
1255
|
+
}
|
|
1256
|
+
return `<ul class="my-2 pl-6 list-disc">${content}</ul>`;
|
|
1257
|
+
}
|
|
1258
|
+
},
|
|
1259
|
+
{
|
|
1260
|
+
type: "ol",
|
|
1261
|
+
render: (token) => {
|
|
1262
|
+
const format = token.attributes?.format || "tailwind";
|
|
1263
|
+
const content = token.attributes?.renderedChildren || "";
|
|
1264
|
+
if (format === "html") {
|
|
1265
|
+
return `<ol style="margin: 8px 0; padding-left: 24px; list-style: decimal;">${content}</ol>`;
|
|
1266
|
+
}
|
|
1267
|
+
return `<ol class="my-2 pl-6 list-decimal">${content}</ol>`;
|
|
1268
|
+
}
|
|
1269
|
+
},
|
|
1178
1270
|
{
|
|
1179
1271
|
type: "list-item",
|
|
1180
1272
|
render: (token) => {
|
|
@@ -1185,6 +1277,17 @@ var ListExtension = {
|
|
|
1185
1277
|
}
|
|
1186
1278
|
return `<li>${content}</li>`;
|
|
1187
1279
|
}
|
|
1280
|
+
},
|
|
1281
|
+
{
|
|
1282
|
+
type: "ordered-list-item",
|
|
1283
|
+
render: (token) => {
|
|
1284
|
+
const format = token.attributes?.format || "tailwind";
|
|
1285
|
+
const content = token.attributes?.renderedChildren || escapeHtml(token.content);
|
|
1286
|
+
if (format === "html") {
|
|
1287
|
+
return `<li>${content}</li>`;
|
|
1288
|
+
}
|
|
1289
|
+
return `<li>${content}</li>`;
|
|
1290
|
+
}
|
|
1188
1291
|
}
|
|
1189
1292
|
]
|
|
1190
1293
|
};
|
|
@@ -1199,6 +1302,7 @@ var TaskListExtension = {
|
|
|
1199
1302
|
content: match[3] || "",
|
|
1200
1303
|
raw: match[0] || "",
|
|
1201
1304
|
attributes: {
|
|
1305
|
+
indent: match[1]?.length || 0,
|
|
1202
1306
|
checked: String((match[2] || "").toLowerCase() === "x")
|
|
1203
1307
|
}
|
|
1204
1308
|
})
|
|
@@ -1211,15 +1315,20 @@ var TaskListExtension = {
|
|
|
1211
1315
|
const isChecked = token.attributes?.checked === "true";
|
|
1212
1316
|
const content = token.attributes?.renderedChildren || escapeHtml(token.content);
|
|
1213
1317
|
const format = token.attributes?.format || "html";
|
|
1318
|
+
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>`;
|
|
1319
|
+
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>`;
|
|
1214
1320
|
if (format === "html") {
|
|
1215
|
-
return `<div style="display: flex; align-items:
|
|
1216
|
-
<
|
|
1321
|
+
return `<div style="display: flex; align-items: flex-start; gap: 8px; margin: 8px 0;">
|
|
1322
|
+
<div style="color: ${isChecked ? "#10b981" : "#9ca3af"}; margin-top: 2px;">
|
|
1323
|
+
${isChecked ? checkmark : checkbox}
|
|
1324
|
+
</div>
|
|
1217
1325
|
<span${isChecked ? ' style="text-decoration: line-through; color: #6b7280;"' : ""}>${content}</span>
|
|
1218
1326
|
</div>`;
|
|
1219
1327
|
}
|
|
1220
|
-
return `<div class="flex items-
|
|
1221
|
-
<
|
|
1222
|
-
|
|
1328
|
+
return `<div class="flex items-start gap-2 my-2 task-list-item">
|
|
1329
|
+
<div class="${isChecked ? "text-green-600" : "text-gray-400"} flex-shrink-0 mt-0.5">
|
|
1330
|
+
${isChecked ? checkmark : checkbox}
|
|
1331
|
+
</div>
|
|
1223
1332
|
<span${isChecked ? ' class="line-through text-muted-foreground"' : ""}>${content}</span>
|
|
1224
1333
|
</div>`;
|
|
1225
1334
|
}
|
|
@@ -1264,6 +1373,35 @@ var TextExtension = {
|
|
|
1264
1373
|
]
|
|
1265
1374
|
};
|
|
1266
1375
|
|
|
1376
|
+
// src/extensions/core/strikethrough.ts
|
|
1377
|
+
var StrikethroughExtension = {
|
|
1378
|
+
name: "strikethrough",
|
|
1379
|
+
parseRules: [
|
|
1380
|
+
{
|
|
1381
|
+
name: "strikethrough",
|
|
1382
|
+
pattern: /~~((?:(?!~~).)+)~~/,
|
|
1383
|
+
render: (match) => ({
|
|
1384
|
+
type: "strikethrough",
|
|
1385
|
+
content: match[1] || "",
|
|
1386
|
+
raw: match[0] || ""
|
|
1387
|
+
})
|
|
1388
|
+
}
|
|
1389
|
+
],
|
|
1390
|
+
renderRules: [
|
|
1391
|
+
{
|
|
1392
|
+
type: "strikethrough",
|
|
1393
|
+
render: (token) => {
|
|
1394
|
+
const content = escapeHtml(token.content);
|
|
1395
|
+
const format = token.attributes?.format;
|
|
1396
|
+
if (format === "html") {
|
|
1397
|
+
return `<del style="text-decoration: line-through; color: #6b7280;">${content}</del>`;
|
|
1398
|
+
}
|
|
1399
|
+
return `<del class="line-through text-gray-500">${content}</del>`;
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
]
|
|
1403
|
+
};
|
|
1404
|
+
|
|
1267
1405
|
// src/extensions/core/index.ts
|
|
1268
1406
|
var CoreExtensions = [
|
|
1269
1407
|
TextExtension,
|
|
@@ -1278,6 +1416,7 @@ var CoreExtensions = [
|
|
|
1278
1416
|
TaskListExtension,
|
|
1279
1417
|
BlockquoteExtension,
|
|
1280
1418
|
HorizontalRuleExtension,
|
|
1419
|
+
StrikethroughExtension,
|
|
1281
1420
|
ParagraphExtension,
|
|
1282
1421
|
LineBreakExtension
|
|
1283
1422
|
];
|