@lvce-editor/extension-detail-view 3.15.0 → 3.16.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.
@@ -82,12 +82,6 @@ const getType = value => {
82
82
  return 'unknown';
83
83
  }
84
84
  };
85
- const array = value => {
86
- const type = getType(value);
87
- if (type !== 'array') {
88
- throw new AssertionError('expected value to be of type array');
89
- }
90
- };
91
85
  const string = value => {
92
86
  const type = getType(value);
93
87
  if (type !== 'string') {
@@ -896,7 +890,7 @@ const create = (uid, uri, width, height, platform, assetDir$1) => {
896
890
  const AdditionalDetails = 'AdditionalDetails';
897
891
  const AdditionalDetailsEntry = 'AdditionalDetailsEntry';
898
892
  const AdditionalDetailsTitle = 'AdditionalDetailsTitle';
899
- const Aside$2 = 'Aside';
893
+ const Aside = 'Aside';
900
894
  const Button$1 = 'Button';
901
895
  const ButtonPrimary = 'ButtonPrimary';
902
896
  const Categories = 'Categories';
@@ -922,7 +916,6 @@ const Features$1 = 'Features';
922
916
  const FeaturesList = 'FeaturesList';
923
917
  const FeatureWebView = 'FeatureWebView';
924
918
  const Large$1 = 'Large';
925
- const Markdown = 'Markdown';
926
919
  const MoreInfo = 'MoreInfo';
927
920
  const MoreInfoEntry = 'MoreInfoEntry';
928
921
  const MoreInfoEntryKey = 'MoreInfoEntryKey';
@@ -1009,49 +1002,24 @@ const getDisplaySize = size => {
1009
1002
  });
1010
1003
  };
1011
1004
 
1012
- const A$1 = 53;
1013
- const Abbr$1 = 54;
1014
- const Article$1 = 27;
1015
- const Aside$1 = 28;
1016
- const Br$1 = 55;
1005
+ const A = 53;
1017
1006
  const Button = 1;
1018
- const Cite$1 = 56;
1019
- const Data$1 = 57;
1020
- const Dd$1 = 43;
1021
- const Div$1 = 4;
1022
- const Dl$1 = 44;
1023
- const Figcaption$1 = 45;
1024
- const Figure$1 = 46;
1025
- const Footer$1 = 29;
1026
- const H1$1 = 5;
1027
- const H2$1 = 22;
1028
- const H3$1 = 23;
1029
- const H4$1 = 24;
1030
- const H5$1 = 25;
1031
- const Header$1 = 30;
1032
- const Hr$1 = 47;
1033
- const Img$1 = 17;
1034
- const Li$1 = 48;
1035
- const Nav$1 = 40;
1036
- const Ol$1 = 49;
1037
- const P$1 = 50;
1038
- const Pre$1 = 51;
1039
- const Search$1 = 42;
1040
- const Section$1 = 41;
1041
- const Span$1 = 8;
1007
+ const Div = 4;
1008
+ const H1 = 5;
1009
+ const H2 = 22;
1010
+ const Img = 17;
1011
+ const Pre = 51;
1042
1012
  const Table = 9;
1043
1013
  const TBody = 10;
1044
1014
  const Td = 11;
1045
- const Text$2 = 12;
1046
- const Tfoot$1 = 59;
1015
+ const Text$1 = 12;
1047
1016
  const Th = 13;
1048
1017
  const THead = 14;
1049
- const Time$1 = 58;
1050
1018
  const Tr = 15;
1051
1019
 
1052
1020
  const text = data => {
1053
1021
  return {
1054
- type: Text$2,
1022
+ type: Text$1,
1055
1023
  text: data,
1056
1024
  childCount: 0
1057
1025
  };
@@ -1060,24 +1028,23 @@ const text = data => {
1060
1028
  const getChangelogVirtualDom = () => {
1061
1029
  // TODO set tabpanel role
1062
1030
  return [{
1063
- type: Div$1,
1031
+ type: Div,
1064
1032
  className: Changelog$1,
1065
1033
  childCount: 1
1066
1034
  }, text('Not Implemented')];
1067
1035
  };
1068
1036
 
1069
- const Document = 'document';
1070
1037
  const TabList = 'tablist';
1071
1038
  const Tab = 'tab';
1072
1039
  const Panel = 'panel';
1073
1040
 
1074
1041
  const getAdditionalDetailsEntryVirtualDom = (heading, items, renderer) => {
1075
1042
  return [{
1076
- type: Div$1,
1043
+ type: Div,
1077
1044
  className: AdditionalDetailsEntry,
1078
1045
  childCount: 2
1079
1046
  }, {
1080
- type: Div$1,
1047
+ type: Div,
1081
1048
  className: AdditionalDetailsTitle,
1082
1049
  childCount: 1
1083
1050
  }, text(heading), ...renderer(items)];
@@ -1088,7 +1055,7 @@ const getCategoryVirtualDom = category => {
1088
1055
  label
1089
1056
  } = category;
1090
1057
  return [{
1091
- type: Div$1,
1058
+ type: Div,
1092
1059
  className: Category,
1093
1060
  childCount: 1
1094
1061
  }, text(label)];
@@ -1096,7 +1063,7 @@ const getCategoryVirtualDom = category => {
1096
1063
 
1097
1064
  const getCategoriesDom = categories => {
1098
1065
  return [{
1099
- type: Div$1,
1066
+ type: Div,
1100
1067
  className: Categories,
1101
1068
  childCount: categories.length
1102
1069
  }, ...categories.flatMap(getCategoryVirtualDom)];
@@ -1107,7 +1074,7 @@ const getMoreInfoEntryKeyVirtualDom = item => {
1107
1074
  key
1108
1075
  } = item;
1109
1076
  return [{
1110
- type: Div$1,
1077
+ type: Div,
1111
1078
  className: MoreInfoEntryKey,
1112
1079
  childCount: 1
1113
1080
  }, text(key)];
@@ -1115,13 +1082,13 @@ const getMoreInfoEntryKeyVirtualDom = item => {
1115
1082
 
1116
1083
  const getTag = (onClick, code) => {
1117
1084
  if (onClick) {
1118
- return A$1;
1085
+ return A;
1119
1086
  }
1120
1087
  if (code) {
1121
1088
  // TODO use code tag
1122
- return Div$1;
1089
+ return Div;
1123
1090
  }
1124
- return Div$1;
1091
+ return Div;
1125
1092
  };
1126
1093
  const getClassName = (onClick, code) => {
1127
1094
  if (onClick) {
@@ -1149,12 +1116,12 @@ const getMoreInfoEntryValueVirtualDom = item => {
1149
1116
  };
1150
1117
 
1151
1118
  const parentNodeEven = {
1152
- type: Div$1,
1119
+ type: Div,
1153
1120
  className: MoreInfoEntry,
1154
1121
  childCount: 2
1155
1122
  };
1156
1123
  const parentNodeOdd = {
1157
- type: Div$1,
1124
+ type: Div,
1158
1125
  className: MoreInfoEntry + ' ' + MoreInfoEntryOdd,
1159
1126
  childCount: 2
1160
1127
  };
@@ -1168,7 +1135,7 @@ const getMoreInfoEntryVirtualDom = item => {
1168
1135
 
1169
1136
  const getMoreInfoVirtualDom = items => {
1170
1137
  return [{
1171
- type: Div$1,
1138
+ type: Div,
1172
1139
  className: MoreInfo,
1173
1140
  childCount: items.length
1174
1141
  }, ...items.flatMap(getMoreInfoEntryVirtualDom)];
@@ -1176,7 +1143,7 @@ const getMoreInfoVirtualDom = items => {
1176
1143
 
1177
1144
  const resourceNode = {
1178
1145
  // TODO use link with url
1179
- type: Div$1,
1146
+ type: Div,
1180
1147
  className: Resource,
1181
1148
  childCount: 1
1182
1149
  };
@@ -1189,7 +1156,7 @@ const getResourceVirtualDom = resource => {
1189
1156
 
1190
1157
  const getResourcesVirtualDom = resources => {
1191
1158
  return [{
1192
- type: Div$1,
1159
+ type: Div,
1193
1160
  className: Resources,
1194
1161
  childCount: resources.length
1195
1162
  }, ...resources.flatMap(getResourceVirtualDom)];
@@ -1200,11 +1167,11 @@ const getAdditionalDetailsVirtualDom = (showAdditionalDetails, firstHeading, ent
1200
1167
  return [];
1201
1168
  }
1202
1169
  return [{
1203
- type: Div$1,
1204
- className: Aside$2,
1170
+ type: Div,
1171
+ className: Aside,
1205
1172
  childCount: 1
1206
1173
  }, {
1207
- type: Div$1,
1174
+ type: Div,
1208
1175
  className: AdditionalDetails,
1209
1176
  tabIndex: 0,
1210
1177
  childCount: 4
@@ -1241,475 +1208,27 @@ const getInstallationEntries = (displaySize, extensionId, extensionVersion) => {
1241
1208
  return entries;
1242
1209
  };
1243
1210
 
1244
- const allowedMarkdownAttributes = ['src', 'id', 'className', 'title', 'alt', 'href', 'target', 'rel'];
1245
-
1246
- const getVirtualDomChildCount = markdownDom => {
1247
- const max = markdownDom.length - 1;
1248
- let stack = [];
1249
- for (let i = max; i >= 0; i--) {
1250
- const element = markdownDom[i];
1251
- if (element.childCount > 0) {
1252
- stack = stack.slice(element.childCount);
1253
- }
1254
- stack.unshift(element);
1255
- }
1256
- return stack.length;
1257
- };
1258
-
1259
- const Div = 'div';
1260
- const H1 = 'h1';
1261
- const H2 = 'h2';
1262
- const H3 = 'h3';
1263
- const H4 = 'h4';
1264
- const H5 = 'h5';
1265
- const Img = 'img';
1266
- const Span = 'span';
1267
- const Article = 'article';
1268
- const Aside = 'aside';
1269
- const Footer = 'footer';
1270
- const Header = 'header';
1271
- const Nav = 'nav';
1272
- const Section = 'section';
1273
- const Search = 'search';
1274
- const Dd = 'dd';
1275
- const Dl = 'dl';
1276
- const Figcaption = 'figcaption';
1277
- const Figure = 'figure';
1278
- const Hr = 'hr';
1279
- const Li = 'li';
1280
- const Ol = 'ol';
1281
- const P = 'p';
1282
- const Pre = 'pre';
1283
- const A = 'a';
1284
- const Abbr = 'abbr';
1285
- const Br = 'br';
1286
- const Cite = 'cite';
1287
- const Data = 'data';
1288
- const Time = 'time';
1289
- const Tfoot = 'tfoot';
1290
-
1291
- const getVirtualDomTag = text => {
1292
- switch (text) {
1293
- case H1:
1294
- return H1$1;
1295
- case H2:
1296
- return H2$1;
1297
- case H3:
1298
- return H3$1;
1299
- case H4:
1300
- return H4$1;
1301
- case H5:
1302
- return H5$1;
1303
- case Div:
1304
- return Div$1;
1305
- case Article:
1306
- return Article$1;
1307
- case Aside:
1308
- return Aside$1;
1309
- case Footer:
1310
- return Footer$1;
1311
- case Header:
1312
- return Header$1;
1313
- case Nav:
1314
- return Nav$1;
1315
- case Section:
1316
- return Section$1;
1317
- case Search:
1318
- return Search$1;
1319
- case Dd:
1320
- return Dd$1;
1321
- case Dl:
1322
- return Dl$1;
1323
- case Figcaption:
1324
- return Figcaption$1;
1325
- case Figure:
1326
- return Figure$1;
1327
- case Hr:
1328
- return Hr$1;
1329
- case Li:
1330
- return Li$1;
1331
- case Ol:
1332
- return Ol$1;
1333
- case P:
1334
- return P$1;
1335
- case Pre:
1336
- return Pre$1;
1337
- case A:
1338
- return A$1;
1339
- case Abbr:
1340
- return Abbr$1;
1341
- case Br:
1342
- return Br$1;
1343
- case Cite:
1344
- return Cite$1;
1345
- case Data:
1346
- return Data$1;
1347
- case Time:
1348
- return Time$1;
1349
- case Tfoot:
1350
- return Tfoot$1;
1351
- case Img:
1352
- return Img$1;
1353
- case Span:
1354
- return Span$1;
1355
- default:
1356
- return Div$1;
1357
- }
1358
- };
1211
+ const RendererWorker = 1;
1359
1212
 
1360
- const None$1 = 0;
1361
- const OpeningAngleBracket = 1;
1362
- const ClosingAngleBracket = 2;
1363
- const TagNameStart = 3;
1364
- const TagNameEnd = 4;
1365
- const Content = 5;
1366
- const ClosingTagSlash = 6;
1367
- const WhitespaceInsideOpeningTag = 7;
1368
- const AttributeName = 8;
1369
- const AttributeEqualSign = 9;
1370
- const AttributeQuoteStart = 10;
1371
- const AttributeValue = 11;
1372
- const AttributeQuoteEnd = 12;
1373
- const WhitespaceAfterClosingTagSlash = 13;
1374
- const WhitespaceAfterOpeningTagOpenAngleBracket = 14;
1375
- const ExclamationMark = 15;
1376
- const Doctype = 16;
1377
- const StartCommentDashes = 17;
1378
- const Comment = 18;
1379
- const EndCommentTag = 19;
1380
- const Text$1 = 20;
1381
- const CommentStart = 21;
1382
-
1383
- const isSelfClosingTag = tag => {
1384
- switch (tag) {
1385
- case Img:
1386
- return true;
1387
- default:
1388
- return false;
1389
- }
1213
+ const rpcs = Object.create(null);
1214
+ const set = (id, rpc) => {
1215
+ rpcs[id] = rpc;
1390
1216
  };
1391
-
1392
- const parseText = text => {
1393
- return text.replaceAll('&gt;', '>').replaceAll('&lt;', '<').replaceAll('&amp;', '&');
1217
+ const get = id => {
1218
+ return rpcs[id];
1394
1219
  };
1395
1220
 
1396
- class UnexpectedTokenError extends Error {
1397
- constructor() {
1398
- super('Unexpected token');
1399
- this.name = 'UnexpectedTokenError';
1400
- }
1401
- }
1402
-
1403
- const State = {
1404
- TopLevelContent: 1,
1405
- AfterOpeningAngleBracket: 2,
1406
- InsideOpeningTag: 3,
1407
- AfterClosingTagSlash: 4,
1408
- AfterClosingTagName: 5,
1409
- InsideOpeningTagAfterWhitespace: 6,
1410
- AfterAttributeName: 7,
1411
- AfterAttributeEqualSign: 8,
1412
- InsideAttributeAfterDoubleQuote: 9,
1413
- AfterAttributeValueInsideDoubleQuote: 10,
1414
- AfterAttributeValueClosingQuote: 11,
1415
- AfterExclamationMark: 16,
1416
- InsideComment: 17
1417
- };
1418
- const RE_ANGLE_BRACKET_OPEN = /^</;
1419
- const RE_ANGLE_BRACKET_OPEN_TAG = /^<(?![\s!%])/;
1420
- const RE_ANGLE_BRACKET_CLOSE = /^>/;
1421
- const RE_SLASH = /^\//;
1422
- const RE_TAGNAME = /^[a-zA-Z\d$]+/;
1423
- const RE_CONTENT = /^[^<>]+/;
1424
- const RE_WHITESPACE = /^\s+/;
1425
- const RE_ATTRIBUTE_NAME = /^[a-zA-Z\d-]+/;
1426
- const RE_EQUAL_SIGN = /^=/;
1427
- const RE_DOUBLE_QUOTE = /^"/;
1428
- const RE_ATTRIBUTE_VALUE_INSIDE_DOUBLE_QUOTE = /^[^"\n]+/;
1429
- const RE_TEXT = /^[^<>]+/;
1430
- const RE_EXCLAMATION_MARK = /^!/;
1431
- const RE_DASH_DASH = /^--/;
1432
- const RE_DOCTYPE = /^doctype/i;
1433
- const RE_BLOCK_COMMENT_CONTENT = /^[a-zA-Z\s]+/;
1434
- const RE_COMMENT_END = /^-->/;
1435
- const RE_TAG_TEXT = /^[^\s>]+/;
1436
- const RE_ANY_TEXT = /^[^\n]+/;
1437
- const RE_BLOCK_COMMENT_START = /^<!--/;
1438
- const RE_SELF_CLOSING = /^\/>/;
1439
- const tokenizeHtml = text => {
1440
- string(text);
1441
- let state = State.TopLevelContent;
1442
- let index = 0;
1443
- let next;
1444
- const tokens = [];
1445
- let token = None$1;
1446
- while (index < text.length) {
1447
- const part = text.slice(index);
1448
- switch (state) {
1449
- case State.TopLevelContent:
1450
- if (next = part.match(RE_ANGLE_BRACKET_OPEN_TAG)) {
1451
- token = OpeningAngleBracket;
1452
- state = State.AfterOpeningAngleBracket;
1453
- } else if (next = part.match(RE_CONTENT)) {
1454
- token = Content;
1455
- state = State.TopLevelContent;
1456
- } else if (next = part.match(RE_BLOCK_COMMENT_START)) {
1457
- token = CommentStart;
1458
- state = State.InsideComment;
1459
- } else if (next = part.match(RE_ANGLE_BRACKET_CLOSE)) {
1460
- token = Content;
1461
- state = State.TopLevelContent;
1462
- } else if (next = part.match(RE_ANGLE_BRACKET_OPEN)) {
1463
- token = Text$1;
1464
- state = State.TopLevelContent;
1465
- } else {
1466
- throw new UnexpectedTokenError();
1467
- }
1468
- break;
1469
- case State.AfterOpeningAngleBracket:
1470
- if (next = part.match(RE_TAGNAME)) {
1471
- token = TagNameStart;
1472
- state = State.InsideOpeningTag;
1473
- } else if (next = part.match(RE_SLASH)) {
1474
- token = ClosingTagSlash;
1475
- state = State.AfterClosingTagSlash;
1476
- } else if (next = part.match(RE_WHITESPACE)) {
1477
- token = WhitespaceAfterOpeningTagOpenAngleBracket;
1478
- state = State.TopLevelContent;
1479
- } else if (next = part.match(RE_ANGLE_BRACKET_CLOSE)) {
1480
- token = ClosingAngleBracket;
1481
- state = State.TopLevelContent;
1482
- } else if (next = part.match(RE_EXCLAMATION_MARK)) {
1483
- token = ExclamationMark;
1484
- state = State.AfterExclamationMark;
1485
- } else if (next = part.match(RE_ANY_TEXT)) {
1486
- token = Text$1;
1487
- state = State.TopLevelContent;
1488
- } else {
1489
- text.slice(index); // ?
1490
- throw new UnexpectedTokenError();
1491
- }
1492
- break;
1493
- case State.AfterExclamationMark:
1494
- if (next = part.match(RE_DASH_DASH)) {
1495
- token = StartCommentDashes;
1496
- state = State.InsideComment;
1497
- } else if (next = part.match(RE_DOCTYPE)) {
1498
- token = Doctype;
1499
- state = State.InsideOpeningTag;
1500
- } else {
1501
- text.slice(index); // ?
1502
- throw new UnexpectedTokenError();
1503
- }
1504
- break;
1505
- case State.InsideComment:
1506
- if (next = part.match(RE_BLOCK_COMMENT_CONTENT)) {
1507
- token = Comment;
1508
- state = State.InsideComment;
1509
- } else if (next = part.match(RE_COMMENT_END)) {
1510
- token = EndCommentTag;
1511
- state = State.TopLevelContent;
1512
- } else {
1513
- text.slice(index); // ?
1514
- throw new UnexpectedTokenError();
1515
- }
1516
- break;
1517
- case State.InsideOpeningTag:
1518
- if (next = part.match(RE_ANGLE_BRACKET_CLOSE)) {
1519
- token = ClosingAngleBracket;
1520
- state = State.TopLevelContent;
1521
- } else if (next = part.match(RE_WHITESPACE)) {
1522
- token = WhitespaceInsideOpeningTag;
1523
- state = State.InsideOpeningTagAfterWhitespace;
1524
- } else if (next = part.match(RE_TAG_TEXT)) {
1525
- token = Text$1;
1526
- state = State.TopLevelContent;
1527
- } else {
1528
- throw new UnexpectedTokenError();
1529
- }
1530
- break;
1531
- case State.InsideOpeningTagAfterWhitespace:
1532
- if (next = part.match(RE_ATTRIBUTE_NAME)) {
1533
- token = AttributeName;
1534
- state = State.AfterAttributeName;
1535
- } else if (next = part.match(RE_ANGLE_BRACKET_CLOSE)) {
1536
- token = ClosingAngleBracket;
1537
- state = State.TopLevelContent;
1538
- } else if (next = part.match(RE_SELF_CLOSING)) {
1539
- token = ClosingAngleBracket;
1540
- state = State.TopLevelContent;
1541
- } else if (next = part.match(RE_TEXT)) {
1542
- token = AttributeName;
1543
- state = State.AfterAttributeName;
1544
- } else {
1545
- text.slice(index).match(RE_TEXT); // ?
1546
- text.slice(index); // ?
1547
- throw new UnexpectedTokenError();
1548
- }
1549
- break;
1550
- case State.AfterAttributeName:
1551
- if (next = part.match(RE_EQUAL_SIGN)) {
1552
- token = AttributeEqualSign;
1553
- state = State.AfterAttributeEqualSign;
1554
- } else if (next = part.match(RE_ANGLE_BRACKET_CLOSE)) {
1555
- token = ClosingAngleBracket;
1556
- state = State.TopLevelContent;
1557
- } else if (next = part.match(RE_WHITESPACE)) {
1558
- token = WhitespaceInsideOpeningTag;
1559
- state = State.InsideOpeningTagAfterWhitespace;
1560
- } else if (next = part.match(RE_ANGLE_BRACKET_OPEN)) {
1561
- token = OpeningAngleBracket;
1562
- state = State.AfterOpeningAngleBracket;
1563
- } else {
1564
- text.slice(index); // ?
1565
- throw new UnexpectedTokenError();
1566
- }
1567
- break;
1568
- case State.AfterAttributeEqualSign:
1569
- if (next = part.match(RE_DOUBLE_QUOTE)) {
1570
- token = AttributeQuoteStart;
1571
- state = State.InsideAttributeAfterDoubleQuote;
1572
- } else if (next = part.match(RE_ANGLE_BRACKET_CLOSE)) {
1573
- token = ClosingAngleBracket;
1574
- state = State.TopLevelContent;
1575
- } else {
1576
- throw new UnexpectedTokenError();
1577
- }
1578
- break;
1579
- case State.InsideAttributeAfterDoubleQuote:
1580
- if (next = text.slice(index).match(RE_ATTRIBUTE_VALUE_INSIDE_DOUBLE_QUOTE)) {
1581
- token = AttributeValue;
1582
- state = State.AfterAttributeValueInsideDoubleQuote;
1583
- } else if (next = part.match(RE_DOUBLE_QUOTE)) {
1584
- token = AttributeQuoteEnd;
1585
- state = State.AfterAttributeValueClosingQuote;
1586
- } else {
1587
- throw new UnexpectedTokenError();
1588
- }
1589
- break;
1590
- case State.AfterAttributeValueInsideDoubleQuote:
1591
- if (next = part.match(RE_DOUBLE_QUOTE)) {
1592
- token = AttributeQuoteEnd;
1593
- state = State.AfterAttributeValueClosingQuote;
1594
- } else {
1595
- throw new UnexpectedTokenError();
1596
- }
1597
- break;
1598
- case State.AfterAttributeValueClosingQuote:
1599
- if (next = part.match(RE_ANGLE_BRACKET_CLOSE)) {
1600
- token = ClosingAngleBracket;
1601
- state = State.TopLevelContent;
1602
- } else if (next = part.match(RE_WHITESPACE)) {
1603
- token = WhitespaceInsideOpeningTag;
1604
- state = State.InsideOpeningTagAfterWhitespace;
1605
- } else if (next = part.match(RE_SELF_CLOSING)) {
1606
- token = ClosingAngleBracket;
1607
- state = State.TopLevelContent;
1608
- } else {
1609
- throw new UnexpectedTokenError();
1610
- }
1611
- break;
1612
- case State.AfterClosingTagSlash:
1613
- if (next = part.match(RE_TAGNAME)) {
1614
- token = TagNameEnd;
1615
- state = State.AfterClosingTagName;
1616
- } else if (next = part.match(RE_WHITESPACE)) {
1617
- token = WhitespaceAfterClosingTagSlash;
1618
- state = State.TopLevelContent;
1619
- } else if (next = part.match(RE_ANGLE_BRACKET_CLOSE)) {
1620
- token = ClosingAngleBracket;
1621
- state = State.TopLevelContent;
1622
- } else {
1623
- throw new UnexpectedTokenError();
1624
- }
1625
- break;
1626
- case State.AfterClosingTagName:
1627
- if (next = part.match(RE_ANGLE_BRACKET_CLOSE)) {
1628
- token = ClosingAngleBracket;
1629
- state = State.TopLevelContent;
1630
- } else if (next = part.match(RE_WHITESPACE)) {
1631
- token = Content;
1632
- state = State.TopLevelContent;
1633
- } else {
1634
- throw new UnexpectedTokenError();
1635
- }
1636
- break;
1637
- default:
1638
- throw new UnexpectedTokenError();
1639
- }
1640
- const tokenText = next[0];
1641
- tokens.push({
1642
- type: token,
1643
- text: tokenText
1644
- });
1645
- index += tokenText.length;
1646
- }
1647
- return tokens;
1221
+ const invoke = (method, ...params) => {
1222
+ const rpc = get(RendererWorker);
1223
+ return rpc.invoke(method, ...params);
1648
1224
  };
1649
1225
 
1650
- const parseHtml = (html, allowedAttributes) => {
1226
+ const getMarkdownVirtualDom = async html => {
1651
1227
  string(html);
1652
- array(allowedAttributes);
1653
- const tokens = tokenizeHtml(html);
1654
- const dom = [];
1655
- const root = {
1656
- type: 0,
1657
- childCount: 0
1658
- };
1659
- let current = root;
1660
- const stack = [root];
1661
- let attributeName = '';
1662
- for (const token of tokens) {
1663
- switch (token.type) {
1664
- case TagNameStart:
1665
- current.childCount++;
1666
- current = {
1667
- type: getVirtualDomTag(token.text),
1668
- childCount: 0
1669
- };
1670
- dom.push(current);
1671
- if (!isSelfClosingTag(token.text)) {
1672
- stack.push(current);
1673
- }
1674
- break;
1675
- case TagNameEnd:
1676
- stack.pop();
1677
- current = stack.at(-1) || root;
1678
- break;
1679
- case Content:
1680
- current.childCount++;
1681
- dom.push(text(parseText(token.text)));
1682
- break;
1683
- case AttributeName:
1684
- attributeName = token.text;
1685
- if (attributeName === 'class') {
1686
- attributeName = 'className';
1687
- }
1688
- break;
1689
- case AttributeValue:
1690
- if (allowedAttributes.includes(attributeName)) {
1691
- current[attributeName] = token.text;
1692
- }
1693
- attributeName = '';
1694
- break;
1695
- }
1696
- }
1228
+ const dom = await invoke('Markdown.getVirtualDom', html);
1697
1229
  return dom;
1698
1230
  };
1699
1231
 
1700
- const getMarkdownVirtualDom = html => {
1701
- string(html);
1702
- const childDom = parseHtml(html, allowedMarkdownAttributes);
1703
- const markdownChildCount = getVirtualDomChildCount(childDom);
1704
- return [{
1705
- type: Div$1,
1706
- className: Markdown,
1707
- role: Document,
1708
- onContextMenu: HandleReadmeContextMenu,
1709
- childCount: markdownChildCount
1710
- }, ...childDom];
1711
- };
1712
-
1713
1232
  const getMarketplaceEntries = () => {
1714
1233
  return [{
1715
1234
  key: 'Published',
@@ -1721,7 +1240,7 @@ const getMarketplaceEntries = () => {
1721
1240
  }];
1722
1241
  };
1723
1242
 
1724
- const getDetailsVirtualDom = (sanitizedReadmeHtml, displaySize, extensionId, extensionVersion, width) => {
1243
+ const getDetailsVirtualDom = async (sanitizedReadmeHtml, displaySize, extensionId, extensionVersion, width) => {
1725
1244
  const firstHeading = 'Installation';
1726
1245
  const entries = getInstallationEntries(displaySize, extensionId, extensionVersion);
1727
1246
  const secondHeading = 'Marketplace';
@@ -1749,11 +1268,11 @@ const getDetailsVirtualDom = (sanitizedReadmeHtml, displaySize, extensionId, ext
1749
1268
  const showAdditionalDetails = width > showAdditionalDetailsBreakpoint;
1750
1269
  const childCount = showAdditionalDetails ? 2 : 1;
1751
1270
  const dom = [{
1752
- type: Div$1,
1271
+ type: Div,
1753
1272
  className: ExtensionDetailPanel,
1754
1273
  childCount: childCount,
1755
1274
  role: Panel
1756
- }, ...getMarkdownVirtualDom(sanitizedReadmeHtml), ...getAdditionalDetailsVirtualDom(showAdditionalDetails, firstHeading, entries, secondHeading, secondEntries, thirdHeading, categories, fourthHeading, resources)];
1275
+ }, ...(await getMarkdownVirtualDom(sanitizedReadmeHtml)), ...getAdditionalDetailsVirtualDom(showAdditionalDetails, firstHeading, entries, secondHeading, secondEntries, thirdHeading, categories, fourthHeading, resources)];
1757
1276
  return dom;
1758
1277
  };
1759
1278
 
@@ -1868,7 +1387,7 @@ const getCommandTableEntries = extension => {
1868
1387
 
1869
1388
  const getFeatureContentHeadingVirtualDom = heading => {
1870
1389
  return [{
1871
- type: H1$1,
1390
+ type: H1,
1872
1391
  childCount: 1
1873
1392
  }, text(heading)];
1874
1393
  };
@@ -1887,7 +1406,7 @@ const getCellCodeVirtualDom = value => {
1887
1406
  className: TableCell,
1888
1407
  childCount: 1
1889
1408
  }, {
1890
- type: Div$1,
1409
+ type: Div,
1891
1410
  // TODO use code tag
1892
1411
  childCount: 1
1893
1412
  }, text(value)];
@@ -1954,7 +1473,7 @@ const getFeatureCommandsVirtualDom = extension => {
1954
1473
  const heading = commands();
1955
1474
  const tableInfo = getCommandTableEntries(extension);
1956
1475
  return [{
1957
- type: Div$1,
1476
+ type: Div,
1958
1477
  className: FeatureContent,
1959
1478
  childCount: 2
1960
1479
  }, ...getFeatureContentHeadingVirtualDom(heading), ...getTableVirtualDom(tableInfo)];
@@ -1987,7 +1506,7 @@ const getFeatureJsonValidationVirtualDom = extension => {
1987
1506
  const heading = jsonValidation();
1988
1507
  const tableInfo = getJsonValidationTableEntries(extension);
1989
1508
  return [{
1990
- type: Div$1,
1509
+ type: Div,
1991
1510
  className: FeatureContent,
1992
1511
  childCount: 2
1993
1512
  }, ...getFeatureContentHeadingVirtualDom(heading), ...getTableVirtualDom(tableInfo)];
@@ -1996,11 +1515,11 @@ const getFeatureJsonValidationVirtualDom = extension => {
1996
1515
  const getFeatureNotImplementedVirtualDom = () => {
1997
1516
  const heading = 'Not implemented';
1998
1517
  return [{
1999
- type: Div$1,
1518
+ type: Div,
2000
1519
  className: FeatureContent,
2001
1520
  childCount: 1
2002
1521
  }, {
2003
- type: H1$1,
1522
+ type: H1,
2004
1523
  childCount: 1
2005
1524
  }, text(heading)];
2006
1525
  };
@@ -2009,7 +1528,7 @@ const getFeatureProgrammingLanguagesVirtualDom = () => {
2009
1528
  const heading = programmingLanguages();
2010
1529
  // TODO
2011
1530
  return [{
2012
- type: Div$1,
1531
+ type: Div,
2013
1532
  className: FeatureContent,
2014
1533
  childCount: 1
2015
1534
  }, ...getFeatureContentHeadingVirtualDom(heading)];
@@ -2045,22 +1564,35 @@ const getFeatureSettingsVirtualDom = extension => {
2045
1564
  const heading = settings();
2046
1565
  const tableInfo = getSettingsTableEntries(extension);
2047
1566
  return [{
2048
- type: Div$1,
1567
+ type: Div,
2049
1568
  className: FeatureContent,
2050
1569
  childCount: 2
2051
1570
  }, ...getFeatureContentHeadingVirtualDom(heading), ...getTableVirtualDom(tableInfo)];
2052
1571
  };
2053
1572
 
2054
- const getFeatureThemesVirtualDom = themesHtml => {
2055
- const markdownDom = getMarkdownVirtualDom(themesHtml);
1573
+ const getVirtualDomChildCount = markdownDom => {
1574
+ const max = markdownDom.length - 1;
1575
+ let stack = [];
1576
+ for (let i = max; i >= 0; i--) {
1577
+ const element = markdownDom[i];
1578
+ if (element.childCount > 0) {
1579
+ stack = stack.slice(element.childCount);
1580
+ }
1581
+ stack.unshift(element);
1582
+ }
1583
+ return stack.length;
1584
+ };
1585
+
1586
+ const getFeatureThemesVirtualDom = async themesHtml => {
1587
+ const markdownDom = await getMarkdownVirtualDom(themesHtml);
2056
1588
  const childCount = getVirtualDomChildCount(markdownDom);
2057
1589
  const heading = theme();
2058
1590
  return [{
2059
- type: Div$1,
1591
+ type: Div,
2060
1592
  className: FeatureContent,
2061
1593
  childCount: 2
2062
1594
  }, ...getFeatureContentHeadingVirtualDom(heading), {
2063
- type: Div$1,
1595
+ type: Div,
2064
1596
  className: 'DefaultMarkdown',
2065
1597
  childCount
2066
1598
  }, ...markdownDom];
@@ -2086,18 +1618,18 @@ const getWebViews = extension => {
2086
1618
  return rawWebViews.map(toWebView);
2087
1619
  };
2088
1620
 
2089
- const heading$1 = {
2090
- type: H2$1,
1621
+ const heading = {
1622
+ type: H2,
2091
1623
  className: DefinitionListItemHeading,
2092
1624
  childCount: 1
2093
1625
  };
2094
1626
  const pre = {
2095
- type: Pre$1,
1627
+ type: Pre,
2096
1628
  className: DefinitionListItemValue,
2097
1629
  childCount: 1
2098
1630
  };
2099
1631
  const item = {
2100
- type: Div$1,
1632
+ type: Div,
2101
1633
  className: DefinitionListItem,
2102
1634
  childCount: 2
2103
1635
  };
@@ -2113,21 +1645,21 @@ const getWebViewVirtualDom = webView => {
2113
1645
  const textContentSecurityPolicy = contentSecurityPolicy();
2114
1646
  const textElements = elements();
2115
1647
  return [{
2116
- type: Div$1,
1648
+ type: Div,
2117
1649
  className: FeatureWebView,
2118
1650
  childCount: 5
2119
- }, item, heading$1, text(textId), pre, text(id$1), item, heading$1, text(textSelector), pre, text(selectorString), item, heading$1, text(textContentSecurityPolicy), pre, text(contentSecurityPolicyString), item, heading$1, text(textElements), pre, text(elementsString)];
1651
+ }, item, heading, text(textId), pre, text(id$1), item, heading, text(textSelector), pre, text(selectorString), item, heading, text(textContentSecurityPolicy), pre, text(contentSecurityPolicyString), item, heading, text(textElements), pre, text(elementsString)];
2120
1652
  };
2121
1653
 
2122
1654
  const getFeatureWebViewsVirtualDom = extension => {
2123
1655
  const webViews$1 = getWebViews(extension);
2124
1656
  const heading = webViews();
2125
1657
  return [{
2126
- type: Div$1,
1658
+ type: Div,
2127
1659
  className: FeatureContent,
2128
1660
  childCount: 2
2129
1661
  }, ...getFeatureContentHeadingVirtualDom(heading), {
2130
- type: Div$1,
1662
+ type: Div,
2131
1663
  childCount: webViews$1.length
2132
1664
  }, ...webViews$1.flatMap(getWebViewVirtualDom)];
2133
1665
  };
@@ -2142,10 +1674,10 @@ const Settings = 'Settings';
2142
1674
  const WebViews = 'WebViews';
2143
1675
  const Theme = 'Theme';
2144
1676
 
2145
- const getFeatureContentVirtualDom = (features, themesHtml, selectedFeature, extension) => {
1677
+ const getFeatureContentVirtualDom = async (features, themesHtml, selectedFeature, extension) => {
2146
1678
  switch (selectedFeature) {
2147
1679
  case Theme:
2148
- return getFeatureThemesVirtualDom(themesHtml);
1680
+ return await getFeatureThemesVirtualDom(themesHtml);
2149
1681
  case Commands:
2150
1682
  return getFeatureCommandsVirtualDom(extension);
2151
1683
  case JsonValidation:
@@ -2180,38 +1712,38 @@ const getFeatureListItemVirtualDom = feature => {
2180
1712
  const getFeatureListVirtualDom = features => {
2181
1713
  return [{
2182
1714
  // TODO use either list or tabs role
2183
- type: Div$1,
1715
+ type: Div,
2184
1716
  className: FeaturesList,
2185
1717
  childCount: features.length,
2186
1718
  onClick: HandleFeaturesClick
2187
1719
  }, ...features.flatMap(getFeatureListItemVirtualDom)];
2188
1720
  };
2189
1721
 
2190
- const getFeaturesVirtualDom = (features, themesHtml, selectedFeature, extension) => {
1722
+ const getFeaturesVirtualDom = async (features, themesHtml, selectedFeature, extension) => {
2191
1723
  if (features.length === 0) {
2192
1724
  return [{
2193
- type: Div$1,
1725
+ type: Div,
2194
1726
  className: Features$1,
2195
1727
  childCount: 3
2196
1728
  }, text('None')];
2197
1729
  }
2198
1730
  return [{
2199
- type: Div$1,
1731
+ type: Div,
2200
1732
  className: Features$1,
2201
1733
  childCount: 3
2202
1734
  }, ...getFeatureListVirtualDom(features), {
2203
- type: Div$1,
1735
+ type: Div,
2204
1736
  className: 'Sash SashVertical',
2205
1737
  childCount: 0
2206
- }, ...getFeatureContentVirtualDom(features, themesHtml, selectedFeature, extension)];
1738
+ }, ...(await getFeatureContentVirtualDom(features, themesHtml, selectedFeature, extension))];
2207
1739
  };
2208
1740
 
2209
- const getExtensionDetailContentVirtualDom = (sanitizedReadmeHtml, themesHtml, selectedTab, features, displaySize, extensionId, extensionVersion, selectedFeature, extension, width) => {
1741
+ const getExtensionDetailContentVirtualDom = async (sanitizedReadmeHtml, themesHtml, selectedTab, features, displaySize, extensionId, extensionVersion, selectedFeature, extension, width) => {
2210
1742
  switch (selectedTab) {
2211
1743
  case Details:
2212
- return getDetailsVirtualDom(sanitizedReadmeHtml, displaySize, extensionId, extensionVersion, width);
1744
+ return await getDetailsVirtualDom(sanitizedReadmeHtml, displaySize, extensionId, extensionVersion, width);
2213
1745
  case Features:
2214
- return getFeaturesVirtualDom(features, themesHtml, selectedFeature, extension);
1746
+ return await getFeaturesVirtualDom(features, themesHtml, selectedFeature, extension);
2215
1747
  case Changelog:
2216
1748
  return getChangelogVirtualDom();
2217
1749
  default:
@@ -2230,7 +1762,7 @@ const getButtonVirtualDom = (message, onClick) => {
2230
1762
 
2231
1763
  const getExtensionDetailHeaderActionsVirtualDom = () => {
2232
1764
  const dom = [{
2233
- type: Div$1,
1765
+ type: Div,
2234
1766
  className: ExtensionDetailHeaderActions,
2235
1767
  childCount: 2
2236
1768
  }, ...getButtonVirtualDom('Disable', HandleClickDisable), ...getButtonVirtualDom('Uninstall', HandleClickUninstall)];
@@ -2244,26 +1776,26 @@ const getExtensionDetailHeaderVirtualDom = extensionDetail => {
2244
1776
  description
2245
1777
  } = extensionDetail;
2246
1778
  const dom = [{
2247
- type: Div$1,
1779
+ type: Div,
2248
1780
  className: ExtensionDetailHeader,
2249
1781
  childCount: 2
2250
1782
  }, {
2251
- type: Img$1,
1783
+ type: Img,
2252
1784
  className: ExtensionDetailIcon,
2253
1785
  alt: '',
2254
1786
  draggable: false,
2255
1787
  childCount: 0,
2256
1788
  src: iconSrc
2257
1789
  }, {
2258
- type: Div$1,
1790
+ type: Div,
2259
1791
  className: ExtensionDetailHeaderDetails,
2260
1792
  childCount: 3
2261
1793
  }, {
2262
- type: Div$1,
1794
+ type: Div,
2263
1795
  className: ExtensionDetailName,
2264
1796
  childCount: 1
2265
1797
  }, text(name), {
2266
- type: Div$1,
1798
+ type: Div,
2267
1799
  className: ExtensionDetailDescription,
2268
1800
  childCount: 1
2269
1801
  }, text(description), ...getExtensionDetailHeaderActionsVirtualDom()];
@@ -2360,7 +1892,7 @@ const getTabVirtualDom = tab => {
2360
1892
 
2361
1893
  const getTabsVirtualDom = tabs => {
2362
1894
  return [{
2363
- type: Div$1,
1895
+ type: Div,
2364
1896
  className: ExtensionDetailTabs,
2365
1897
  childCount: tabs.length,
2366
1898
  role: TabList,
@@ -2396,7 +1928,7 @@ const getClassNames = size => {
2396
1928
  }
2397
1929
  };
2398
1930
 
2399
- const getExtensionDetailVirtualDom = (extensionDetail, sanitizedReadmeHtml, selectedTab, newState) => {
1931
+ const getExtensionDetailVirtualDom = async (extensionDetail, sanitizedReadmeHtml, selectedTab, newState) => {
2400
1932
  // TODO move this to view model so that rendering occurs like
2401
1933
  // 1. state
2402
1934
  // 2. view model
@@ -2415,18 +1947,18 @@ const getExtensionDetailVirtualDom = (extensionDetail, sanitizedReadmeHtml, sele
2415
1947
  const sizeValue = getViewletSize(newState?.width || 0);
2416
1948
  const sizeClass = getClassNames(sizeValue);
2417
1949
  const dom = [{
2418
- type: Div$1,
1950
+ type: Div,
2419
1951
  className: mergeClassNames(Viewlet, ExtensionDetail, sizeClass),
2420
1952
  childCount: 3
2421
- }, ...getExtensionDetailHeaderVirtualDom(extensionDetail), ...getTabsVirtualDom(tabs), ...getExtensionDetailContentVirtualDom(sanitizedReadmeHtml, themesHtml, selectedTab, features, displaySize, extensionId, extensionVersion, selectedFeature, extension, width)];
1953
+ }, ...getExtensionDetailHeaderVirtualDom(extensionDetail), ...getTabsVirtualDom(tabs), ...(await getExtensionDetailContentVirtualDom(sanitizedReadmeHtml, themesHtml, selectedTab, features, displaySize, extensionId, extensionVersion, selectedFeature, extension, width))];
2422
1954
  return dom;
2423
1955
  };
2424
1956
 
2425
- const getExtensionDetailVirtualDom2 = uid => {
1957
+ const getExtensionDetailVirtualDom2 = async uid => {
2426
1958
  const {
2427
1959
  newState
2428
1960
  } = get$1(uid);
2429
- return getExtensionDetailVirtualDom(newState, newState.sanitizedReadmeHtml, newState.selectedTab, newState);
1961
+ return await getExtensionDetailVirtualDom(newState, newState.sanitizedReadmeHtml, newState.selectedTab, newState);
2430
1962
  };
2431
1963
 
2432
1964
  const None = 0;
@@ -2506,21 +2038,6 @@ const handleClickFeatures = async (state, name) => {
2506
2038
  return selectFeature(state, name);
2507
2039
  };
2508
2040
 
2509
- const RendererWorker = 1;
2510
-
2511
- const rpcs = Object.create(null);
2512
- const set = (id, rpc) => {
2513
- rpcs[id] = rpc;
2514
- };
2515
- const get = id => {
2516
- return rpcs[id];
2517
- };
2518
-
2519
- const invoke = (method, ...params) => {
2520
- const rpc = get(RendererWorker);
2521
- return rpc.invoke(method, ...params);
2522
- };
2523
-
2524
2041
  const handleClickSize = async state => {
2525
2042
  const {
2526
2043
  uri
@@ -2609,2492 +2126,8 @@ const getThemeMarkdown = (themes, iconThemes, productIconThemes) => {
2609
2126
  return markdown;
2610
2127
  };
2611
2128
 
2612
- /**
2613
- * marked v15.0.6 - a markdown parser
2614
- * Copyright (c) 2011-2025, Christopher Jeffrey. (MIT Licensed)
2615
- * https://github.com/markedjs/marked
2616
- */
2617
-
2618
- /**
2619
- * DO NOT EDIT THIS FILE
2620
- * The code in this file is generated from files in ./src/
2621
- */
2622
-
2623
- /**
2624
- * Gets the original marked default options.
2625
- */
2626
- function _getDefaults() {
2627
- return {
2628
- async: false,
2629
- breaks: false,
2630
- extensions: null,
2631
- gfm: true,
2632
- hooks: null,
2633
- pedantic: false,
2634
- renderer: null,
2635
- silent: false,
2636
- tokenizer: null,
2637
- walkTokens: null
2638
- };
2639
- }
2640
- let _defaults = _getDefaults();
2641
- function changeDefaults(newDefaults) {
2642
- _defaults = newDefaults;
2643
- }
2644
- const noopTest = {
2645
- exec: () => null
2646
- };
2647
- function edit(regex, opt = '') {
2648
- let source = typeof regex === 'string' ? regex : regex.source;
2649
- const obj = {
2650
- replace: (name, val) => {
2651
- let valSource = typeof val === 'string' ? val : val.source;
2652
- valSource = valSource.replace(other.caret, '$1');
2653
- source = source.replace(name, valSource);
2654
- return obj;
2655
- },
2656
- getRegex: () => {
2657
- return new RegExp(source, opt);
2658
- }
2659
- };
2660
- return obj;
2661
- }
2662
- const other = {
2663
- codeRemoveIndent: /^(?: {1,4}| {0,3}\t)/gm,
2664
- outputLinkReplace: /\\([\[\]])/g,
2665
- indentCodeCompensation: /^(\s+)(?:```)/,
2666
- beginningSpace: /^\s+/,
2667
- endingHash: /#$/,
2668
- startingSpaceChar: /^ /,
2669
- endingSpaceChar: / $/,
2670
- nonSpaceChar: /[^ ]/,
2671
- newLineCharGlobal: /\n/g,
2672
- tabCharGlobal: /\t/g,
2673
- multipleSpaceGlobal: /\s+/g,
2674
- blankLine: /^[ \t]*$/,
2675
- doubleBlankLine: /\n[ \t]*\n[ \t]*$/,
2676
- blockquoteStart: /^ {0,3}>/,
2677
- blockquoteSetextReplace: /\n {0,3}((?:=+|-+) *)(?=\n|$)/g,
2678
- blockquoteSetextReplace2: /^ {0,3}>[ \t]?/gm,
2679
- listReplaceTabs: /^\t+/,
2680
- listReplaceNesting: /^ {1,4}(?=( {4})*[^ ])/g,
2681
- listIsTask: /^\[[ xX]\] /,
2682
- listReplaceTask: /^\[[ xX]\] +/,
2683
- anyLine: /\n.*\n/,
2684
- hrefBrackets: /^<(.*)>$/,
2685
- tableDelimiter: /[:|]/,
2686
- tableAlignChars: /^\||\| *$/g,
2687
- tableRowBlankLine: /\n[ \t]*$/,
2688
- tableAlignRight: /^ *-+: *$/,
2689
- tableAlignCenter: /^ *:-+: *$/,
2690
- tableAlignLeft: /^ *:-+ *$/,
2691
- startATag: /^<a /i,
2692
- endATag: /^<\/a>/i,
2693
- startPreScriptTag: /^<(pre|code|kbd|script)(\s|>)/i,
2694
- endPreScriptTag: /^<\/(pre|code|kbd|script)(\s|>)/i,
2695
- startAngleBracket: /^</,
2696
- endAngleBracket: />$/,
2697
- pedanticHrefTitle: /^([^'"]*[^\s])\s+(['"])(.*)\2/,
2698
- unicodeAlphaNumeric: /[\p{L}\p{N}]/u,
2699
- escapeTest: /[&<>"']/,
2700
- escapeReplace: /[&<>"']/g,
2701
- escapeTestNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,
2702
- escapeReplaceNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g,
2703
- unescapeTest: /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig,
2704
- caret: /(^|[^\[])\^/g,
2705
- percentDecode: /%25/g,
2706
- findPipe: /\|/g,
2707
- splitPipe: / \|/,
2708
- slashPipe: /\\\|/g,
2709
- carriageReturn: /\r\n|\r/g,
2710
- spaceLine: /^ +$/gm,
2711
- notSpaceStart: /^\S*/,
2712
- endingNewline: /\n$/,
2713
- listItemRegex: bull => new RegExp(`^( {0,3}${bull})((?:[\t ][^\\n]*)?(?:\\n|$))`),
2714
- nextBulletRegex: indent => new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ \t][^\\n]*)?(?:\\n|$))`),
2715
- hrRegex: indent => new RegExp(`^ {0,${Math.min(3, indent - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`),
2716
- fencesBeginRegex: indent => new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:\`\`\`|~~~)`),
2717
- headingBeginRegex: indent => new RegExp(`^ {0,${Math.min(3, indent - 1)}}#`),
2718
- htmlBeginRegex: indent => new RegExp(`^ {0,${Math.min(3, indent - 1)}}<(?:[a-z].*>|!--)`, 'i')
2719
- };
2720
- /**
2721
- * Block-Level Grammar
2722
- */
2723
- const newline = /^(?:[ \t]*(?:\n|$))+/;
2724
- const blockCode = /^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/;
2725
- const fences = /^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/;
2726
- const hr = /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/;
2727
- const heading = /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/;
2728
- const bullet = /(?:[*+-]|\d{1,9}[.)])/;
2729
- const lheading = edit(/^(?!bull |blockCode|fences|blockquote|heading|html)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html))+?)\n {0,3}(=+|-+) *(?:\n+|$)/).replace(/bull/g, bullet) // lists can interrupt
2730
- .replace(/blockCode/g, /(?: {4}| {0,3}\t)/) // indented code blocks can interrupt
2731
- .replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/) // fenced code blocks can interrupt
2732
- .replace(/blockquote/g, / {0,3}>/) // blockquote can interrupt
2733
- .replace(/heading/g, / {0,3}#{1,6}/) // ATX heading can interrupt
2734
- .replace(/html/g, / {0,3}<[^\n>]+>\n/) // block html can interrupt
2735
- .getRegex();
2736
- const _paragraph = /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/;
2737
- const blockText = /^[^\n]+/;
2738
- const _blockLabel = /(?!\s*\])(?:\\.|[^\[\]\\])+/;
2739
- const def = edit(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace('label', _blockLabel).replace('title', /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex();
2740
- const list = edit(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g, bullet).getRegex();
2741
- const _tag = 'address|article|aside|base|basefont|blockquote|body|caption' + '|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption' + '|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe' + '|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option' + '|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title' + '|tr|track|ul';
2742
- const _comment = /<!--(?:-?>|[\s\S]*?(?:-->|$))/;
2743
- const html = edit('^ {0,3}(?:' // optional indentation
2744
- + '<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)' // (1)
2745
- + '|comment[^\\n]*(\\n+|$)' // (2)
2746
- + '|<\\?[\\s\\S]*?(?:\\?>\\n*|$)' // (3)
2747
- + '|<![A-Z][\\s\\S]*?(?:>\\n*|$)' // (4)
2748
- + '|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)' // (5)
2749
- + '|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$)' // (6)
2750
- + '|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$)' // (7) open tag
2751
- + '|</(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$)' // (7) closing tag
2752
- + ')', 'i').replace('comment', _comment).replace('tag', _tag).replace('attribute', / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex();
2753
- const paragraph = edit(_paragraph).replace('hr', hr).replace('heading', ' {0,3}#{1,6}(?:\\s|$)').replace('|lheading', '') // setext headings don't interrupt commonmark paragraphs
2754
- .replace('|table', '').replace('blockquote', ' {0,3}>').replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n').replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
2755
- .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)').replace('tag', _tag) // pars can be interrupted by type (6) html blocks
2756
- .getRegex();
2757
- const blockquote = edit(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace('paragraph', paragraph).getRegex();
2758
- /**
2759
- * Normal Block Grammar
2760
- */
2761
- const blockNormal = {
2762
- blockquote,
2763
- code: blockCode,
2764
- def,
2765
- fences,
2766
- heading,
2767
- hr,
2768
- html,
2769
- lheading,
2770
- list,
2771
- newline,
2772
- paragraph,
2773
- table: noopTest,
2774
- text: blockText
2775
- };
2776
- /**
2777
- * GFM Block Grammar
2778
- */
2779
- const gfmTable = edit('^ *([^\\n ].*)\\n' // Header
2780
- + ' {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)' // Align
2781
- + '(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)') // Cells
2782
- .replace('hr', hr).replace('heading', ' {0,3}#{1,6}(?:\\s|$)').replace('blockquote', ' {0,3}>').replace('code', '(?: {4}| {0,3}\t)[^\\n]').replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n').replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
2783
- .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)').replace('tag', _tag) // tables can be interrupted by type (6) html blocks
2784
- .getRegex();
2785
- const blockGfm = {
2786
- ...blockNormal,
2787
- table: gfmTable,
2788
- paragraph: edit(_paragraph).replace('hr', hr).replace('heading', ' {0,3}#{1,6}(?:\\s|$)').replace('|lheading', '') // setext headings don't interrupt commonmark paragraphs
2789
- .replace('table', gfmTable) // interrupt paragraphs with table
2790
- .replace('blockquote', ' {0,3}>').replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n').replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
2791
- .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)').replace('tag', _tag) // pars can be interrupted by type (6) html blocks
2792
- .getRegex()
2793
- };
2794
- /**
2795
- * Pedantic grammar (original John Gruber's loose markdown specification)
2796
- */
2797
- const blockPedantic = {
2798
- ...blockNormal,
2799
- html: edit('^ *(?:comment *(?:\\n|\\s*$)' + '|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)' // closed tag
2800
- + '|<tag(?:"[^"]*"|\'[^\']*\'|\\s[^\'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))').replace('comment', _comment).replace(/tag/g, '(?!(?:' + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub' + '|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)' + '\\b)\\w+(?!:|[^\\w\\s@]*@)\\b').getRegex(),
2801
- def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,
2802
- heading: /^(#{1,6})(.*)(?:\n+|$)/,
2803
- fences: noopTest,
2804
- // fences not supported
2805
- lheading: /^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,
2806
- paragraph: edit(_paragraph).replace('hr', hr).replace('heading', ' *#{1,6} *[^\n]').replace('lheading', lheading).replace('|table', '').replace('blockquote', ' {0,3}>').replace('|fences', '').replace('|list', '').replace('|html', '').replace('|tag', '').getRegex()
2807
- };
2808
- /**
2809
- * Inline-Level Grammar
2810
- */
2811
- const escape$1 = /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/;
2812
- const inlineCode = /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/;
2813
- const br = /^( {2,}|\\)\n(?!\s*$)/;
2814
- const inlineText = /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/;
2815
- // list of unicode punctuation marks, plus any missing characters from CommonMark spec
2816
- const _punctuation = /[\p{P}\p{S}]/u;
2817
- const _punctuationOrSpace = /[\s\p{P}\p{S}]/u;
2818
- const _notPunctuationOrSpace = /[^\s\p{P}\p{S}]/u;
2819
- const punctuation = edit(/^((?![*_])punctSpace)/, 'u').replace(/punctSpace/g, _punctuationOrSpace).getRegex();
2820
- // GFM allows ~ inside strong and em for strikethrough
2821
- const _punctuationGfmStrongEm = /(?!~)[\p{P}\p{S}]/u;
2822
- const _punctuationOrSpaceGfmStrongEm = /(?!~)[\s\p{P}\p{S}]/u;
2823
- const _notPunctuationOrSpaceGfmStrongEm = /(?:[^\s\p{P}\p{S}]|~)/u;
2824
- // sequences em should skip over [title](link), `code`, <html>
2825
- const blockSkip = /\[[^[\]]*?\]\((?:\\.|[^\\\(\)]|\((?:\\.|[^\\\(\)])*\))*\)|`[^`]*?`|<[^<>]*?>/g;
2826
- const emStrongLDelimCore = /^(?:\*+(?:((?!\*)punct)|[^\s*]))|^_+(?:((?!_)punct)|([^\s_]))/;
2827
- const emStrongLDelim = edit(emStrongLDelimCore, 'u').replace(/punct/g, _punctuation).getRegex();
2828
- const emStrongLDelimGfm = edit(emStrongLDelimCore, 'u').replace(/punct/g, _punctuationGfmStrongEm).getRegex();
2829
- const emStrongRDelimAstCore = '^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)' // Skip orphan inside strong
2830
- + '|[^*]+(?=[^*])' // Consume to delim
2831
- + '|(?!\\*)punct(\\*+)(?=[\\s]|$)' // (1) #*** can only be a Right Delimiter
2832
- + '|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)' // (2) a***#, a*** can only be a Right Delimiter
2833
- + '|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)' // (3) #***a, ***a can only be Left Delimiter
2834
- + '|[\\s](\\*+)(?!\\*)(?=punct)' // (4) ***# can only be Left Delimiter
2835
- + '|(?!\\*)punct(\\*+)(?!\\*)(?=punct)' // (5) #***# can be either Left or Right Delimiter
2836
- + '|notPunctSpace(\\*+)(?=notPunctSpace)'; // (6) a***a can be either Left or Right Delimiter
2837
- const emStrongRDelimAst = edit(emStrongRDelimAstCore, 'gu').replace(/notPunctSpace/g, _notPunctuationOrSpace).replace(/punctSpace/g, _punctuationOrSpace).replace(/punct/g, _punctuation).getRegex();
2838
- const emStrongRDelimAstGfm = edit(emStrongRDelimAstCore, 'gu').replace(/notPunctSpace/g, _notPunctuationOrSpaceGfmStrongEm).replace(/punctSpace/g, _punctuationOrSpaceGfmStrongEm).replace(/punct/g, _punctuationGfmStrongEm).getRegex();
2839
- // (6) Not allowed for _
2840
- const emStrongRDelimUnd = edit('^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)' // Skip orphan inside strong
2841
- + '|[^_]+(?=[^_])' // Consume to delim
2842
- + '|(?!_)punct(_+)(?=[\\s]|$)' // (1) #___ can only be a Right Delimiter
2843
- + '|notPunctSpace(_+)(?!_)(?=punctSpace|$)' // (2) a___#, a___ can only be a Right Delimiter
2844
- + '|(?!_)punctSpace(_+)(?=notPunctSpace)' // (3) #___a, ___a can only be Left Delimiter
2845
- + '|[\\s](_+)(?!_)(?=punct)' // (4) ___# can only be Left Delimiter
2846
- + '|(?!_)punct(_+)(?!_)(?=punct)', 'gu') // (5) #___# can be either Left or Right Delimiter
2847
- .replace(/notPunctSpace/g, _notPunctuationOrSpace).replace(/punctSpace/g, _punctuationOrSpace).replace(/punct/g, _punctuation).getRegex();
2848
- const anyPunctuation = edit(/\\(punct)/, 'gu').replace(/punct/g, _punctuation).getRegex();
2849
- const autolink = edit(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace('scheme', /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace('email', /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex();
2850
- const _inlineComment = edit(_comment).replace('(?:-->|$)', '-->').getRegex();
2851
- const tag = edit('^comment' + '|^</[a-zA-Z][\\w:-]*\\s*>' // self-closing tag
2852
- + '|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>' // open tag
2853
- + '|^<\\?[\\s\\S]*?\\?>' // processing instruction, e.g. <?php ?>
2854
- + '|^<![a-zA-Z]+\\s[\\s\\S]*?>' // declaration, e.g. <!DOCTYPE html>
2855
- + '|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>') // CDATA section
2856
- .replace('comment', _inlineComment).replace('attribute', /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex();
2857
- const _inlineLabel = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/;
2858
- const link = edit(/^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/).replace('label', _inlineLabel).replace('href', /<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/).replace('title', /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex();
2859
- const reflink = edit(/^!?\[(label)\]\[(ref)\]/).replace('label', _inlineLabel).replace('ref', _blockLabel).getRegex();
2860
- const nolink = edit(/^!?\[(ref)\](?:\[\])?/).replace('ref', _blockLabel).getRegex();
2861
- const reflinkSearch = edit('reflink|nolink(?!\\()', 'g').replace('reflink', reflink).replace('nolink', nolink).getRegex();
2862
- /**
2863
- * Normal Inline Grammar
2864
- */
2865
- const inlineNormal = {
2866
- _backpedal: noopTest,
2867
- // only used for GFM url
2868
- anyPunctuation,
2869
- autolink,
2870
- blockSkip,
2871
- br,
2872
- code: inlineCode,
2873
- del: noopTest,
2874
- emStrongLDelim,
2875
- emStrongRDelimAst,
2876
- emStrongRDelimUnd,
2877
- escape: escape$1,
2878
- link,
2879
- nolink,
2880
- punctuation,
2881
- reflink,
2882
- reflinkSearch,
2883
- tag,
2884
- text: inlineText,
2885
- url: noopTest
2886
- };
2887
- /**
2888
- * Pedantic Inline Grammar
2889
- */
2890
- const inlinePedantic = {
2891
- ...inlineNormal,
2892
- link: edit(/^!?\[(label)\]\((.*?)\)/).replace('label', _inlineLabel).getRegex(),
2893
- reflink: edit(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace('label', _inlineLabel).getRegex()
2894
- };
2895
- /**
2896
- * GFM Inline Grammar
2897
- */
2898
- const inlineGfm = {
2899
- ...inlineNormal,
2900
- emStrongRDelimAst: emStrongRDelimAstGfm,
2901
- emStrongLDelim: emStrongLDelimGfm,
2902
- url: edit(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/, 'i').replace('email', /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(),
2903
- _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/,
2904
- del: /^(~~?)(?=[^\s~])((?:\\.|[^\\])*?(?:\\.|[^\s~\\]))\1(?=[^~]|$)/,
2905
- text: /^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|https?:\/\/|ftp:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/
2906
- };
2907
- /**
2908
- * GFM + Line Breaks Inline Grammar
2909
- */
2910
- const inlineBreaks = {
2911
- ...inlineGfm,
2912
- br: edit(br).replace('{2,}', '*').getRegex(),
2913
- text: edit(inlineGfm.text).replace('\\b_', '\\b_| {2,}\\n').replace(/\{2,\}/g, '*').getRegex()
2914
- };
2915
- /**
2916
- * exports
2917
- */
2918
- const block = {
2919
- normal: blockNormal,
2920
- gfm: blockGfm,
2921
- pedantic: blockPedantic
2922
- };
2923
- const inline = {
2924
- normal: inlineNormal,
2925
- gfm: inlineGfm,
2926
- breaks: inlineBreaks,
2927
- pedantic: inlinePedantic
2928
- };
2929
-
2930
- /**
2931
- * Helpers
2932
- */
2933
- const escapeReplacements = {
2934
- '&': '&amp;',
2935
- '<': '&lt;',
2936
- '>': '&gt;',
2937
- '"': '&quot;',
2938
- "'": '&#39;'
2939
- };
2940
- const getEscapeReplacement = ch => escapeReplacements[ch];
2941
- function escape(html, encode) {
2942
- if (encode) {
2943
- if (other.escapeTest.test(html)) {
2944
- return html.replace(other.escapeReplace, getEscapeReplacement);
2945
- }
2946
- } else {
2947
- if (other.escapeTestNoEncode.test(html)) {
2948
- return html.replace(other.escapeReplaceNoEncode, getEscapeReplacement);
2949
- }
2950
- }
2951
- return html;
2952
- }
2953
- function cleanUrl(href) {
2954
- try {
2955
- href = encodeURI(href).replace(other.percentDecode, '%');
2956
- } catch {
2957
- return null;
2958
- }
2959
- return href;
2960
- }
2961
- function splitCells(tableRow, count) {
2962
- // ensure that every cell-delimiting pipe has a space
2963
- // before it to distinguish it from an escaped pipe
2964
- const row = tableRow.replace(other.findPipe, (match, offset, str) => {
2965
- let escaped = false;
2966
- let curr = offset;
2967
- while (--curr >= 0 && str[curr] === '\\') escaped = !escaped;
2968
- if (escaped) {
2969
- // odd number of slashes means | is escaped
2970
- // so we leave it alone
2971
- return '|';
2972
- } else {
2973
- // add space before unescaped |
2974
- return ' |';
2975
- }
2976
- }),
2977
- cells = row.split(other.splitPipe);
2978
- let i = 0;
2979
- // First/last cell in a row cannot be empty if it has no leading/trailing pipe
2980
- if (!cells[0].trim()) {
2981
- cells.shift();
2982
- }
2983
- if (cells.length > 0 && !cells.at(-1)?.trim()) {
2984
- cells.pop();
2985
- }
2986
- if (count) {
2987
- if (cells.length > count) {
2988
- cells.splice(count);
2989
- } else {
2990
- while (cells.length < count) cells.push('');
2991
- }
2992
- }
2993
- for (; i < cells.length; i++) {
2994
- // leading or trailing whitespace is ignored per the gfm spec
2995
- cells[i] = cells[i].trim().replace(other.slashPipe, '|');
2996
- }
2997
- return cells;
2998
- }
2999
- /**
3000
- * Remove trailing 'c's. Equivalent to str.replace(/c*$/, '').
3001
- * /c*$/ is vulnerable to REDOS.
3002
- *
3003
- * @param str
3004
- * @param c
3005
- * @param invert Remove suffix of non-c chars instead. Default falsey.
3006
- */
3007
- function rtrim(str, c, invert) {
3008
- const l = str.length;
3009
- if (l === 0) {
3010
- return '';
3011
- }
3012
- // Length of suffix matching the invert condition.
3013
- let suffLen = 0;
3014
- // Step left until we fail to match the invert condition.
3015
- while (suffLen < l) {
3016
- const currChar = str.charAt(l - suffLen - 1);
3017
- if (currChar === c && true) {
3018
- suffLen++;
3019
- } else {
3020
- break;
3021
- }
3022
- }
3023
- return str.slice(0, l - suffLen);
3024
- }
3025
- function findClosingBracket(str, b) {
3026
- if (str.indexOf(b[1]) === -1) {
3027
- return -1;
3028
- }
3029
- let level = 0;
3030
- for (let i = 0; i < str.length; i++) {
3031
- if (str[i] === '\\') {
3032
- i++;
3033
- } else if (str[i] === b[0]) {
3034
- level++;
3035
- } else if (str[i] === b[1]) {
3036
- level--;
3037
- if (level < 0) {
3038
- return i;
3039
- }
3040
- }
3041
- }
3042
- return -1;
3043
- }
3044
- function outputLink(cap, link, raw, lexer, rules) {
3045
- const href = link.href;
3046
- const title = link.title || null;
3047
- const text = cap[1].replace(rules.other.outputLinkReplace, '$1');
3048
- if (cap[0].charAt(0) !== '!') {
3049
- lexer.state.inLink = true;
3050
- const token = {
3051
- type: 'link',
3052
- raw,
3053
- href,
3054
- title,
3055
- text,
3056
- tokens: lexer.inlineTokens(text)
3057
- };
3058
- lexer.state.inLink = false;
3059
- return token;
3060
- }
3061
- return {
3062
- type: 'image',
3063
- raw,
3064
- href,
3065
- title,
3066
- text
3067
- };
3068
- }
3069
- function indentCodeCompensation(raw, text, rules) {
3070
- const matchIndentToCode = raw.match(rules.other.indentCodeCompensation);
3071
- if (matchIndentToCode === null) {
3072
- return text;
3073
- }
3074
- const indentToCode = matchIndentToCode[1];
3075
- return text.split('\n').map(node => {
3076
- const matchIndentInNode = node.match(rules.other.beginningSpace);
3077
- if (matchIndentInNode === null) {
3078
- return node;
3079
- }
3080
- const [indentInNode] = matchIndentInNode;
3081
- if (indentInNode.length >= indentToCode.length) {
3082
- return node.slice(indentToCode.length);
3083
- }
3084
- return node;
3085
- }).join('\n');
3086
- }
3087
- /**
3088
- * Tokenizer
3089
- */
3090
- class _Tokenizer {
3091
- options;
3092
- rules; // set by the lexer
3093
- lexer; // set by the lexer
3094
- constructor(options) {
3095
- this.options = options || _defaults;
3096
- }
3097
- space(src) {
3098
- const cap = this.rules.block.newline.exec(src);
3099
- if (cap && cap[0].length > 0) {
3100
- return {
3101
- type: 'space',
3102
- raw: cap[0]
3103
- };
3104
- }
3105
- }
3106
- code(src) {
3107
- const cap = this.rules.block.code.exec(src);
3108
- if (cap) {
3109
- const text = cap[0].replace(this.rules.other.codeRemoveIndent, '');
3110
- return {
3111
- type: 'code',
3112
- raw: cap[0],
3113
- codeBlockStyle: 'indented',
3114
- text: !this.options.pedantic ? rtrim(text, '\n') : text
3115
- };
3116
- }
3117
- }
3118
- fences(src) {
3119
- const cap = this.rules.block.fences.exec(src);
3120
- if (cap) {
3121
- const raw = cap[0];
3122
- const text = indentCodeCompensation(raw, cap[3] || '', this.rules);
3123
- return {
3124
- type: 'code',
3125
- raw,
3126
- lang: cap[2] ? cap[2].trim().replace(this.rules.inline.anyPunctuation, '$1') : cap[2],
3127
- text
3128
- };
3129
- }
3130
- }
3131
- heading(src) {
3132
- const cap = this.rules.block.heading.exec(src);
3133
- if (cap) {
3134
- let text = cap[2].trim();
3135
- // remove trailing #s
3136
- if (this.rules.other.endingHash.test(text)) {
3137
- const trimmed = rtrim(text, '#');
3138
- if (this.options.pedantic) {
3139
- text = trimmed.trim();
3140
- } else if (!trimmed || this.rules.other.endingSpaceChar.test(trimmed)) {
3141
- // CommonMark requires space before trailing #s
3142
- text = trimmed.trim();
3143
- }
3144
- }
3145
- return {
3146
- type: 'heading',
3147
- raw: cap[0],
3148
- depth: cap[1].length,
3149
- text,
3150
- tokens: this.lexer.inline(text)
3151
- };
3152
- }
3153
- }
3154
- hr(src) {
3155
- const cap = this.rules.block.hr.exec(src);
3156
- if (cap) {
3157
- return {
3158
- type: 'hr',
3159
- raw: rtrim(cap[0], '\n')
3160
- };
3161
- }
3162
- }
3163
- blockquote(src) {
3164
- const cap = this.rules.block.blockquote.exec(src);
3165
- if (cap) {
3166
- let lines = rtrim(cap[0], '\n').split('\n');
3167
- let raw = '';
3168
- let text = '';
3169
- const tokens = [];
3170
- while (lines.length > 0) {
3171
- let inBlockquote = false;
3172
- const currentLines = [];
3173
- let i;
3174
- for (i = 0; i < lines.length; i++) {
3175
- // get lines up to a continuation
3176
- if (this.rules.other.blockquoteStart.test(lines[i])) {
3177
- currentLines.push(lines[i]);
3178
- inBlockquote = true;
3179
- } else if (!inBlockquote) {
3180
- currentLines.push(lines[i]);
3181
- } else {
3182
- break;
3183
- }
3184
- }
3185
- lines = lines.slice(i);
3186
- const currentRaw = currentLines.join('\n');
3187
- const currentText = currentRaw
3188
- // precede setext continuation with 4 spaces so it isn't a setext
3189
- .replace(this.rules.other.blockquoteSetextReplace, '\n $1').replace(this.rules.other.blockquoteSetextReplace2, '');
3190
- raw = raw ? `${raw}\n${currentRaw}` : currentRaw;
3191
- text = text ? `${text}\n${currentText}` : currentText;
3192
- // parse blockquote lines as top level tokens
3193
- // merge paragraphs if this is a continuation
3194
- const top = this.lexer.state.top;
3195
- this.lexer.state.top = true;
3196
- this.lexer.blockTokens(currentText, tokens, true);
3197
- this.lexer.state.top = top;
3198
- // if there is no continuation then we are done
3199
- if (lines.length === 0) {
3200
- break;
3201
- }
3202
- const lastToken = tokens.at(-1);
3203
- if (lastToken?.type === 'code') {
3204
- // blockquote continuation cannot be preceded by a code block
3205
- break;
3206
- } else if (lastToken?.type === 'blockquote') {
3207
- // include continuation in nested blockquote
3208
- const oldToken = lastToken;
3209
- const newText = oldToken.raw + '\n' + lines.join('\n');
3210
- const newToken = this.blockquote(newText);
3211
- tokens[tokens.length - 1] = newToken;
3212
- raw = raw.substring(0, raw.length - oldToken.raw.length) + newToken.raw;
3213
- text = text.substring(0, text.length - oldToken.text.length) + newToken.text;
3214
- break;
3215
- } else if (lastToken?.type === 'list') {
3216
- // include continuation in nested list
3217
- const oldToken = lastToken;
3218
- const newText = oldToken.raw + '\n' + lines.join('\n');
3219
- const newToken = this.list(newText);
3220
- tokens[tokens.length - 1] = newToken;
3221
- raw = raw.substring(0, raw.length - lastToken.raw.length) + newToken.raw;
3222
- text = text.substring(0, text.length - oldToken.raw.length) + newToken.raw;
3223
- lines = newText.substring(tokens.at(-1).raw.length).split('\n');
3224
- continue;
3225
- }
3226
- }
3227
- return {
3228
- type: 'blockquote',
3229
- raw,
3230
- tokens,
3231
- text
3232
- };
3233
- }
3234
- }
3235
- list(src) {
3236
- let cap = this.rules.block.list.exec(src);
3237
- if (cap) {
3238
- let bull = cap[1].trim();
3239
- const isordered = bull.length > 1;
3240
- const list = {
3241
- type: 'list',
3242
- raw: '',
3243
- ordered: isordered,
3244
- start: isordered ? +bull.slice(0, -1) : '',
3245
- loose: false,
3246
- items: []
3247
- };
3248
- bull = isordered ? `\\d{1,9}\\${bull.slice(-1)}` : `\\${bull}`;
3249
- if (this.options.pedantic) {
3250
- bull = isordered ? bull : '[*+-]';
3251
- }
3252
- // Get next list item
3253
- const itemRegex = this.rules.other.listItemRegex(bull);
3254
- let endsWithBlankLine = false;
3255
- // Check if current bullet point can start a new List Item
3256
- while (src) {
3257
- let endEarly = false;
3258
- let raw = '';
3259
- let itemContents = '';
3260
- if (!(cap = itemRegex.exec(src))) {
3261
- break;
3262
- }
3263
- if (this.rules.block.hr.test(src)) {
3264
- // End list if bullet was actually HR (possibly move into itemRegex?)
3265
- break;
3266
- }
3267
- raw = cap[0];
3268
- src = src.substring(raw.length);
3269
- let line = cap[2].split('\n', 1)[0].replace(this.rules.other.listReplaceTabs, t => ' '.repeat(3 * t.length));
3270
- let nextLine = src.split('\n', 1)[0];
3271
- let blankLine = !line.trim();
3272
- let indent = 0;
3273
- if (this.options.pedantic) {
3274
- indent = 2;
3275
- itemContents = line.trimStart();
3276
- } else if (blankLine) {
3277
- indent = cap[1].length + 1;
3278
- } else {
3279
- indent = cap[2].search(this.rules.other.nonSpaceChar); // Find first non-space char
3280
- indent = indent > 4 ? 1 : indent; // Treat indented code blocks (> 4 spaces) as having only 1 indent
3281
- itemContents = line.slice(indent);
3282
- indent += cap[1].length;
3283
- }
3284
- if (blankLine && this.rules.other.blankLine.test(nextLine)) {
3285
- // Items begin with at most one blank line
3286
- raw += nextLine + '\n';
3287
- src = src.substring(nextLine.length + 1);
3288
- endEarly = true;
3289
- }
3290
- if (!endEarly) {
3291
- const nextBulletRegex = this.rules.other.nextBulletRegex(indent);
3292
- const hrRegex = this.rules.other.hrRegex(indent);
3293
- const fencesBeginRegex = this.rules.other.fencesBeginRegex(indent);
3294
- const headingBeginRegex = this.rules.other.headingBeginRegex(indent);
3295
- const htmlBeginRegex = this.rules.other.htmlBeginRegex(indent);
3296
- // Check if following lines should be included in List Item
3297
- while (src) {
3298
- const rawLine = src.split('\n', 1)[0];
3299
- let nextLineWithoutTabs;
3300
- nextLine = rawLine;
3301
- // Re-align to follow commonmark nesting rules
3302
- if (this.options.pedantic) {
3303
- nextLine = nextLine.replace(this.rules.other.listReplaceNesting, ' ');
3304
- nextLineWithoutTabs = nextLine;
3305
- } else {
3306
- nextLineWithoutTabs = nextLine.replace(this.rules.other.tabCharGlobal, ' ');
3307
- }
3308
- // End list item if found code fences
3309
- if (fencesBeginRegex.test(nextLine)) {
3310
- break;
3311
- }
3312
- // End list item if found start of new heading
3313
- if (headingBeginRegex.test(nextLine)) {
3314
- break;
3315
- }
3316
- // End list item if found start of html block
3317
- if (htmlBeginRegex.test(nextLine)) {
3318
- break;
3319
- }
3320
- // End list item if found start of new bullet
3321
- if (nextBulletRegex.test(nextLine)) {
3322
- break;
3323
- }
3324
- // Horizontal rule found
3325
- if (hrRegex.test(nextLine)) {
3326
- break;
3327
- }
3328
- if (nextLineWithoutTabs.search(this.rules.other.nonSpaceChar) >= indent || !nextLine.trim()) {
3329
- // Dedent if possible
3330
- itemContents += '\n' + nextLineWithoutTabs.slice(indent);
3331
- } else {
3332
- // not enough indentation
3333
- if (blankLine) {
3334
- break;
3335
- }
3336
- // paragraph continuation unless last line was a different block level element
3337
- if (line.replace(this.rules.other.tabCharGlobal, ' ').search(this.rules.other.nonSpaceChar) >= 4) {
3338
- // indented code block
3339
- break;
3340
- }
3341
- if (fencesBeginRegex.test(line)) {
3342
- break;
3343
- }
3344
- if (headingBeginRegex.test(line)) {
3345
- break;
3346
- }
3347
- if (hrRegex.test(line)) {
3348
- break;
3349
- }
3350
- itemContents += '\n' + nextLine;
3351
- }
3352
- if (!blankLine && !nextLine.trim()) {
3353
- // Check if current line is blank
3354
- blankLine = true;
3355
- }
3356
- raw += rawLine + '\n';
3357
- src = src.substring(rawLine.length + 1);
3358
- line = nextLineWithoutTabs.slice(indent);
3359
- }
3360
- }
3361
- if (!list.loose) {
3362
- // If the previous item ended with a blank line, the list is loose
3363
- if (endsWithBlankLine) {
3364
- list.loose = true;
3365
- } else if (this.rules.other.doubleBlankLine.test(raw)) {
3366
- endsWithBlankLine = true;
3367
- }
3368
- }
3369
- let istask = null;
3370
- let ischecked;
3371
- // Check for task list items
3372
- if (this.options.gfm) {
3373
- istask = this.rules.other.listIsTask.exec(itemContents);
3374
- if (istask) {
3375
- ischecked = istask[0] !== '[ ] ';
3376
- itemContents = itemContents.replace(this.rules.other.listReplaceTask, '');
3377
- }
3378
- }
3379
- list.items.push({
3380
- type: 'list_item',
3381
- raw,
3382
- task: !!istask,
3383
- checked: ischecked,
3384
- loose: false,
3385
- text: itemContents,
3386
- tokens: []
3387
- });
3388
- list.raw += raw;
3389
- }
3390
- // Do not consume newlines at end of final item. Alternatively, make itemRegex *start* with any newlines to simplify/speed up endsWithBlankLine logic
3391
- const lastItem = list.items.at(-1);
3392
- if (lastItem) {
3393
- lastItem.raw = lastItem.raw.trimEnd();
3394
- lastItem.text = lastItem.text.trimEnd();
3395
- } else {
3396
- // not a list since there were no items
3397
- return;
3398
- }
3399
- list.raw = list.raw.trimEnd();
3400
- // Item child tokens handled here at end because we needed to have the final item to trim it first
3401
- for (let i = 0; i < list.items.length; i++) {
3402
- this.lexer.state.top = false;
3403
- list.items[i].tokens = this.lexer.blockTokens(list.items[i].text, []);
3404
- if (!list.loose) {
3405
- // Check if list should be loose
3406
- const spacers = list.items[i].tokens.filter(t => t.type === 'space');
3407
- const hasMultipleLineBreaks = spacers.length > 0 && spacers.some(t => this.rules.other.anyLine.test(t.raw));
3408
- list.loose = hasMultipleLineBreaks;
3409
- }
3410
- }
3411
- // Set all items to loose if list is loose
3412
- if (list.loose) {
3413
- for (let i = 0; i < list.items.length; i++) {
3414
- list.items[i].loose = true;
3415
- }
3416
- }
3417
- return list;
3418
- }
3419
- }
3420
- html(src) {
3421
- const cap = this.rules.block.html.exec(src);
3422
- if (cap) {
3423
- const token = {
3424
- type: 'html',
3425
- block: true,
3426
- raw: cap[0],
3427
- pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style',
3428
- text: cap[0]
3429
- };
3430
- return token;
3431
- }
3432
- }
3433
- def(src) {
3434
- const cap = this.rules.block.def.exec(src);
3435
- if (cap) {
3436
- const tag = cap[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal, ' ');
3437
- const href = cap[2] ? cap[2].replace(this.rules.other.hrefBrackets, '$1').replace(this.rules.inline.anyPunctuation, '$1') : '';
3438
- const title = cap[3] ? cap[3].substring(1, cap[3].length - 1).replace(this.rules.inline.anyPunctuation, '$1') : cap[3];
3439
- return {
3440
- type: 'def',
3441
- tag,
3442
- raw: cap[0],
3443
- href,
3444
- title
3445
- };
3446
- }
3447
- }
3448
- table(src) {
3449
- const cap = this.rules.block.table.exec(src);
3450
- if (!cap) {
3451
- return;
3452
- }
3453
- if (!this.rules.other.tableDelimiter.test(cap[2])) {
3454
- // delimiter row must have a pipe (|) or colon (:) otherwise it is a setext heading
3455
- return;
3456
- }
3457
- const headers = splitCells(cap[1]);
3458
- const aligns = cap[2].replace(this.rules.other.tableAlignChars, '').split('|');
3459
- const rows = cap[3]?.trim() ? cap[3].replace(this.rules.other.tableRowBlankLine, '').split('\n') : [];
3460
- const item = {
3461
- type: 'table',
3462
- raw: cap[0],
3463
- header: [],
3464
- align: [],
3465
- rows: []
3466
- };
3467
- if (headers.length !== aligns.length) {
3468
- // header and align columns must be equal, rows can be different.
3469
- return;
3470
- }
3471
- for (const align of aligns) {
3472
- if (this.rules.other.tableAlignRight.test(align)) {
3473
- item.align.push('right');
3474
- } else if (this.rules.other.tableAlignCenter.test(align)) {
3475
- item.align.push('center');
3476
- } else if (this.rules.other.tableAlignLeft.test(align)) {
3477
- item.align.push('left');
3478
- } else {
3479
- item.align.push(null);
3480
- }
3481
- }
3482
- for (let i = 0; i < headers.length; i++) {
3483
- item.header.push({
3484
- text: headers[i],
3485
- tokens: this.lexer.inline(headers[i]),
3486
- header: true,
3487
- align: item.align[i]
3488
- });
3489
- }
3490
- for (const row of rows) {
3491
- item.rows.push(splitCells(row, item.header.length).map((cell, i) => {
3492
- return {
3493
- text: cell,
3494
- tokens: this.lexer.inline(cell),
3495
- header: false,
3496
- align: item.align[i]
3497
- };
3498
- }));
3499
- }
3500
- return item;
3501
- }
3502
- lheading(src) {
3503
- const cap = this.rules.block.lheading.exec(src);
3504
- if (cap) {
3505
- return {
3506
- type: 'heading',
3507
- raw: cap[0],
3508
- depth: cap[2].charAt(0) === '=' ? 1 : 2,
3509
- text: cap[1],
3510
- tokens: this.lexer.inline(cap[1])
3511
- };
3512
- }
3513
- }
3514
- paragraph(src) {
3515
- const cap = this.rules.block.paragraph.exec(src);
3516
- if (cap) {
3517
- const text = cap[1].charAt(cap[1].length - 1) === '\n' ? cap[1].slice(0, -1) : cap[1];
3518
- return {
3519
- type: 'paragraph',
3520
- raw: cap[0],
3521
- text,
3522
- tokens: this.lexer.inline(text)
3523
- };
3524
- }
3525
- }
3526
- text(src) {
3527
- const cap = this.rules.block.text.exec(src);
3528
- if (cap) {
3529
- return {
3530
- type: 'text',
3531
- raw: cap[0],
3532
- text: cap[0],
3533
- tokens: this.lexer.inline(cap[0])
3534
- };
3535
- }
3536
- }
3537
- escape(src) {
3538
- const cap = this.rules.inline.escape.exec(src);
3539
- if (cap) {
3540
- return {
3541
- type: 'escape',
3542
- raw: cap[0],
3543
- text: cap[1]
3544
- };
3545
- }
3546
- }
3547
- tag(src) {
3548
- const cap = this.rules.inline.tag.exec(src);
3549
- if (cap) {
3550
- if (!this.lexer.state.inLink && this.rules.other.startATag.test(cap[0])) {
3551
- this.lexer.state.inLink = true;
3552
- } else if (this.lexer.state.inLink && this.rules.other.endATag.test(cap[0])) {
3553
- this.lexer.state.inLink = false;
3554
- }
3555
- if (!this.lexer.state.inRawBlock && this.rules.other.startPreScriptTag.test(cap[0])) {
3556
- this.lexer.state.inRawBlock = true;
3557
- } else if (this.lexer.state.inRawBlock && this.rules.other.endPreScriptTag.test(cap[0])) {
3558
- this.lexer.state.inRawBlock = false;
3559
- }
3560
- return {
3561
- type: 'html',
3562
- raw: cap[0],
3563
- inLink: this.lexer.state.inLink,
3564
- inRawBlock: this.lexer.state.inRawBlock,
3565
- block: false,
3566
- text: cap[0]
3567
- };
3568
- }
3569
- }
3570
- link(src) {
3571
- const cap = this.rules.inline.link.exec(src);
3572
- if (cap) {
3573
- const trimmedUrl = cap[2].trim();
3574
- if (!this.options.pedantic && this.rules.other.startAngleBracket.test(trimmedUrl)) {
3575
- // commonmark requires matching angle brackets
3576
- if (!this.rules.other.endAngleBracket.test(trimmedUrl)) {
3577
- return;
3578
- }
3579
- // ending angle bracket cannot be escaped
3580
- const rtrimSlash = rtrim(trimmedUrl.slice(0, -1), '\\');
3581
- if ((trimmedUrl.length - rtrimSlash.length) % 2 === 0) {
3582
- return;
3583
- }
3584
- } else {
3585
- // find closing parenthesis
3586
- const lastParenIndex = findClosingBracket(cap[2], '()');
3587
- if (lastParenIndex > -1) {
3588
- const start = cap[0].indexOf('!') === 0 ? 5 : 4;
3589
- const linkLen = start + cap[1].length + lastParenIndex;
3590
- cap[2] = cap[2].substring(0, lastParenIndex);
3591
- cap[0] = cap[0].substring(0, linkLen).trim();
3592
- cap[3] = '';
3593
- }
3594
- }
3595
- let href = cap[2];
3596
- let title = '';
3597
- if (this.options.pedantic) {
3598
- // split pedantic href and title
3599
- const link = this.rules.other.pedanticHrefTitle.exec(href);
3600
- if (link) {
3601
- href = link[1];
3602
- title = link[3];
3603
- }
3604
- } else {
3605
- title = cap[3] ? cap[3].slice(1, -1) : '';
3606
- }
3607
- href = href.trim();
3608
- if (this.rules.other.startAngleBracket.test(href)) {
3609
- if (this.options.pedantic && !this.rules.other.endAngleBracket.test(trimmedUrl)) {
3610
- // pedantic allows starting angle bracket without ending angle bracket
3611
- href = href.slice(1);
3612
- } else {
3613
- href = href.slice(1, -1);
3614
- }
3615
- }
3616
- return outputLink(cap, {
3617
- href: href ? href.replace(this.rules.inline.anyPunctuation, '$1') : href,
3618
- title: title ? title.replace(this.rules.inline.anyPunctuation, '$1') : title
3619
- }, cap[0], this.lexer, this.rules);
3620
- }
3621
- }
3622
- reflink(src, links) {
3623
- let cap;
3624
- if ((cap = this.rules.inline.reflink.exec(src)) || (cap = this.rules.inline.nolink.exec(src))) {
3625
- const linkString = (cap[2] || cap[1]).replace(this.rules.other.multipleSpaceGlobal, ' ');
3626
- const link = links[linkString.toLowerCase()];
3627
- if (!link) {
3628
- const text = cap[0].charAt(0);
3629
- return {
3630
- type: 'text',
3631
- raw: text,
3632
- text
3633
- };
3634
- }
3635
- return outputLink(cap, link, cap[0], this.lexer, this.rules);
3636
- }
3637
- }
3638
- emStrong(src, maskedSrc, prevChar = '') {
3639
- let match = this.rules.inline.emStrongLDelim.exec(src);
3640
- if (!match) return;
3641
- // _ can't be between two alphanumerics. \p{L}\p{N} includes non-english alphabet/numbers as well
3642
- if (match[3] && prevChar.match(this.rules.other.unicodeAlphaNumeric)) return;
3643
- const nextChar = match[1] || match[2] || '';
3644
- if (!nextChar || !prevChar || this.rules.inline.punctuation.exec(prevChar)) {
3645
- // unicode Regex counts emoji as 1 char; spread into array for proper count (used multiple times below)
3646
- const lLength = [...match[0]].length - 1;
3647
- let rDelim,
3648
- rLength,
3649
- delimTotal = lLength,
3650
- midDelimTotal = 0;
3651
- const endReg = match[0][0] === '*' ? this.rules.inline.emStrongRDelimAst : this.rules.inline.emStrongRDelimUnd;
3652
- endReg.lastIndex = 0;
3653
- // Clip maskedSrc to same section of string as src (move to lexer?)
3654
- maskedSrc = maskedSrc.slice(-1 * src.length + lLength);
3655
- while ((match = endReg.exec(maskedSrc)) != null) {
3656
- rDelim = match[1] || match[2] || match[3] || match[4] || match[5] || match[6];
3657
- if (!rDelim) continue; // skip single * in __abc*abc__
3658
- rLength = [...rDelim].length;
3659
- if (match[3] || match[4]) {
3660
- // found another Left Delim
3661
- delimTotal += rLength;
3662
- continue;
3663
- } else if (match[5] || match[6]) {
3664
- // either Left or Right Delim
3665
- if (lLength % 3 && !((lLength + rLength) % 3)) {
3666
- midDelimTotal += rLength;
3667
- continue; // CommonMark Emphasis Rules 9-10
3668
- }
3669
- }
3670
- delimTotal -= rLength;
3671
- if (delimTotal > 0) continue; // Haven't found enough closing delimiters
3672
- // Remove extra characters. *a*** -> *a*
3673
- rLength = Math.min(rLength, rLength + delimTotal + midDelimTotal);
3674
- // char length can be >1 for unicode characters;
3675
- const lastCharLength = [...match[0]][0].length;
3676
- const raw = src.slice(0, lLength + match.index + lastCharLength + rLength);
3677
- // Create `em` if smallest delimiter has odd char count. *a***
3678
- if (Math.min(lLength, rLength) % 2) {
3679
- const text = raw.slice(1, -1);
3680
- return {
3681
- type: 'em',
3682
- raw,
3683
- text,
3684
- tokens: this.lexer.inlineTokens(text)
3685
- };
3686
- }
3687
- // Create 'strong' if smallest delimiter has even char count. **a***
3688
- const text = raw.slice(2, -2);
3689
- return {
3690
- type: 'strong',
3691
- raw,
3692
- text,
3693
- tokens: this.lexer.inlineTokens(text)
3694
- };
3695
- }
3696
- }
3697
- }
3698
- codespan(src) {
3699
- const cap = this.rules.inline.code.exec(src);
3700
- if (cap) {
3701
- let text = cap[2].replace(this.rules.other.newLineCharGlobal, ' ');
3702
- const hasNonSpaceChars = this.rules.other.nonSpaceChar.test(text);
3703
- const hasSpaceCharsOnBothEnds = this.rules.other.startingSpaceChar.test(text) && this.rules.other.endingSpaceChar.test(text);
3704
- if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) {
3705
- text = text.substring(1, text.length - 1);
3706
- }
3707
- return {
3708
- type: 'codespan',
3709
- raw: cap[0],
3710
- text
3711
- };
3712
- }
3713
- }
3714
- br(src) {
3715
- const cap = this.rules.inline.br.exec(src);
3716
- if (cap) {
3717
- return {
3718
- type: 'br',
3719
- raw: cap[0]
3720
- };
3721
- }
3722
- }
3723
- del(src) {
3724
- const cap = this.rules.inline.del.exec(src);
3725
- if (cap) {
3726
- return {
3727
- type: 'del',
3728
- raw: cap[0],
3729
- text: cap[2],
3730
- tokens: this.lexer.inlineTokens(cap[2])
3731
- };
3732
- }
3733
- }
3734
- autolink(src) {
3735
- const cap = this.rules.inline.autolink.exec(src);
3736
- if (cap) {
3737
- let text, href;
3738
- if (cap[2] === '@') {
3739
- text = cap[1];
3740
- href = 'mailto:' + text;
3741
- } else {
3742
- text = cap[1];
3743
- href = text;
3744
- }
3745
- return {
3746
- type: 'link',
3747
- raw: cap[0],
3748
- text,
3749
- href,
3750
- tokens: [{
3751
- type: 'text',
3752
- raw: text,
3753
- text
3754
- }]
3755
- };
3756
- }
3757
- }
3758
- url(src) {
3759
- let cap;
3760
- if (cap = this.rules.inline.url.exec(src)) {
3761
- let text, href;
3762
- if (cap[2] === '@') {
3763
- text = cap[0];
3764
- href = 'mailto:' + text;
3765
- } else {
3766
- // do extended autolink path validation
3767
- let prevCapZero;
3768
- do {
3769
- prevCapZero = cap[0];
3770
- cap[0] = this.rules.inline._backpedal.exec(cap[0])?.[0] ?? '';
3771
- } while (prevCapZero !== cap[0]);
3772
- text = cap[0];
3773
- if (cap[1] === 'www.') {
3774
- href = 'http://' + cap[0];
3775
- } else {
3776
- href = cap[0];
3777
- }
3778
- }
3779
- return {
3780
- type: 'link',
3781
- raw: cap[0],
3782
- text,
3783
- href,
3784
- tokens: [{
3785
- type: 'text',
3786
- raw: text,
3787
- text
3788
- }]
3789
- };
3790
- }
3791
- }
3792
- inlineText(src) {
3793
- const cap = this.rules.inline.text.exec(src);
3794
- if (cap) {
3795
- const escaped = this.lexer.state.inRawBlock;
3796
- return {
3797
- type: 'text',
3798
- raw: cap[0],
3799
- text: cap[0],
3800
- escaped
3801
- };
3802
- }
3803
- }
3804
- }
3805
-
3806
- /**
3807
- * Block Lexer
3808
- */
3809
- class _Lexer {
3810
- tokens;
3811
- options;
3812
- state;
3813
- tokenizer;
3814
- inlineQueue;
3815
- constructor(options) {
3816
- // TokenList cannot be created in one go
3817
- this.tokens = [];
3818
- this.tokens.links = Object.create(null);
3819
- this.options = options || _defaults;
3820
- this.options.tokenizer = this.options.tokenizer || new _Tokenizer();
3821
- this.tokenizer = this.options.tokenizer;
3822
- this.tokenizer.options = this.options;
3823
- this.tokenizer.lexer = this;
3824
- this.inlineQueue = [];
3825
- this.state = {
3826
- inLink: false,
3827
- inRawBlock: false,
3828
- top: true
3829
- };
3830
- const rules = {
3831
- other,
3832
- block: block.normal,
3833
- inline: inline.normal
3834
- };
3835
- if (this.options.pedantic) {
3836
- rules.block = block.pedantic;
3837
- rules.inline = inline.pedantic;
3838
- } else if (this.options.gfm) {
3839
- rules.block = block.gfm;
3840
- if (this.options.breaks) {
3841
- rules.inline = inline.breaks;
3842
- } else {
3843
- rules.inline = inline.gfm;
3844
- }
3845
- }
3846
- this.tokenizer.rules = rules;
3847
- }
3848
- /**
3849
- * Expose Rules
3850
- */
3851
- static get rules() {
3852
- return {
3853
- block,
3854
- inline
3855
- };
3856
- }
3857
- /**
3858
- * Static Lex Method
3859
- */
3860
- static lex(src, options) {
3861
- const lexer = new _Lexer(options);
3862
- return lexer.lex(src);
3863
- }
3864
- /**
3865
- * Static Lex Inline Method
3866
- */
3867
- static lexInline(src, options) {
3868
- const lexer = new _Lexer(options);
3869
- return lexer.inlineTokens(src);
3870
- }
3871
- /**
3872
- * Preprocessing
3873
- */
3874
- lex(src) {
3875
- src = src.replace(other.carriageReturn, '\n');
3876
- this.blockTokens(src, this.tokens);
3877
- for (let i = 0; i < this.inlineQueue.length; i++) {
3878
- const next = this.inlineQueue[i];
3879
- this.inlineTokens(next.src, next.tokens);
3880
- }
3881
- this.inlineQueue = [];
3882
- return this.tokens;
3883
- }
3884
- blockTokens(src, tokens = [], lastParagraphClipped = false) {
3885
- if (this.options.pedantic) {
3886
- src = src.replace(other.tabCharGlobal, ' ').replace(other.spaceLine, '');
3887
- }
3888
- while (src) {
3889
- let token;
3890
- if (this.options.extensions?.block?.some(extTokenizer => {
3891
- if (token = extTokenizer.call({
3892
- lexer: this
3893
- }, src, tokens)) {
3894
- src = src.substring(token.raw.length);
3895
- tokens.push(token);
3896
- return true;
3897
- }
3898
- return false;
3899
- })) {
3900
- continue;
3901
- }
3902
- // newline
3903
- if (token = this.tokenizer.space(src)) {
3904
- src = src.substring(token.raw.length);
3905
- const lastToken = tokens.at(-1);
3906
- if (token.raw.length === 1 && lastToken !== undefined) {
3907
- // if there's a single \n as a spacer, it's terminating the last line,
3908
- // so move it there so that we don't get unnecessary paragraph tags
3909
- lastToken.raw += '\n';
3910
- } else {
3911
- tokens.push(token);
3912
- }
3913
- continue;
3914
- }
3915
- // code
3916
- if (token = this.tokenizer.code(src)) {
3917
- src = src.substring(token.raw.length);
3918
- const lastToken = tokens.at(-1);
3919
- // An indented code block cannot interrupt a paragraph.
3920
- if (lastToken?.type === 'paragraph' || lastToken?.type === 'text') {
3921
- lastToken.raw += '\n' + token.raw;
3922
- lastToken.text += '\n' + token.text;
3923
- this.inlineQueue.at(-1).src = lastToken.text;
3924
- } else {
3925
- tokens.push(token);
3926
- }
3927
- continue;
3928
- }
3929
- // fences
3930
- if (token = this.tokenizer.fences(src)) {
3931
- src = src.substring(token.raw.length);
3932
- tokens.push(token);
3933
- continue;
3934
- }
3935
- // heading
3936
- if (token = this.tokenizer.heading(src)) {
3937
- src = src.substring(token.raw.length);
3938
- tokens.push(token);
3939
- continue;
3940
- }
3941
- // hr
3942
- if (token = this.tokenizer.hr(src)) {
3943
- src = src.substring(token.raw.length);
3944
- tokens.push(token);
3945
- continue;
3946
- }
3947
- // blockquote
3948
- if (token = this.tokenizer.blockquote(src)) {
3949
- src = src.substring(token.raw.length);
3950
- tokens.push(token);
3951
- continue;
3952
- }
3953
- // list
3954
- if (token = this.tokenizer.list(src)) {
3955
- src = src.substring(token.raw.length);
3956
- tokens.push(token);
3957
- continue;
3958
- }
3959
- // html
3960
- if (token = this.tokenizer.html(src)) {
3961
- src = src.substring(token.raw.length);
3962
- tokens.push(token);
3963
- continue;
3964
- }
3965
- // def
3966
- if (token = this.tokenizer.def(src)) {
3967
- src = src.substring(token.raw.length);
3968
- const lastToken = tokens.at(-1);
3969
- if (lastToken?.type === 'paragraph' || lastToken?.type === 'text') {
3970
- lastToken.raw += '\n' + token.raw;
3971
- lastToken.text += '\n' + token.raw;
3972
- this.inlineQueue.at(-1).src = lastToken.text;
3973
- } else if (!this.tokens.links[token.tag]) {
3974
- this.tokens.links[token.tag] = {
3975
- href: token.href,
3976
- title: token.title
3977
- };
3978
- }
3979
- continue;
3980
- }
3981
- // table (gfm)
3982
- if (token = this.tokenizer.table(src)) {
3983
- src = src.substring(token.raw.length);
3984
- tokens.push(token);
3985
- continue;
3986
- }
3987
- // lheading
3988
- if (token = this.tokenizer.lheading(src)) {
3989
- src = src.substring(token.raw.length);
3990
- tokens.push(token);
3991
- continue;
3992
- }
3993
- // top-level paragraph
3994
- // prevent paragraph consuming extensions by clipping 'src' to extension start
3995
- let cutSrc = src;
3996
- if (this.options.extensions?.startBlock) {
3997
- let startIndex = Infinity;
3998
- const tempSrc = src.slice(1);
3999
- let tempStart;
4000
- this.options.extensions.startBlock.forEach(getStartIndex => {
4001
- tempStart = getStartIndex.call({
4002
- lexer: this
4003
- }, tempSrc);
4004
- if (typeof tempStart === 'number' && tempStart >= 0) {
4005
- startIndex = Math.min(startIndex, tempStart);
4006
- }
4007
- });
4008
- if (startIndex < Infinity && startIndex >= 0) {
4009
- cutSrc = src.substring(0, startIndex + 1);
4010
- }
4011
- }
4012
- if (this.state.top && (token = this.tokenizer.paragraph(cutSrc))) {
4013
- const lastToken = tokens.at(-1);
4014
- if (lastParagraphClipped && lastToken?.type === 'paragraph') {
4015
- lastToken.raw += '\n' + token.raw;
4016
- lastToken.text += '\n' + token.text;
4017
- this.inlineQueue.pop();
4018
- this.inlineQueue.at(-1).src = lastToken.text;
4019
- } else {
4020
- tokens.push(token);
4021
- }
4022
- lastParagraphClipped = cutSrc.length !== src.length;
4023
- src = src.substring(token.raw.length);
4024
- continue;
4025
- }
4026
- // text
4027
- if (token = this.tokenizer.text(src)) {
4028
- src = src.substring(token.raw.length);
4029
- const lastToken = tokens.at(-1);
4030
- if (lastToken?.type === 'text') {
4031
- lastToken.raw += '\n' + token.raw;
4032
- lastToken.text += '\n' + token.text;
4033
- this.inlineQueue.pop();
4034
- this.inlineQueue.at(-1).src = lastToken.text;
4035
- } else {
4036
- tokens.push(token);
4037
- }
4038
- continue;
4039
- }
4040
- if (src) {
4041
- const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);
4042
- if (this.options.silent) {
4043
- console.error(errMsg);
4044
- break;
4045
- } else {
4046
- throw new Error(errMsg);
4047
- }
4048
- }
4049
- }
4050
- this.state.top = true;
4051
- return tokens;
4052
- }
4053
- inline(src, tokens = []) {
4054
- this.inlineQueue.push({
4055
- src,
4056
- tokens
4057
- });
4058
- return tokens;
4059
- }
4060
- /**
4061
- * Lexing/Compiling
4062
- */
4063
- inlineTokens(src, tokens = []) {
4064
- // String with links masked to avoid interference with em and strong
4065
- let maskedSrc = src;
4066
- let match = null;
4067
- // Mask out reflinks
4068
- if (this.tokens.links) {
4069
- const links = Object.keys(this.tokens.links);
4070
- if (links.length > 0) {
4071
- while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) {
4072
- if (links.includes(match[0].slice(match[0].lastIndexOf('[') + 1, -1))) {
4073
- maskedSrc = maskedSrc.slice(0, match.index) + '[' + 'a'.repeat(match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex);
4074
- }
4075
- }
4076
- }
4077
- }
4078
- // Mask out other blocks
4079
- while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) {
4080
- maskedSrc = maskedSrc.slice(0, match.index) + '[' + 'a'.repeat(match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
4081
- }
4082
- // Mask out escaped characters
4083
- while ((match = this.tokenizer.rules.inline.anyPunctuation.exec(maskedSrc)) != null) {
4084
- maskedSrc = maskedSrc.slice(0, match.index) + '++' + maskedSrc.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);
4085
- }
4086
- let keepPrevChar = false;
4087
- let prevChar = '';
4088
- while (src) {
4089
- if (!keepPrevChar) {
4090
- prevChar = '';
4091
- }
4092
- keepPrevChar = false;
4093
- let token;
4094
- // extensions
4095
- if (this.options.extensions?.inline?.some(extTokenizer => {
4096
- if (token = extTokenizer.call({
4097
- lexer: this
4098
- }, src, tokens)) {
4099
- src = src.substring(token.raw.length);
4100
- tokens.push(token);
4101
- return true;
4102
- }
4103
- return false;
4104
- })) {
4105
- continue;
4106
- }
4107
- // escape
4108
- if (token = this.tokenizer.escape(src)) {
4109
- src = src.substring(token.raw.length);
4110
- tokens.push(token);
4111
- continue;
4112
- }
4113
- // tag
4114
- if (token = this.tokenizer.tag(src)) {
4115
- src = src.substring(token.raw.length);
4116
- tokens.push(token);
4117
- continue;
4118
- }
4119
- // link
4120
- if (token = this.tokenizer.link(src)) {
4121
- src = src.substring(token.raw.length);
4122
- tokens.push(token);
4123
- continue;
4124
- }
4125
- // reflink, nolink
4126
- if (token = this.tokenizer.reflink(src, this.tokens.links)) {
4127
- src = src.substring(token.raw.length);
4128
- const lastToken = tokens.at(-1);
4129
- if (token.type === 'text' && lastToken?.type === 'text') {
4130
- lastToken.raw += token.raw;
4131
- lastToken.text += token.text;
4132
- } else {
4133
- tokens.push(token);
4134
- }
4135
- continue;
4136
- }
4137
- // em & strong
4138
- if (token = this.tokenizer.emStrong(src, maskedSrc, prevChar)) {
4139
- src = src.substring(token.raw.length);
4140
- tokens.push(token);
4141
- continue;
4142
- }
4143
- // code
4144
- if (token = this.tokenizer.codespan(src)) {
4145
- src = src.substring(token.raw.length);
4146
- tokens.push(token);
4147
- continue;
4148
- }
4149
- // br
4150
- if (token = this.tokenizer.br(src)) {
4151
- src = src.substring(token.raw.length);
4152
- tokens.push(token);
4153
- continue;
4154
- }
4155
- // del (gfm)
4156
- if (token = this.tokenizer.del(src)) {
4157
- src = src.substring(token.raw.length);
4158
- tokens.push(token);
4159
- continue;
4160
- }
4161
- // autolink
4162
- if (token = this.tokenizer.autolink(src)) {
4163
- src = src.substring(token.raw.length);
4164
- tokens.push(token);
4165
- continue;
4166
- }
4167
- // url (gfm)
4168
- if (!this.state.inLink && (token = this.tokenizer.url(src))) {
4169
- src = src.substring(token.raw.length);
4170
- tokens.push(token);
4171
- continue;
4172
- }
4173
- // text
4174
- // prevent inlineText consuming extensions by clipping 'src' to extension start
4175
- let cutSrc = src;
4176
- if (this.options.extensions?.startInline) {
4177
- let startIndex = Infinity;
4178
- const tempSrc = src.slice(1);
4179
- let tempStart;
4180
- this.options.extensions.startInline.forEach(getStartIndex => {
4181
- tempStart = getStartIndex.call({
4182
- lexer: this
4183
- }, tempSrc);
4184
- if (typeof tempStart === 'number' && tempStart >= 0) {
4185
- startIndex = Math.min(startIndex, tempStart);
4186
- }
4187
- });
4188
- if (startIndex < Infinity && startIndex >= 0) {
4189
- cutSrc = src.substring(0, startIndex + 1);
4190
- }
4191
- }
4192
- if (token = this.tokenizer.inlineText(cutSrc)) {
4193
- src = src.substring(token.raw.length);
4194
- if (token.raw.slice(-1) !== '_') {
4195
- // Track prevChar before string of ____ started
4196
- prevChar = token.raw.slice(-1);
4197
- }
4198
- keepPrevChar = true;
4199
- const lastToken = tokens.at(-1);
4200
- if (lastToken?.type === 'text') {
4201
- lastToken.raw += token.raw;
4202
- lastToken.text += token.text;
4203
- } else {
4204
- tokens.push(token);
4205
- }
4206
- continue;
4207
- }
4208
- if (src) {
4209
- const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);
4210
- if (this.options.silent) {
4211
- console.error(errMsg);
4212
- break;
4213
- } else {
4214
- throw new Error(errMsg);
4215
- }
4216
- }
4217
- }
4218
- return tokens;
4219
- }
4220
- }
4221
-
4222
- /**
4223
- * Renderer
4224
- */
4225
- class _Renderer {
4226
- options;
4227
- parser; // set by the parser
4228
- constructor(options) {
4229
- this.options = options || _defaults;
4230
- }
4231
- space(token) {
4232
- return '';
4233
- }
4234
- code({
4235
- text,
4236
- lang,
4237
- escaped
4238
- }) {
4239
- const langString = (lang || '').match(other.notSpaceStart)?.[0];
4240
- const code = text.replace(other.endingNewline, '') + '\n';
4241
- if (!langString) {
4242
- return '<pre><code>' + (escaped ? code : escape(code, true)) + '</code></pre>\n';
4243
- }
4244
- return '<pre><code class="language-' + escape(langString) + '">' + (escaped ? code : escape(code, true)) + '</code></pre>\n';
4245
- }
4246
- blockquote({
4247
- tokens
4248
- }) {
4249
- const body = this.parser.parse(tokens);
4250
- return `<blockquote>\n${body}</blockquote>\n`;
4251
- }
4252
- html({
4253
- text
4254
- }) {
4255
- return text;
4256
- }
4257
- heading({
4258
- tokens,
4259
- depth
4260
- }) {
4261
- return `<h${depth}>${this.parser.parseInline(tokens)}</h${depth}>\n`;
4262
- }
4263
- hr(token) {
4264
- return '<hr>\n';
4265
- }
4266
- list(token) {
4267
- const ordered = token.ordered;
4268
- const start = token.start;
4269
- let body = '';
4270
- for (let j = 0; j < token.items.length; j++) {
4271
- const item = token.items[j];
4272
- body += this.listitem(item);
4273
- }
4274
- const type = ordered ? 'ol' : 'ul';
4275
- const startAttr = ordered && start !== 1 ? ' start="' + start + '"' : '';
4276
- return '<' + type + startAttr + '>\n' + body + '</' + type + '>\n';
4277
- }
4278
- listitem(item) {
4279
- let itemBody = '';
4280
- if (item.task) {
4281
- const checkbox = this.checkbox({
4282
- checked: !!item.checked
4283
- });
4284
- if (item.loose) {
4285
- if (item.tokens[0]?.type === 'paragraph') {
4286
- item.tokens[0].text = checkbox + ' ' + item.tokens[0].text;
4287
- if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') {
4288
- item.tokens[0].tokens[0].text = checkbox + ' ' + escape(item.tokens[0].tokens[0].text);
4289
- item.tokens[0].tokens[0].escaped = true;
4290
- }
4291
- } else {
4292
- item.tokens.unshift({
4293
- type: 'text',
4294
- raw: checkbox + ' ',
4295
- text: checkbox + ' ',
4296
- escaped: true
4297
- });
4298
- }
4299
- } else {
4300
- itemBody += checkbox + ' ';
4301
- }
4302
- }
4303
- itemBody += this.parser.parse(item.tokens, !!item.loose);
4304
- return `<li>${itemBody}</li>\n`;
4305
- }
4306
- checkbox({
4307
- checked
4308
- }) {
4309
- return '<input ' + (checked ? 'checked="" ' : '') + 'disabled="" type="checkbox">';
4310
- }
4311
- paragraph({
4312
- tokens
4313
- }) {
4314
- return `<p>${this.parser.parseInline(tokens)}</p>\n`;
4315
- }
4316
- table(token) {
4317
- let header = '';
4318
- // header
4319
- let cell = '';
4320
- for (let j = 0; j < token.header.length; j++) {
4321
- cell += this.tablecell(token.header[j]);
4322
- }
4323
- header += this.tablerow({
4324
- text: cell
4325
- });
4326
- let body = '';
4327
- for (let j = 0; j < token.rows.length; j++) {
4328
- const row = token.rows[j];
4329
- cell = '';
4330
- for (let k = 0; k < row.length; k++) {
4331
- cell += this.tablecell(row[k]);
4332
- }
4333
- body += this.tablerow({
4334
- text: cell
4335
- });
4336
- }
4337
- if (body) body = `<tbody>${body}</tbody>`;
4338
- return '<table>\n' + '<thead>\n' + header + '</thead>\n' + body + '</table>\n';
4339
- }
4340
- tablerow({
4341
- text
4342
- }) {
4343
- return `<tr>\n${text}</tr>\n`;
4344
- }
4345
- tablecell(token) {
4346
- const content = this.parser.parseInline(token.tokens);
4347
- const type = token.header ? 'th' : 'td';
4348
- const tag = token.align ? `<${type} align="${token.align}">` : `<${type}>`;
4349
- return tag + content + `</${type}>\n`;
4350
- }
4351
- /**
4352
- * span level renderer
4353
- */
4354
- strong({
4355
- tokens
4356
- }) {
4357
- return `<strong>${this.parser.parseInline(tokens)}</strong>`;
4358
- }
4359
- em({
4360
- tokens
4361
- }) {
4362
- return `<em>${this.parser.parseInline(tokens)}</em>`;
4363
- }
4364
- codespan({
4365
- text
4366
- }) {
4367
- return `<code>${escape(text, true)}</code>`;
4368
- }
4369
- br(token) {
4370
- return '<br>';
4371
- }
4372
- del({
4373
- tokens
4374
- }) {
4375
- return `<del>${this.parser.parseInline(tokens)}</del>`;
4376
- }
4377
- link({
4378
- href,
4379
- title,
4380
- tokens
4381
- }) {
4382
- const text = this.parser.parseInline(tokens);
4383
- const cleanHref = cleanUrl(href);
4384
- if (cleanHref === null) {
4385
- return text;
4386
- }
4387
- href = cleanHref;
4388
- let out = '<a href="' + href + '"';
4389
- if (title) {
4390
- out += ' title="' + escape(title) + '"';
4391
- }
4392
- out += '>' + text + '</a>';
4393
- return out;
4394
- }
4395
- image({
4396
- href,
4397
- title,
4398
- text
4399
- }) {
4400
- const cleanHref = cleanUrl(href);
4401
- if (cleanHref === null) {
4402
- return escape(text);
4403
- }
4404
- href = cleanHref;
4405
- let out = `<img src="${href}" alt="${text}"`;
4406
- if (title) {
4407
- out += ` title="${escape(title)}"`;
4408
- }
4409
- out += '>';
4410
- return out;
4411
- }
4412
- text(token) {
4413
- return 'tokens' in token && token.tokens ? this.parser.parseInline(token.tokens) : 'escaped' in token && token.escaped ? token.text : escape(token.text);
4414
- }
4415
- }
4416
-
4417
- /**
4418
- * TextRenderer
4419
- * returns only the textual part of the token
4420
- */
4421
- class _TextRenderer {
4422
- // no need for block level renderers
4423
- strong({
4424
- text
4425
- }) {
4426
- return text;
4427
- }
4428
- em({
4429
- text
4430
- }) {
4431
- return text;
4432
- }
4433
- codespan({
4434
- text
4435
- }) {
4436
- return text;
4437
- }
4438
- del({
4439
- text
4440
- }) {
4441
- return text;
4442
- }
4443
- html({
4444
- text
4445
- }) {
4446
- return text;
4447
- }
4448
- text({
4449
- text
4450
- }) {
4451
- return text;
4452
- }
4453
- link({
4454
- text
4455
- }) {
4456
- return '' + text;
4457
- }
4458
- image({
4459
- text
4460
- }) {
4461
- return '' + text;
4462
- }
4463
- br() {
4464
- return '';
4465
- }
4466
- }
4467
-
4468
- /**
4469
- * Parsing & Compiling
4470
- */
4471
- class _Parser {
4472
- options;
4473
- renderer;
4474
- textRenderer;
4475
- constructor(options) {
4476
- this.options = options || _defaults;
4477
- this.options.renderer = this.options.renderer || new _Renderer();
4478
- this.renderer = this.options.renderer;
4479
- this.renderer.options = this.options;
4480
- this.renderer.parser = this;
4481
- this.textRenderer = new _TextRenderer();
4482
- }
4483
- /**
4484
- * Static Parse Method
4485
- */
4486
- static parse(tokens, options) {
4487
- const parser = new _Parser(options);
4488
- return parser.parse(tokens);
4489
- }
4490
- /**
4491
- * Static Parse Inline Method
4492
- */
4493
- static parseInline(tokens, options) {
4494
- const parser = new _Parser(options);
4495
- return parser.parseInline(tokens);
4496
- }
4497
- /**
4498
- * Parse Loop
4499
- */
4500
- parse(tokens, top = true) {
4501
- let out = '';
4502
- for (let i = 0; i < tokens.length; i++) {
4503
- const anyToken = tokens[i];
4504
- // Run any renderer extensions
4505
- if (this.options.extensions?.renderers?.[anyToken.type]) {
4506
- const genericToken = anyToken;
4507
- const ret = this.options.extensions.renderers[genericToken.type].call({
4508
- parser: this
4509
- }, genericToken);
4510
- if (ret !== false || !['space', 'hr', 'heading', 'code', 'table', 'blockquote', 'list', 'html', 'paragraph', 'text'].includes(genericToken.type)) {
4511
- out += ret || '';
4512
- continue;
4513
- }
4514
- }
4515
- const token = anyToken;
4516
- switch (token.type) {
4517
- case 'space':
4518
- {
4519
- out += this.renderer.space(token);
4520
- continue;
4521
- }
4522
- case 'hr':
4523
- {
4524
- out += this.renderer.hr(token);
4525
- continue;
4526
- }
4527
- case 'heading':
4528
- {
4529
- out += this.renderer.heading(token);
4530
- continue;
4531
- }
4532
- case 'code':
4533
- {
4534
- out += this.renderer.code(token);
4535
- continue;
4536
- }
4537
- case 'table':
4538
- {
4539
- out += this.renderer.table(token);
4540
- continue;
4541
- }
4542
- case 'blockquote':
4543
- {
4544
- out += this.renderer.blockquote(token);
4545
- continue;
4546
- }
4547
- case 'list':
4548
- {
4549
- out += this.renderer.list(token);
4550
- continue;
4551
- }
4552
- case 'html':
4553
- {
4554
- out += this.renderer.html(token);
4555
- continue;
4556
- }
4557
- case 'paragraph':
4558
- {
4559
- out += this.renderer.paragraph(token);
4560
- continue;
4561
- }
4562
- case 'text':
4563
- {
4564
- let textToken = token;
4565
- let body = this.renderer.text(textToken);
4566
- while (i + 1 < tokens.length && tokens[i + 1].type === 'text') {
4567
- textToken = tokens[++i];
4568
- body += '\n' + this.renderer.text(textToken);
4569
- }
4570
- if (top) {
4571
- out += this.renderer.paragraph({
4572
- type: 'paragraph',
4573
- raw: body,
4574
- text: body,
4575
- tokens: [{
4576
- type: 'text',
4577
- raw: body,
4578
- text: body,
4579
- escaped: true
4580
- }]
4581
- });
4582
- } else {
4583
- out += body;
4584
- }
4585
- continue;
4586
- }
4587
- default:
4588
- {
4589
- const errMsg = 'Token with "' + token.type + '" type was not found.';
4590
- if (this.options.silent) {
4591
- console.error(errMsg);
4592
- return '';
4593
- } else {
4594
- throw new Error(errMsg);
4595
- }
4596
- }
4597
- }
4598
- }
4599
- return out;
4600
- }
4601
- /**
4602
- * Parse Inline Tokens
4603
- */
4604
- parseInline(tokens, renderer = this.renderer) {
4605
- let out = '';
4606
- for (let i = 0; i < tokens.length; i++) {
4607
- const anyToken = tokens[i];
4608
- // Run any renderer extensions
4609
- if (this.options.extensions?.renderers?.[anyToken.type]) {
4610
- const ret = this.options.extensions.renderers[anyToken.type].call({
4611
- parser: this
4612
- }, anyToken);
4613
- if (ret !== false || !['escape', 'html', 'link', 'image', 'strong', 'em', 'codespan', 'br', 'del', 'text'].includes(anyToken.type)) {
4614
- out += ret || '';
4615
- continue;
4616
- }
4617
- }
4618
- const token = anyToken;
4619
- switch (token.type) {
4620
- case 'escape':
4621
- {
4622
- out += renderer.text(token);
4623
- break;
4624
- }
4625
- case 'html':
4626
- {
4627
- out += renderer.html(token);
4628
- break;
4629
- }
4630
- case 'link':
4631
- {
4632
- out += renderer.link(token);
4633
- break;
4634
- }
4635
- case 'image':
4636
- {
4637
- out += renderer.image(token);
4638
- break;
4639
- }
4640
- case 'strong':
4641
- {
4642
- out += renderer.strong(token);
4643
- break;
4644
- }
4645
- case 'em':
4646
- {
4647
- out += renderer.em(token);
4648
- break;
4649
- }
4650
- case 'codespan':
4651
- {
4652
- out += renderer.codespan(token);
4653
- break;
4654
- }
4655
- case 'br':
4656
- {
4657
- out += renderer.br(token);
4658
- break;
4659
- }
4660
- case 'del':
4661
- {
4662
- out += renderer.del(token);
4663
- break;
4664
- }
4665
- case 'text':
4666
- {
4667
- out += renderer.text(token);
4668
- break;
4669
- }
4670
- default:
4671
- {
4672
- const errMsg = 'Token with "' + token.type + '" type was not found.';
4673
- if (this.options.silent) {
4674
- console.error(errMsg);
4675
- return '';
4676
- } else {
4677
- throw new Error(errMsg);
4678
- }
4679
- }
4680
- }
4681
- }
4682
- return out;
4683
- }
4684
- }
4685
- class _Hooks {
4686
- options;
4687
- block;
4688
- constructor(options) {
4689
- this.options = options || _defaults;
4690
- }
4691
- static passThroughHooks = new Set(['preprocess', 'postprocess', 'processAllTokens']);
4692
- /**
4693
- * Process markdown before marked
4694
- */
4695
- preprocess(markdown) {
4696
- return markdown;
4697
- }
4698
- /**
4699
- * Process HTML after marked is finished
4700
- */
4701
- postprocess(html) {
4702
- return html;
4703
- }
4704
- /**
4705
- * Process all tokens before walk tokens
4706
- */
4707
- processAllTokens(tokens) {
4708
- return tokens;
4709
- }
4710
- /**
4711
- * Provide function to tokenize markdown
4712
- */
4713
- provideLexer() {
4714
- return this.block ? _Lexer.lex : _Lexer.lexInline;
4715
- }
4716
- /**
4717
- * Provide function to parse tokens
4718
- */
4719
- provideParser() {
4720
- return this.block ? _Parser.parse : _Parser.parseInline;
4721
- }
4722
- }
4723
- class Marked {
4724
- defaults = _getDefaults();
4725
- options = this.setOptions;
4726
- parse = this.parseMarkdown(true);
4727
- parseInline = this.parseMarkdown(false);
4728
- Parser = _Parser;
4729
- Renderer = _Renderer;
4730
- TextRenderer = _TextRenderer;
4731
- Lexer = _Lexer;
4732
- Tokenizer = _Tokenizer;
4733
- Hooks = _Hooks;
4734
- constructor(...args) {
4735
- this.use(...args);
4736
- }
4737
- /**
4738
- * Run callback for every token
4739
- */
4740
- walkTokens(tokens, callback) {
4741
- let values = [];
4742
- for (const token of tokens) {
4743
- values = values.concat(callback.call(this, token));
4744
- switch (token.type) {
4745
- case 'table':
4746
- {
4747
- const tableToken = token;
4748
- for (const cell of tableToken.header) {
4749
- values = values.concat(this.walkTokens(cell.tokens, callback));
4750
- }
4751
- for (const row of tableToken.rows) {
4752
- for (const cell of row) {
4753
- values = values.concat(this.walkTokens(cell.tokens, callback));
4754
- }
4755
- }
4756
- break;
4757
- }
4758
- case 'list':
4759
- {
4760
- const listToken = token;
4761
- values = values.concat(this.walkTokens(listToken.items, callback));
4762
- break;
4763
- }
4764
- default:
4765
- {
4766
- const genericToken = token;
4767
- if (this.defaults.extensions?.childTokens?.[genericToken.type]) {
4768
- this.defaults.extensions.childTokens[genericToken.type].forEach(childTokens => {
4769
- const tokens = genericToken[childTokens].flat(Infinity);
4770
- values = values.concat(this.walkTokens(tokens, callback));
4771
- });
4772
- } else if (genericToken.tokens) {
4773
- values = values.concat(this.walkTokens(genericToken.tokens, callback));
4774
- }
4775
- }
4776
- }
4777
- }
4778
- return values;
4779
- }
4780
- use(...args) {
4781
- const extensions = this.defaults.extensions || {
4782
- renderers: {},
4783
- childTokens: {}
4784
- };
4785
- args.forEach(pack => {
4786
- // copy options to new object
4787
- const opts = {
4788
- ...pack
4789
- };
4790
- // set async to true if it was set to true before
4791
- opts.async = this.defaults.async || opts.async || false;
4792
- // ==-- Parse "addon" extensions --== //
4793
- if (pack.extensions) {
4794
- pack.extensions.forEach(ext => {
4795
- if (!ext.name) {
4796
- throw new Error('extension name required');
4797
- }
4798
- if ('renderer' in ext) {
4799
- // Renderer extensions
4800
- const prevRenderer = extensions.renderers[ext.name];
4801
- if (prevRenderer) {
4802
- // Replace extension with func to run new extension but fall back if false
4803
- extensions.renderers[ext.name] = function (...args) {
4804
- let ret = ext.renderer.apply(this, args);
4805
- if (ret === false) {
4806
- ret = prevRenderer.apply(this, args);
4807
- }
4808
- return ret;
4809
- };
4810
- } else {
4811
- extensions.renderers[ext.name] = ext.renderer;
4812
- }
4813
- }
4814
- if ('tokenizer' in ext) {
4815
- // Tokenizer Extensions
4816
- if (!ext.level || ext.level !== 'block' && ext.level !== 'inline') {
4817
- throw new Error("extension level must be 'block' or 'inline'");
4818
- }
4819
- const extLevel = extensions[ext.level];
4820
- if (extLevel) {
4821
- extLevel.unshift(ext.tokenizer);
4822
- } else {
4823
- extensions[ext.level] = [ext.tokenizer];
4824
- }
4825
- if (ext.start) {
4826
- // Function to check for start of token
4827
- if (ext.level === 'block') {
4828
- if (extensions.startBlock) {
4829
- extensions.startBlock.push(ext.start);
4830
- } else {
4831
- extensions.startBlock = [ext.start];
4832
- }
4833
- } else if (ext.level === 'inline') {
4834
- if (extensions.startInline) {
4835
- extensions.startInline.push(ext.start);
4836
- } else {
4837
- extensions.startInline = [ext.start];
4838
- }
4839
- }
4840
- }
4841
- }
4842
- if ('childTokens' in ext && ext.childTokens) {
4843
- // Child tokens to be visited by walkTokens
4844
- extensions.childTokens[ext.name] = ext.childTokens;
4845
- }
4846
- });
4847
- opts.extensions = extensions;
4848
- }
4849
- // ==-- Parse "overwrite" extensions --== //
4850
- if (pack.renderer) {
4851
- const renderer = this.defaults.renderer || new _Renderer(this.defaults);
4852
- for (const prop in pack.renderer) {
4853
- if (!(prop in renderer)) {
4854
- throw new Error(`renderer '${prop}' does not exist`);
4855
- }
4856
- if (['options', 'parser'].includes(prop)) {
4857
- // ignore options property
4858
- continue;
4859
- }
4860
- const rendererProp = prop;
4861
- const rendererFunc = pack.renderer[rendererProp];
4862
- const prevRenderer = renderer[rendererProp];
4863
- // Replace renderer with func to run extension, but fall back if false
4864
- renderer[rendererProp] = (...args) => {
4865
- let ret = rendererFunc.apply(renderer, args);
4866
- if (ret === false) {
4867
- ret = prevRenderer.apply(renderer, args);
4868
- }
4869
- return ret || '';
4870
- };
4871
- }
4872
- opts.renderer = renderer;
4873
- }
4874
- if (pack.tokenizer) {
4875
- const tokenizer = this.defaults.tokenizer || new _Tokenizer(this.defaults);
4876
- for (const prop in pack.tokenizer) {
4877
- if (!(prop in tokenizer)) {
4878
- throw new Error(`tokenizer '${prop}' does not exist`);
4879
- }
4880
- if (['options', 'rules', 'lexer'].includes(prop)) {
4881
- // ignore options, rules, and lexer properties
4882
- continue;
4883
- }
4884
- const tokenizerProp = prop;
4885
- const tokenizerFunc = pack.tokenizer[tokenizerProp];
4886
- const prevTokenizer = tokenizer[tokenizerProp];
4887
- // Replace tokenizer with func to run extension, but fall back if false
4888
- // @ts-expect-error cannot type tokenizer function dynamically
4889
- tokenizer[tokenizerProp] = (...args) => {
4890
- let ret = tokenizerFunc.apply(tokenizer, args);
4891
- if (ret === false) {
4892
- ret = prevTokenizer.apply(tokenizer, args);
4893
- }
4894
- return ret;
4895
- };
4896
- }
4897
- opts.tokenizer = tokenizer;
4898
- }
4899
- // ==-- Parse Hooks extensions --== //
4900
- if (pack.hooks) {
4901
- const hooks = this.defaults.hooks || new _Hooks();
4902
- for (const prop in pack.hooks) {
4903
- if (!(prop in hooks)) {
4904
- throw new Error(`hook '${prop}' does not exist`);
4905
- }
4906
- if (['options', 'block'].includes(prop)) {
4907
- // ignore options and block properties
4908
- continue;
4909
- }
4910
- const hooksProp = prop;
4911
- const hooksFunc = pack.hooks[hooksProp];
4912
- const prevHook = hooks[hooksProp];
4913
- if (_Hooks.passThroughHooks.has(prop)) {
4914
- // @ts-expect-error cannot type hook function dynamically
4915
- hooks[hooksProp] = arg => {
4916
- if (this.defaults.async) {
4917
- return Promise.resolve(hooksFunc.call(hooks, arg)).then(ret => {
4918
- return prevHook.call(hooks, ret);
4919
- });
4920
- }
4921
- const ret = hooksFunc.call(hooks, arg);
4922
- return prevHook.call(hooks, ret);
4923
- };
4924
- } else {
4925
- // @ts-expect-error cannot type hook function dynamically
4926
- hooks[hooksProp] = (...args) => {
4927
- let ret = hooksFunc.apply(hooks, args);
4928
- if (ret === false) {
4929
- ret = prevHook.apply(hooks, args);
4930
- }
4931
- return ret;
4932
- };
4933
- }
4934
- }
4935
- opts.hooks = hooks;
4936
- }
4937
- // ==-- Parse WalkTokens extensions --== //
4938
- if (pack.walkTokens) {
4939
- const walkTokens = this.defaults.walkTokens;
4940
- const packWalktokens = pack.walkTokens;
4941
- opts.walkTokens = function (token) {
4942
- let values = [];
4943
- values.push(packWalktokens.call(this, token));
4944
- if (walkTokens) {
4945
- values = values.concat(walkTokens.call(this, token));
4946
- }
4947
- return values;
4948
- };
4949
- }
4950
- this.defaults = {
4951
- ...this.defaults,
4952
- ...opts
4953
- };
4954
- });
4955
- return this;
4956
- }
4957
- setOptions(opt) {
4958
- this.defaults = {
4959
- ...this.defaults,
4960
- ...opt
4961
- };
4962
- return this;
4963
- }
4964
- lexer(src, options) {
4965
- return _Lexer.lex(src, options ?? this.defaults);
4966
- }
4967
- parser(tokens, options) {
4968
- return _Parser.parse(tokens, options ?? this.defaults);
4969
- }
4970
- parseMarkdown(blockType) {
4971
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
4972
- const parse = (src, options) => {
4973
- const origOpt = {
4974
- ...options
4975
- };
4976
- const opt = {
4977
- ...this.defaults,
4978
- ...origOpt
4979
- };
4980
- const throwError = this.onError(!!opt.silent, !!opt.async);
4981
- // throw error if an extension set async to true but parse was called with async: false
4982
- if (this.defaults.async === true && origOpt.async === false) {
4983
- return throwError(new Error('marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise.'));
4984
- }
4985
- // throw error in case of non string input
4986
- if (typeof src === 'undefined' || src === null) {
4987
- return throwError(new Error('marked(): input parameter is undefined or null'));
4988
- }
4989
- if (typeof src !== 'string') {
4990
- return throwError(new Error('marked(): input parameter is of type ' + Object.prototype.toString.call(src) + ', string expected'));
4991
- }
4992
- if (opt.hooks) {
4993
- opt.hooks.options = opt;
4994
- opt.hooks.block = blockType;
4995
- }
4996
- const lexer = opt.hooks ? opt.hooks.provideLexer() : blockType ? _Lexer.lex : _Lexer.lexInline;
4997
- const parser = opt.hooks ? opt.hooks.provideParser() : blockType ? _Parser.parse : _Parser.parseInline;
4998
- if (opt.async) {
4999
- return Promise.resolve(opt.hooks ? opt.hooks.preprocess(src) : src).then(src => lexer(src, opt)).then(tokens => opt.hooks ? opt.hooks.processAllTokens(tokens) : tokens).then(tokens => opt.walkTokens ? Promise.all(this.walkTokens(tokens, opt.walkTokens)).then(() => tokens) : tokens).then(tokens => parser(tokens, opt)).then(html => opt.hooks ? opt.hooks.postprocess(html) : html).catch(throwError);
5000
- }
5001
- try {
5002
- if (opt.hooks) {
5003
- src = opt.hooks.preprocess(src);
5004
- }
5005
- let tokens = lexer(src, opt);
5006
- if (opt.hooks) {
5007
- tokens = opt.hooks.processAllTokens(tokens);
5008
- }
5009
- if (opt.walkTokens) {
5010
- this.walkTokens(tokens, opt.walkTokens);
5011
- }
5012
- let html = parser(tokens, opt);
5013
- if (opt.hooks) {
5014
- html = opt.hooks.postprocess(html);
5015
- }
5016
- return html;
5017
- } catch (e) {
5018
- return throwError(e);
5019
- }
5020
- };
5021
- return parse;
5022
- }
5023
- onError(silent, async) {
5024
- return e => {
5025
- e.message += '\nPlease report this to https://github.com/markedjs/marked.';
5026
- if (silent) {
5027
- const msg = '<p>An error occurred:</p><pre>' + escape(e.message + '', true) + '</pre>';
5028
- if (async) {
5029
- return Promise.resolve(msg);
5030
- }
5031
- return msg;
5032
- }
5033
- if (async) {
5034
- return Promise.reject(e);
5035
- }
5036
- throw e;
5037
- };
5038
- }
5039
- }
5040
- const markedInstance = new Marked();
5041
- function marked(src, opt) {
5042
- return markedInstance.parse(src, opt);
5043
- }
5044
- /**
5045
- * Sets the default options.
5046
- *
5047
- * @param options Hash of options
5048
- */
5049
- marked.options = marked.setOptions = function (options) {
5050
- markedInstance.setOptions(options);
5051
- marked.defaults = markedInstance.defaults;
5052
- changeDefaults(marked.defaults);
5053
- return marked;
5054
- };
5055
- /**
5056
- * Gets the original marked default options.
5057
- */
5058
- marked.getDefaults = _getDefaults;
5059
- marked.defaults = _defaults;
5060
- /**
5061
- * Use Extension
5062
- */
5063
- marked.use = function (...args) {
5064
- markedInstance.use(...args);
5065
- marked.defaults = markedInstance.defaults;
5066
- changeDefaults(marked.defaults);
5067
- return marked;
5068
- };
5069
- /**
5070
- * Run callback for every token
5071
- */
5072
- marked.walkTokens = function (tokens, callback) {
5073
- return markedInstance.walkTokens(tokens, callback);
5074
- };
5075
- /**
5076
- * Compiles markdown to HTML without enclosing `p` tag.
5077
- *
5078
- * @param src String of markdown source to be compiled
5079
- * @param options Hash of options
5080
- * @return String of compiled HTML
5081
- */
5082
- marked.parseInline = markedInstance.parseInline;
5083
- /**
5084
- * Expose
5085
- */
5086
- marked.Parser = _Parser;
5087
- marked.parser = _Parser.parse;
5088
- marked.Renderer = _Renderer;
5089
- marked.TextRenderer = _TextRenderer;
5090
- marked.Lexer = _Lexer;
5091
- marked.lexer = _Lexer.lex;
5092
- marked.Tokenizer = _Tokenizer;
5093
- marked.Hooks = _Hooks;
5094
- marked.parse = marked;
5095
-
5096
2129
  const renderMarkdown = async (markdown, options = {}) => {
5097
- const html = await marked(markdown, {});
2130
+ const html = await invoke('Markdown.renderMarkdown', markdown, options);
5098
2131
  return html;
5099
2132
  };
5100
2133
 
@@ -5444,11 +2477,7 @@ const commandMap = {
5444
2477
  'ExtensionDetail.resize': resize,
5445
2478
  'ExtensionDetail.saveState': saveState,
5446
2479
  'ExtensionDetail.selectTab': wrapCommand(selectTab),
5447
- 'ExtensionDetail.terminate': terminate,
5448
- // deprecated
5449
- 'ExtensionDetail.getVirtualDom': wrapCommand(getExtensionDetailVirtualDom),
5450
- 'HandleIconError.handleIconError': handleIconError,
5451
- 'RenderMarkdown.renderMarkdown': renderMarkdown
2480
+ 'ExtensionDetail.terminate': terminate
5452
2481
  };
5453
2482
 
5454
2483
  const listen = async () => {