@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.mjs CHANGED
@@ -565,20 +565,59 @@ var MarkdownRenderer = class {
565
565
  format: this.config.format
566
566
  }
567
567
  }));
568
- const htmlParts = tokensWithFormat.map((token) => this.renderToken(token));
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
- title: match[3] || ""
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 title = token.attributes?.title || "";
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)}"${titleAttr} style="max-width: 100%; height: auto; border-radius: 8px; margin: 16px 0;" loading="lazy" />`;
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)}"${titleAttr} class="max-w-full h-auto rounded-lg my-4" loading="lazy" />`;
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: center; gap: 8px; margin: 8px 0;">
1216
- <input type="checkbox" ${isChecked ? "checked" : ""} disabled style="margin: 0;" />
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-center gap-2 my-2 task-list-item">
1221
- <input type="checkbox" ${isChecked ? "checked" : ""} disabled
1222
- class="form-checkbox h-4 w-4 rounded border-gray-300 text-primary focus:ring-primary" />
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
  ];