@lvce-editor/extension-detail-view 3.14.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,71 +1564,102 @@ 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];
2067
1599
  };
2068
1600
 
2069
- const heading$1 = {
2070
- type: H2$1,
1601
+ const toWebView = rawWebView => {
1602
+ const {
1603
+ id,
1604
+ selector,
1605
+ contentSecurityPolicy,
1606
+ elements
1607
+ } = rawWebView;
1608
+ return {
1609
+ id,
1610
+ selectorString: JSON.stringify(selector),
1611
+ contentSecurityPolicyString: JSON.stringify(contentSecurityPolicy),
1612
+ elementsString: JSON.stringify(elements, null, 2)
1613
+ };
1614
+ };
1615
+
1616
+ const getWebViews = extension => {
1617
+ const rawWebViews = extension.webViews || [];
1618
+ return rawWebViews.map(toWebView);
1619
+ };
1620
+
1621
+ const heading = {
1622
+ type: H2,
2071
1623
  className: DefinitionListItemHeading,
2072
1624
  childCount: 1
2073
1625
  };
2074
1626
  const pre = {
2075
- type: Pre$1,
1627
+ type: Pre,
2076
1628
  className: DefinitionListItemValue,
2077
1629
  childCount: 1
2078
1630
  };
2079
1631
  const item = {
2080
- type: Div$1,
1632
+ type: Div,
2081
1633
  className: DefinitionListItem,
2082
1634
  childCount: 2
2083
1635
  };
2084
-
2085
- // TODO move json stringify to view model
2086
1636
  const getWebViewVirtualDom = webView => {
2087
1637
  const {
2088
1638
  id: id$1,
2089
- selector: selector$1,
2090
- contentSecurityPolicy: contentSecurityPolicy$1,
2091
- elements: elements$1
1639
+ selectorString,
1640
+ contentSecurityPolicyString,
1641
+ elementsString
2092
1642
  } = webView;
2093
1643
  const textId = id();
2094
1644
  const textSelector = selector();
2095
1645
  const textContentSecurityPolicy = contentSecurityPolicy();
2096
1646
  const textElements = elements();
2097
1647
  return [{
2098
- type: Div$1,
1648
+ type: Div,
2099
1649
  className: FeatureWebView,
2100
1650
  childCount: 5
2101
- }, item, heading$1, text(textId), pre, text(id$1), item, heading$1, text(textSelector), pre, text(JSON.stringify(selector$1)), item, heading$1, text(textContentSecurityPolicy), pre, text(JSON.stringify(contentSecurityPolicy$1)), item, heading$1, text(textElements), pre, text(JSON.stringify(elements$1, null, 2))];
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)];
2102
1652
  };
2103
1653
 
2104
1654
  const getFeatureWebViewsVirtualDom = extension => {
2105
- const webViews$1 = extension.webViews || [];
1655
+ const webViews$1 = getWebViews(extension);
2106
1656
  const heading = webViews();
2107
1657
  return [{
2108
- type: Div$1,
1658
+ type: Div,
2109
1659
  className: FeatureContent,
2110
1660
  childCount: 2
2111
1661
  }, ...getFeatureContentHeadingVirtualDom(heading), {
2112
- type: Div$1,
1662
+ type: Div,
2113
1663
  childCount: webViews$1.length
2114
1664
  }, ...webViews$1.flatMap(getWebViewVirtualDom)];
2115
1665
  };
@@ -2124,10 +1674,10 @@ const Settings = 'Settings';
2124
1674
  const WebViews = 'WebViews';
2125
1675
  const Theme = 'Theme';
2126
1676
 
2127
- const getFeatureContentVirtualDom = (features, themesHtml, selectedFeature, extension) => {
1677
+ const getFeatureContentVirtualDom = async (features, themesHtml, selectedFeature, extension) => {
2128
1678
  switch (selectedFeature) {
2129
1679
  case Theme:
2130
- return getFeatureThemesVirtualDom(themesHtml);
1680
+ return await getFeatureThemesVirtualDom(themesHtml);
2131
1681
  case Commands:
2132
1682
  return getFeatureCommandsVirtualDom(extension);
2133
1683
  case JsonValidation:
@@ -2162,38 +1712,38 @@ const getFeatureListItemVirtualDom = feature => {
2162
1712
  const getFeatureListVirtualDom = features => {
2163
1713
  return [{
2164
1714
  // TODO use either list or tabs role
2165
- type: Div$1,
1715
+ type: Div,
2166
1716
  className: FeaturesList,
2167
1717
  childCount: features.length,
2168
1718
  onClick: HandleFeaturesClick
2169
1719
  }, ...features.flatMap(getFeatureListItemVirtualDom)];
2170
1720
  };
2171
1721
 
2172
- const getFeaturesVirtualDom = (features, themesHtml, selectedFeature, extension) => {
1722
+ const getFeaturesVirtualDom = async (features, themesHtml, selectedFeature, extension) => {
2173
1723
  if (features.length === 0) {
2174
1724
  return [{
2175
- type: Div$1,
1725
+ type: Div,
2176
1726
  className: Features$1,
2177
1727
  childCount: 3
2178
1728
  }, text('None')];
2179
1729
  }
2180
1730
  return [{
2181
- type: Div$1,
1731
+ type: Div,
2182
1732
  className: Features$1,
2183
1733
  childCount: 3
2184
1734
  }, ...getFeatureListVirtualDom(features), {
2185
- type: Div$1,
1735
+ type: Div,
2186
1736
  className: 'Sash SashVertical',
2187
1737
  childCount: 0
2188
- }, ...getFeatureContentVirtualDom(features, themesHtml, selectedFeature, extension)];
1738
+ }, ...(await getFeatureContentVirtualDom(features, themesHtml, selectedFeature, extension))];
2189
1739
  };
2190
1740
 
2191
- 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) => {
2192
1742
  switch (selectedTab) {
2193
1743
  case Details:
2194
- return getDetailsVirtualDom(sanitizedReadmeHtml, displaySize, extensionId, extensionVersion, width);
1744
+ return await getDetailsVirtualDom(sanitizedReadmeHtml, displaySize, extensionId, extensionVersion, width);
2195
1745
  case Features:
2196
- return getFeaturesVirtualDom(features, themesHtml, selectedFeature, extension);
1746
+ return await getFeaturesVirtualDom(features, themesHtml, selectedFeature, extension);
2197
1747
  case Changelog:
2198
1748
  return getChangelogVirtualDom();
2199
1749
  default:
@@ -2212,7 +1762,7 @@ const getButtonVirtualDom = (message, onClick) => {
2212
1762
 
2213
1763
  const getExtensionDetailHeaderActionsVirtualDom = () => {
2214
1764
  const dom = [{
2215
- type: Div$1,
1765
+ type: Div,
2216
1766
  className: ExtensionDetailHeaderActions,
2217
1767
  childCount: 2
2218
1768
  }, ...getButtonVirtualDom('Disable', HandleClickDisable), ...getButtonVirtualDom('Uninstall', HandleClickUninstall)];
@@ -2226,26 +1776,26 @@ const getExtensionDetailHeaderVirtualDom = extensionDetail => {
2226
1776
  description
2227
1777
  } = extensionDetail;
2228
1778
  const dom = [{
2229
- type: Div$1,
1779
+ type: Div,
2230
1780
  className: ExtensionDetailHeader,
2231
1781
  childCount: 2
2232
1782
  }, {
2233
- type: Img$1,
1783
+ type: Img,
2234
1784
  className: ExtensionDetailIcon,
2235
1785
  alt: '',
2236
1786
  draggable: false,
2237
1787
  childCount: 0,
2238
1788
  src: iconSrc
2239
1789
  }, {
2240
- type: Div$1,
1790
+ type: Div,
2241
1791
  className: ExtensionDetailHeaderDetails,
2242
1792
  childCount: 3
2243
1793
  }, {
2244
- type: Div$1,
1794
+ type: Div,
2245
1795
  className: ExtensionDetailName,
2246
1796
  childCount: 1
2247
1797
  }, text(name), {
2248
- type: Div$1,
1798
+ type: Div,
2249
1799
  className: ExtensionDetailDescription,
2250
1800
  childCount: 1
2251
1801
  }, text(description), ...getExtensionDetailHeaderActionsVirtualDom()];
@@ -2342,7 +1892,7 @@ const getTabVirtualDom = tab => {
2342
1892
 
2343
1893
  const getTabsVirtualDom = tabs => {
2344
1894
  return [{
2345
- type: Div$1,
1895
+ type: Div,
2346
1896
  className: ExtensionDetailTabs,
2347
1897
  childCount: tabs.length,
2348
1898
  role: TabList,
@@ -2378,7 +1928,7 @@ const getClassNames = size => {
2378
1928
  }
2379
1929
  };
2380
1930
 
2381
- const getExtensionDetailVirtualDom = (extensionDetail, sanitizedReadmeHtml, selectedTab, newState) => {
1931
+ const getExtensionDetailVirtualDom = async (extensionDetail, sanitizedReadmeHtml, selectedTab, newState) => {
2382
1932
  // TODO move this to view model so that rendering occurs like
2383
1933
  // 1. state
2384
1934
  // 2. view model
@@ -2397,18 +1947,18 @@ const getExtensionDetailVirtualDom = (extensionDetail, sanitizedReadmeHtml, sele
2397
1947
  const sizeValue = getViewletSize(newState?.width || 0);
2398
1948
  const sizeClass = getClassNames(sizeValue);
2399
1949
  const dom = [{
2400
- type: Div$1,
1950
+ type: Div,
2401
1951
  className: mergeClassNames(Viewlet, ExtensionDetail, sizeClass),
2402
1952
  childCount: 3
2403
- }, ...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))];
2404
1954
  return dom;
2405
1955
  };
2406
1956
 
2407
- const getExtensionDetailVirtualDom2 = uid => {
1957
+ const getExtensionDetailVirtualDom2 = async uid => {
2408
1958
  const {
2409
1959
  newState
2410
1960
  } = get$1(uid);
2411
- return getExtensionDetailVirtualDom(newState, newState.sanitizedReadmeHtml, newState.selectedTab, newState);
1961
+ return await getExtensionDetailVirtualDom(newState, newState.sanitizedReadmeHtml, newState.selectedTab, newState);
2412
1962
  };
2413
1963
 
2414
1964
  const None = 0;
@@ -2488,21 +2038,6 @@ const handleClickFeatures = async (state, name) => {
2488
2038
  return selectFeature(state, name);
2489
2039
  };
2490
2040
 
2491
- const RendererWorker = 1;
2492
-
2493
- const rpcs = Object.create(null);
2494
- const set = (id, rpc) => {
2495
- rpcs[id] = rpc;
2496
- };
2497
- const get = id => {
2498
- return rpcs[id];
2499
- };
2500
-
2501
- const invoke = (method, ...params) => {
2502
- const rpc = get(RendererWorker);
2503
- return rpc.invoke(method, ...params);
2504
- };
2505
-
2506
2041
  const handleClickSize = async state => {
2507
2042
  const {
2508
2043
  uri
@@ -2591,2492 +2126,8 @@ const getThemeMarkdown = (themes, iconThemes, productIconThemes) => {
2591
2126
  return markdown;
2592
2127
  };
2593
2128
 
2594
- /**
2595
- * marked v15.0.6 - a markdown parser
2596
- * Copyright (c) 2011-2025, Christopher Jeffrey. (MIT Licensed)
2597
- * https://github.com/markedjs/marked
2598
- */
2599
-
2600
- /**
2601
- * DO NOT EDIT THIS FILE
2602
- * The code in this file is generated from files in ./src/
2603
- */
2604
-
2605
- /**
2606
- * Gets the original marked default options.
2607
- */
2608
- function _getDefaults() {
2609
- return {
2610
- async: false,
2611
- breaks: false,
2612
- extensions: null,
2613
- gfm: true,
2614
- hooks: null,
2615
- pedantic: false,
2616
- renderer: null,
2617
- silent: false,
2618
- tokenizer: null,
2619
- walkTokens: null
2620
- };
2621
- }
2622
- let _defaults = _getDefaults();
2623
- function changeDefaults(newDefaults) {
2624
- _defaults = newDefaults;
2625
- }
2626
- const noopTest = {
2627
- exec: () => null
2628
- };
2629
- function edit(regex, opt = '') {
2630
- let source = typeof regex === 'string' ? regex : regex.source;
2631
- const obj = {
2632
- replace: (name, val) => {
2633
- let valSource = typeof val === 'string' ? val : val.source;
2634
- valSource = valSource.replace(other.caret, '$1');
2635
- source = source.replace(name, valSource);
2636
- return obj;
2637
- },
2638
- getRegex: () => {
2639
- return new RegExp(source, opt);
2640
- }
2641
- };
2642
- return obj;
2643
- }
2644
- const other = {
2645
- codeRemoveIndent: /^(?: {1,4}| {0,3}\t)/gm,
2646
- outputLinkReplace: /\\([\[\]])/g,
2647
- indentCodeCompensation: /^(\s+)(?:```)/,
2648
- beginningSpace: /^\s+/,
2649
- endingHash: /#$/,
2650
- startingSpaceChar: /^ /,
2651
- endingSpaceChar: / $/,
2652
- nonSpaceChar: /[^ ]/,
2653
- newLineCharGlobal: /\n/g,
2654
- tabCharGlobal: /\t/g,
2655
- multipleSpaceGlobal: /\s+/g,
2656
- blankLine: /^[ \t]*$/,
2657
- doubleBlankLine: /\n[ \t]*\n[ \t]*$/,
2658
- blockquoteStart: /^ {0,3}>/,
2659
- blockquoteSetextReplace: /\n {0,3}((?:=+|-+) *)(?=\n|$)/g,
2660
- blockquoteSetextReplace2: /^ {0,3}>[ \t]?/gm,
2661
- listReplaceTabs: /^\t+/,
2662
- listReplaceNesting: /^ {1,4}(?=( {4})*[^ ])/g,
2663
- listIsTask: /^\[[ xX]\] /,
2664
- listReplaceTask: /^\[[ xX]\] +/,
2665
- anyLine: /\n.*\n/,
2666
- hrefBrackets: /^<(.*)>$/,
2667
- tableDelimiter: /[:|]/,
2668
- tableAlignChars: /^\||\| *$/g,
2669
- tableRowBlankLine: /\n[ \t]*$/,
2670
- tableAlignRight: /^ *-+: *$/,
2671
- tableAlignCenter: /^ *:-+: *$/,
2672
- tableAlignLeft: /^ *:-+ *$/,
2673
- startATag: /^<a /i,
2674
- endATag: /^<\/a>/i,
2675
- startPreScriptTag: /^<(pre|code|kbd|script)(\s|>)/i,
2676
- endPreScriptTag: /^<\/(pre|code|kbd|script)(\s|>)/i,
2677
- startAngleBracket: /^</,
2678
- endAngleBracket: />$/,
2679
- pedanticHrefTitle: /^([^'"]*[^\s])\s+(['"])(.*)\2/,
2680
- unicodeAlphaNumeric: /[\p{L}\p{N}]/u,
2681
- escapeTest: /[&<>"']/,
2682
- escapeReplace: /[&<>"']/g,
2683
- escapeTestNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,
2684
- escapeReplaceNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g,
2685
- unescapeTest: /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig,
2686
- caret: /(^|[^\[])\^/g,
2687
- percentDecode: /%25/g,
2688
- findPipe: /\|/g,
2689
- splitPipe: / \|/,
2690
- slashPipe: /\\\|/g,
2691
- carriageReturn: /\r\n|\r/g,
2692
- spaceLine: /^ +$/gm,
2693
- notSpaceStart: /^\S*/,
2694
- endingNewline: /\n$/,
2695
- listItemRegex: bull => new RegExp(`^( {0,3}${bull})((?:[\t ][^\\n]*)?(?:\\n|$))`),
2696
- nextBulletRegex: indent => new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ \t][^\\n]*)?(?:\\n|$))`),
2697
- hrRegex: indent => new RegExp(`^ {0,${Math.min(3, indent - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`),
2698
- fencesBeginRegex: indent => new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:\`\`\`|~~~)`),
2699
- headingBeginRegex: indent => new RegExp(`^ {0,${Math.min(3, indent - 1)}}#`),
2700
- htmlBeginRegex: indent => new RegExp(`^ {0,${Math.min(3, indent - 1)}}<(?:[a-z].*>|!--)`, 'i')
2701
- };
2702
- /**
2703
- * Block-Level Grammar
2704
- */
2705
- const newline = /^(?:[ \t]*(?:\n|$))+/;
2706
- const blockCode = /^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/;
2707
- const fences = /^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/;
2708
- const hr = /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/;
2709
- const heading = /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/;
2710
- const bullet = /(?:[*+-]|\d{1,9}[.)])/;
2711
- 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
2712
- .replace(/blockCode/g, /(?: {4}| {0,3}\t)/) // indented code blocks can interrupt
2713
- .replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/) // fenced code blocks can interrupt
2714
- .replace(/blockquote/g, / {0,3}>/) // blockquote can interrupt
2715
- .replace(/heading/g, / {0,3}#{1,6}/) // ATX heading can interrupt
2716
- .replace(/html/g, / {0,3}<[^\n>]+>\n/) // block html can interrupt
2717
- .getRegex();
2718
- const _paragraph = /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/;
2719
- const blockText = /^[^\n]+/;
2720
- const _blockLabel = /(?!\s*\])(?:\\.|[^\[\]\\])+/;
2721
- 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();
2722
- const list = edit(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g, bullet).getRegex();
2723
- 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';
2724
- const _comment = /<!--(?:-?>|[\s\S]*?(?:-->|$))/;
2725
- const html = edit('^ {0,3}(?:' // optional indentation
2726
- + '<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)' // (1)
2727
- + '|comment[^\\n]*(\\n+|$)' // (2)
2728
- + '|<\\?[\\s\\S]*?(?:\\?>\\n*|$)' // (3)
2729
- + '|<![A-Z][\\s\\S]*?(?:>\\n*|$)' // (4)
2730
- + '|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)' // (5)
2731
- + '|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$)' // (6)
2732
- + '|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$)' // (7) open tag
2733
- + '|</(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$)' // (7) closing tag
2734
- + ')', 'i').replace('comment', _comment).replace('tag', _tag).replace('attribute', / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex();
2735
- const paragraph = edit(_paragraph).replace('hr', hr).replace('heading', ' {0,3}#{1,6}(?:\\s|$)').replace('|lheading', '') // setext headings don't interrupt commonmark paragraphs
2736
- .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
2737
- .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)').replace('tag', _tag) // pars can be interrupted by type (6) html blocks
2738
- .getRegex();
2739
- const blockquote = edit(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace('paragraph', paragraph).getRegex();
2740
- /**
2741
- * Normal Block Grammar
2742
- */
2743
- const blockNormal = {
2744
- blockquote,
2745
- code: blockCode,
2746
- def,
2747
- fences,
2748
- heading,
2749
- hr,
2750
- html,
2751
- lheading,
2752
- list,
2753
- newline,
2754
- paragraph,
2755
- table: noopTest,
2756
- text: blockText
2757
- };
2758
- /**
2759
- * GFM Block Grammar
2760
- */
2761
- const gfmTable = edit('^ *([^\\n ].*)\\n' // Header
2762
- + ' {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)' // Align
2763
- + '(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)') // Cells
2764
- .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
2765
- .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)').replace('tag', _tag) // tables can be interrupted by type (6) html blocks
2766
- .getRegex();
2767
- const blockGfm = {
2768
- ...blockNormal,
2769
- table: gfmTable,
2770
- paragraph: edit(_paragraph).replace('hr', hr).replace('heading', ' {0,3}#{1,6}(?:\\s|$)').replace('|lheading', '') // setext headings don't interrupt commonmark paragraphs
2771
- .replace('table', gfmTable) // interrupt paragraphs with table
2772
- .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
2773
- .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)').replace('tag', _tag) // pars can be interrupted by type (6) html blocks
2774
- .getRegex()
2775
- };
2776
- /**
2777
- * Pedantic grammar (original John Gruber's loose markdown specification)
2778
- */
2779
- const blockPedantic = {
2780
- ...blockNormal,
2781
- html: edit('^ *(?:comment *(?:\\n|\\s*$)' + '|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)' // closed tag
2782
- + '|<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(),
2783
- def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,
2784
- heading: /^(#{1,6})(.*)(?:\n+|$)/,
2785
- fences: noopTest,
2786
- // fences not supported
2787
- lheading: /^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,
2788
- 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()
2789
- };
2790
- /**
2791
- * Inline-Level Grammar
2792
- */
2793
- const escape$1 = /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/;
2794
- const inlineCode = /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/;
2795
- const br = /^( {2,}|\\)\n(?!\s*$)/;
2796
- const inlineText = /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/;
2797
- // list of unicode punctuation marks, plus any missing characters from CommonMark spec
2798
- const _punctuation = /[\p{P}\p{S}]/u;
2799
- const _punctuationOrSpace = /[\s\p{P}\p{S}]/u;
2800
- const _notPunctuationOrSpace = /[^\s\p{P}\p{S}]/u;
2801
- const punctuation = edit(/^((?![*_])punctSpace)/, 'u').replace(/punctSpace/g, _punctuationOrSpace).getRegex();
2802
- // GFM allows ~ inside strong and em for strikethrough
2803
- const _punctuationGfmStrongEm = /(?!~)[\p{P}\p{S}]/u;
2804
- const _punctuationOrSpaceGfmStrongEm = /(?!~)[\s\p{P}\p{S}]/u;
2805
- const _notPunctuationOrSpaceGfmStrongEm = /(?:[^\s\p{P}\p{S}]|~)/u;
2806
- // sequences em should skip over [title](link), `code`, <html>
2807
- const blockSkip = /\[[^[\]]*?\]\((?:\\.|[^\\\(\)]|\((?:\\.|[^\\\(\)])*\))*\)|`[^`]*?`|<[^<>]*?>/g;
2808
- const emStrongLDelimCore = /^(?:\*+(?:((?!\*)punct)|[^\s*]))|^_+(?:((?!_)punct)|([^\s_]))/;
2809
- const emStrongLDelim = edit(emStrongLDelimCore, 'u').replace(/punct/g, _punctuation).getRegex();
2810
- const emStrongLDelimGfm = edit(emStrongLDelimCore, 'u').replace(/punct/g, _punctuationGfmStrongEm).getRegex();
2811
- const emStrongRDelimAstCore = '^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)' // Skip orphan inside strong
2812
- + '|[^*]+(?=[^*])' // Consume to delim
2813
- + '|(?!\\*)punct(\\*+)(?=[\\s]|$)' // (1) #*** can only be a Right Delimiter
2814
- + '|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)' // (2) a***#, a*** can only be a Right Delimiter
2815
- + '|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)' // (3) #***a, ***a can only be Left Delimiter
2816
- + '|[\\s](\\*+)(?!\\*)(?=punct)' // (4) ***# can only be Left Delimiter
2817
- + '|(?!\\*)punct(\\*+)(?!\\*)(?=punct)' // (5) #***# can be either Left or Right Delimiter
2818
- + '|notPunctSpace(\\*+)(?=notPunctSpace)'; // (6) a***a can be either Left or Right Delimiter
2819
- const emStrongRDelimAst = edit(emStrongRDelimAstCore, 'gu').replace(/notPunctSpace/g, _notPunctuationOrSpace).replace(/punctSpace/g, _punctuationOrSpace).replace(/punct/g, _punctuation).getRegex();
2820
- const emStrongRDelimAstGfm = edit(emStrongRDelimAstCore, 'gu').replace(/notPunctSpace/g, _notPunctuationOrSpaceGfmStrongEm).replace(/punctSpace/g, _punctuationOrSpaceGfmStrongEm).replace(/punct/g, _punctuationGfmStrongEm).getRegex();
2821
- // (6) Not allowed for _
2822
- const emStrongRDelimUnd = edit('^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)' // Skip orphan inside strong
2823
- + '|[^_]+(?=[^_])' // Consume to delim
2824
- + '|(?!_)punct(_+)(?=[\\s]|$)' // (1) #___ can only be a Right Delimiter
2825
- + '|notPunctSpace(_+)(?!_)(?=punctSpace|$)' // (2) a___#, a___ can only be a Right Delimiter
2826
- + '|(?!_)punctSpace(_+)(?=notPunctSpace)' // (3) #___a, ___a can only be Left Delimiter
2827
- + '|[\\s](_+)(?!_)(?=punct)' // (4) ___# can only be Left Delimiter
2828
- + '|(?!_)punct(_+)(?!_)(?=punct)', 'gu') // (5) #___# can be either Left or Right Delimiter
2829
- .replace(/notPunctSpace/g, _notPunctuationOrSpace).replace(/punctSpace/g, _punctuationOrSpace).replace(/punct/g, _punctuation).getRegex();
2830
- const anyPunctuation = edit(/\\(punct)/, 'gu').replace(/punct/g, _punctuation).getRegex();
2831
- 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();
2832
- const _inlineComment = edit(_comment).replace('(?:-->|$)', '-->').getRegex();
2833
- const tag = edit('^comment' + '|^</[a-zA-Z][\\w:-]*\\s*>' // self-closing tag
2834
- + '|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>' // open tag
2835
- + '|^<\\?[\\s\\S]*?\\?>' // processing instruction, e.g. <?php ?>
2836
- + '|^<![a-zA-Z]+\\s[\\s\\S]*?>' // declaration, e.g. <!DOCTYPE html>
2837
- + '|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>') // CDATA section
2838
- .replace('comment', _inlineComment).replace('attribute', /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex();
2839
- const _inlineLabel = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/;
2840
- const link = edit(/^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/).replace('label', _inlineLabel).replace('href', /<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/).replace('title', /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex();
2841
- const reflink = edit(/^!?\[(label)\]\[(ref)\]/).replace('label', _inlineLabel).replace('ref', _blockLabel).getRegex();
2842
- const nolink = edit(/^!?\[(ref)\](?:\[\])?/).replace('ref', _blockLabel).getRegex();
2843
- const reflinkSearch = edit('reflink|nolink(?!\\()', 'g').replace('reflink', reflink).replace('nolink', nolink).getRegex();
2844
- /**
2845
- * Normal Inline Grammar
2846
- */
2847
- const inlineNormal = {
2848
- _backpedal: noopTest,
2849
- // only used for GFM url
2850
- anyPunctuation,
2851
- autolink,
2852
- blockSkip,
2853
- br,
2854
- code: inlineCode,
2855
- del: noopTest,
2856
- emStrongLDelim,
2857
- emStrongRDelimAst,
2858
- emStrongRDelimUnd,
2859
- escape: escape$1,
2860
- link,
2861
- nolink,
2862
- punctuation,
2863
- reflink,
2864
- reflinkSearch,
2865
- tag,
2866
- text: inlineText,
2867
- url: noopTest
2868
- };
2869
- /**
2870
- * Pedantic Inline Grammar
2871
- */
2872
- const inlinePedantic = {
2873
- ...inlineNormal,
2874
- link: edit(/^!?\[(label)\]\((.*?)\)/).replace('label', _inlineLabel).getRegex(),
2875
- reflink: edit(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace('label', _inlineLabel).getRegex()
2876
- };
2877
- /**
2878
- * GFM Inline Grammar
2879
- */
2880
- const inlineGfm = {
2881
- ...inlineNormal,
2882
- emStrongRDelimAst: emStrongRDelimAstGfm,
2883
- emStrongLDelim: emStrongLDelimGfm,
2884
- 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(),
2885
- _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/,
2886
- del: /^(~~?)(?=[^\s~])((?:\\.|[^\\])*?(?:\\.|[^\s~\\]))\1(?=[^~]|$)/,
2887
- text: /^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|https?:\/\/|ftp:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/
2888
- };
2889
- /**
2890
- * GFM + Line Breaks Inline Grammar
2891
- */
2892
- const inlineBreaks = {
2893
- ...inlineGfm,
2894
- br: edit(br).replace('{2,}', '*').getRegex(),
2895
- text: edit(inlineGfm.text).replace('\\b_', '\\b_| {2,}\\n').replace(/\{2,\}/g, '*').getRegex()
2896
- };
2897
- /**
2898
- * exports
2899
- */
2900
- const block = {
2901
- normal: blockNormal,
2902
- gfm: blockGfm,
2903
- pedantic: blockPedantic
2904
- };
2905
- const inline = {
2906
- normal: inlineNormal,
2907
- gfm: inlineGfm,
2908
- breaks: inlineBreaks,
2909
- pedantic: inlinePedantic
2910
- };
2911
-
2912
- /**
2913
- * Helpers
2914
- */
2915
- const escapeReplacements = {
2916
- '&': '&amp;',
2917
- '<': '&lt;',
2918
- '>': '&gt;',
2919
- '"': '&quot;',
2920
- "'": '&#39;'
2921
- };
2922
- const getEscapeReplacement = ch => escapeReplacements[ch];
2923
- function escape(html, encode) {
2924
- if (encode) {
2925
- if (other.escapeTest.test(html)) {
2926
- return html.replace(other.escapeReplace, getEscapeReplacement);
2927
- }
2928
- } else {
2929
- if (other.escapeTestNoEncode.test(html)) {
2930
- return html.replace(other.escapeReplaceNoEncode, getEscapeReplacement);
2931
- }
2932
- }
2933
- return html;
2934
- }
2935
- function cleanUrl(href) {
2936
- try {
2937
- href = encodeURI(href).replace(other.percentDecode, '%');
2938
- } catch {
2939
- return null;
2940
- }
2941
- return href;
2942
- }
2943
- function splitCells(tableRow, count) {
2944
- // ensure that every cell-delimiting pipe has a space
2945
- // before it to distinguish it from an escaped pipe
2946
- const row = tableRow.replace(other.findPipe, (match, offset, str) => {
2947
- let escaped = false;
2948
- let curr = offset;
2949
- while (--curr >= 0 && str[curr] === '\\') escaped = !escaped;
2950
- if (escaped) {
2951
- // odd number of slashes means | is escaped
2952
- // so we leave it alone
2953
- return '|';
2954
- } else {
2955
- // add space before unescaped |
2956
- return ' |';
2957
- }
2958
- }),
2959
- cells = row.split(other.splitPipe);
2960
- let i = 0;
2961
- // First/last cell in a row cannot be empty if it has no leading/trailing pipe
2962
- if (!cells[0].trim()) {
2963
- cells.shift();
2964
- }
2965
- if (cells.length > 0 && !cells.at(-1)?.trim()) {
2966
- cells.pop();
2967
- }
2968
- if (count) {
2969
- if (cells.length > count) {
2970
- cells.splice(count);
2971
- } else {
2972
- while (cells.length < count) cells.push('');
2973
- }
2974
- }
2975
- for (; i < cells.length; i++) {
2976
- // leading or trailing whitespace is ignored per the gfm spec
2977
- cells[i] = cells[i].trim().replace(other.slashPipe, '|');
2978
- }
2979
- return cells;
2980
- }
2981
- /**
2982
- * Remove trailing 'c's. Equivalent to str.replace(/c*$/, '').
2983
- * /c*$/ is vulnerable to REDOS.
2984
- *
2985
- * @param str
2986
- * @param c
2987
- * @param invert Remove suffix of non-c chars instead. Default falsey.
2988
- */
2989
- function rtrim(str, c, invert) {
2990
- const l = str.length;
2991
- if (l === 0) {
2992
- return '';
2993
- }
2994
- // Length of suffix matching the invert condition.
2995
- let suffLen = 0;
2996
- // Step left until we fail to match the invert condition.
2997
- while (suffLen < l) {
2998
- const currChar = str.charAt(l - suffLen - 1);
2999
- if (currChar === c && true) {
3000
- suffLen++;
3001
- } else {
3002
- break;
3003
- }
3004
- }
3005
- return str.slice(0, l - suffLen);
3006
- }
3007
- function findClosingBracket(str, b) {
3008
- if (str.indexOf(b[1]) === -1) {
3009
- return -1;
3010
- }
3011
- let level = 0;
3012
- for (let i = 0; i < str.length; i++) {
3013
- if (str[i] === '\\') {
3014
- i++;
3015
- } else if (str[i] === b[0]) {
3016
- level++;
3017
- } else if (str[i] === b[1]) {
3018
- level--;
3019
- if (level < 0) {
3020
- return i;
3021
- }
3022
- }
3023
- }
3024
- return -1;
3025
- }
3026
- function outputLink(cap, link, raw, lexer, rules) {
3027
- const href = link.href;
3028
- const title = link.title || null;
3029
- const text = cap[1].replace(rules.other.outputLinkReplace, '$1');
3030
- if (cap[0].charAt(0) !== '!') {
3031
- lexer.state.inLink = true;
3032
- const token = {
3033
- type: 'link',
3034
- raw,
3035
- href,
3036
- title,
3037
- text,
3038
- tokens: lexer.inlineTokens(text)
3039
- };
3040
- lexer.state.inLink = false;
3041
- return token;
3042
- }
3043
- return {
3044
- type: 'image',
3045
- raw,
3046
- href,
3047
- title,
3048
- text
3049
- };
3050
- }
3051
- function indentCodeCompensation(raw, text, rules) {
3052
- const matchIndentToCode = raw.match(rules.other.indentCodeCompensation);
3053
- if (matchIndentToCode === null) {
3054
- return text;
3055
- }
3056
- const indentToCode = matchIndentToCode[1];
3057
- return text.split('\n').map(node => {
3058
- const matchIndentInNode = node.match(rules.other.beginningSpace);
3059
- if (matchIndentInNode === null) {
3060
- return node;
3061
- }
3062
- const [indentInNode] = matchIndentInNode;
3063
- if (indentInNode.length >= indentToCode.length) {
3064
- return node.slice(indentToCode.length);
3065
- }
3066
- return node;
3067
- }).join('\n');
3068
- }
3069
- /**
3070
- * Tokenizer
3071
- */
3072
- class _Tokenizer {
3073
- options;
3074
- rules; // set by the lexer
3075
- lexer; // set by the lexer
3076
- constructor(options) {
3077
- this.options = options || _defaults;
3078
- }
3079
- space(src) {
3080
- const cap = this.rules.block.newline.exec(src);
3081
- if (cap && cap[0].length > 0) {
3082
- return {
3083
- type: 'space',
3084
- raw: cap[0]
3085
- };
3086
- }
3087
- }
3088
- code(src) {
3089
- const cap = this.rules.block.code.exec(src);
3090
- if (cap) {
3091
- const text = cap[0].replace(this.rules.other.codeRemoveIndent, '');
3092
- return {
3093
- type: 'code',
3094
- raw: cap[0],
3095
- codeBlockStyle: 'indented',
3096
- text: !this.options.pedantic ? rtrim(text, '\n') : text
3097
- };
3098
- }
3099
- }
3100
- fences(src) {
3101
- const cap = this.rules.block.fences.exec(src);
3102
- if (cap) {
3103
- const raw = cap[0];
3104
- const text = indentCodeCompensation(raw, cap[3] || '', this.rules);
3105
- return {
3106
- type: 'code',
3107
- raw,
3108
- lang: cap[2] ? cap[2].trim().replace(this.rules.inline.anyPunctuation, '$1') : cap[2],
3109
- text
3110
- };
3111
- }
3112
- }
3113
- heading(src) {
3114
- const cap = this.rules.block.heading.exec(src);
3115
- if (cap) {
3116
- let text = cap[2].trim();
3117
- // remove trailing #s
3118
- if (this.rules.other.endingHash.test(text)) {
3119
- const trimmed = rtrim(text, '#');
3120
- if (this.options.pedantic) {
3121
- text = trimmed.trim();
3122
- } else if (!trimmed || this.rules.other.endingSpaceChar.test(trimmed)) {
3123
- // CommonMark requires space before trailing #s
3124
- text = trimmed.trim();
3125
- }
3126
- }
3127
- return {
3128
- type: 'heading',
3129
- raw: cap[0],
3130
- depth: cap[1].length,
3131
- text,
3132
- tokens: this.lexer.inline(text)
3133
- };
3134
- }
3135
- }
3136
- hr(src) {
3137
- const cap = this.rules.block.hr.exec(src);
3138
- if (cap) {
3139
- return {
3140
- type: 'hr',
3141
- raw: rtrim(cap[0], '\n')
3142
- };
3143
- }
3144
- }
3145
- blockquote(src) {
3146
- const cap = this.rules.block.blockquote.exec(src);
3147
- if (cap) {
3148
- let lines = rtrim(cap[0], '\n').split('\n');
3149
- let raw = '';
3150
- let text = '';
3151
- const tokens = [];
3152
- while (lines.length > 0) {
3153
- let inBlockquote = false;
3154
- const currentLines = [];
3155
- let i;
3156
- for (i = 0; i < lines.length; i++) {
3157
- // get lines up to a continuation
3158
- if (this.rules.other.blockquoteStart.test(lines[i])) {
3159
- currentLines.push(lines[i]);
3160
- inBlockquote = true;
3161
- } else if (!inBlockquote) {
3162
- currentLines.push(lines[i]);
3163
- } else {
3164
- break;
3165
- }
3166
- }
3167
- lines = lines.slice(i);
3168
- const currentRaw = currentLines.join('\n');
3169
- const currentText = currentRaw
3170
- // precede setext continuation with 4 spaces so it isn't a setext
3171
- .replace(this.rules.other.blockquoteSetextReplace, '\n $1').replace(this.rules.other.blockquoteSetextReplace2, '');
3172
- raw = raw ? `${raw}\n${currentRaw}` : currentRaw;
3173
- text = text ? `${text}\n${currentText}` : currentText;
3174
- // parse blockquote lines as top level tokens
3175
- // merge paragraphs if this is a continuation
3176
- const top = this.lexer.state.top;
3177
- this.lexer.state.top = true;
3178
- this.lexer.blockTokens(currentText, tokens, true);
3179
- this.lexer.state.top = top;
3180
- // if there is no continuation then we are done
3181
- if (lines.length === 0) {
3182
- break;
3183
- }
3184
- const lastToken = tokens.at(-1);
3185
- if (lastToken?.type === 'code') {
3186
- // blockquote continuation cannot be preceded by a code block
3187
- break;
3188
- } else if (lastToken?.type === 'blockquote') {
3189
- // include continuation in nested blockquote
3190
- const oldToken = lastToken;
3191
- const newText = oldToken.raw + '\n' + lines.join('\n');
3192
- const newToken = this.blockquote(newText);
3193
- tokens[tokens.length - 1] = newToken;
3194
- raw = raw.substring(0, raw.length - oldToken.raw.length) + newToken.raw;
3195
- text = text.substring(0, text.length - oldToken.text.length) + newToken.text;
3196
- break;
3197
- } else if (lastToken?.type === 'list') {
3198
- // include continuation in nested list
3199
- const oldToken = lastToken;
3200
- const newText = oldToken.raw + '\n' + lines.join('\n');
3201
- const newToken = this.list(newText);
3202
- tokens[tokens.length - 1] = newToken;
3203
- raw = raw.substring(0, raw.length - lastToken.raw.length) + newToken.raw;
3204
- text = text.substring(0, text.length - oldToken.raw.length) + newToken.raw;
3205
- lines = newText.substring(tokens.at(-1).raw.length).split('\n');
3206
- continue;
3207
- }
3208
- }
3209
- return {
3210
- type: 'blockquote',
3211
- raw,
3212
- tokens,
3213
- text
3214
- };
3215
- }
3216
- }
3217
- list(src) {
3218
- let cap = this.rules.block.list.exec(src);
3219
- if (cap) {
3220
- let bull = cap[1].trim();
3221
- const isordered = bull.length > 1;
3222
- const list = {
3223
- type: 'list',
3224
- raw: '',
3225
- ordered: isordered,
3226
- start: isordered ? +bull.slice(0, -1) : '',
3227
- loose: false,
3228
- items: []
3229
- };
3230
- bull = isordered ? `\\d{1,9}\\${bull.slice(-1)}` : `\\${bull}`;
3231
- if (this.options.pedantic) {
3232
- bull = isordered ? bull : '[*+-]';
3233
- }
3234
- // Get next list item
3235
- const itemRegex = this.rules.other.listItemRegex(bull);
3236
- let endsWithBlankLine = false;
3237
- // Check if current bullet point can start a new List Item
3238
- while (src) {
3239
- let endEarly = false;
3240
- let raw = '';
3241
- let itemContents = '';
3242
- if (!(cap = itemRegex.exec(src))) {
3243
- break;
3244
- }
3245
- if (this.rules.block.hr.test(src)) {
3246
- // End list if bullet was actually HR (possibly move into itemRegex?)
3247
- break;
3248
- }
3249
- raw = cap[0];
3250
- src = src.substring(raw.length);
3251
- let line = cap[2].split('\n', 1)[0].replace(this.rules.other.listReplaceTabs, t => ' '.repeat(3 * t.length));
3252
- let nextLine = src.split('\n', 1)[0];
3253
- let blankLine = !line.trim();
3254
- let indent = 0;
3255
- if (this.options.pedantic) {
3256
- indent = 2;
3257
- itemContents = line.trimStart();
3258
- } else if (blankLine) {
3259
- indent = cap[1].length + 1;
3260
- } else {
3261
- indent = cap[2].search(this.rules.other.nonSpaceChar); // Find first non-space char
3262
- indent = indent > 4 ? 1 : indent; // Treat indented code blocks (> 4 spaces) as having only 1 indent
3263
- itemContents = line.slice(indent);
3264
- indent += cap[1].length;
3265
- }
3266
- if (blankLine && this.rules.other.blankLine.test(nextLine)) {
3267
- // Items begin with at most one blank line
3268
- raw += nextLine + '\n';
3269
- src = src.substring(nextLine.length + 1);
3270
- endEarly = true;
3271
- }
3272
- if (!endEarly) {
3273
- const nextBulletRegex = this.rules.other.nextBulletRegex(indent);
3274
- const hrRegex = this.rules.other.hrRegex(indent);
3275
- const fencesBeginRegex = this.rules.other.fencesBeginRegex(indent);
3276
- const headingBeginRegex = this.rules.other.headingBeginRegex(indent);
3277
- const htmlBeginRegex = this.rules.other.htmlBeginRegex(indent);
3278
- // Check if following lines should be included in List Item
3279
- while (src) {
3280
- const rawLine = src.split('\n', 1)[0];
3281
- let nextLineWithoutTabs;
3282
- nextLine = rawLine;
3283
- // Re-align to follow commonmark nesting rules
3284
- if (this.options.pedantic) {
3285
- nextLine = nextLine.replace(this.rules.other.listReplaceNesting, ' ');
3286
- nextLineWithoutTabs = nextLine;
3287
- } else {
3288
- nextLineWithoutTabs = nextLine.replace(this.rules.other.tabCharGlobal, ' ');
3289
- }
3290
- // End list item if found code fences
3291
- if (fencesBeginRegex.test(nextLine)) {
3292
- break;
3293
- }
3294
- // End list item if found start of new heading
3295
- if (headingBeginRegex.test(nextLine)) {
3296
- break;
3297
- }
3298
- // End list item if found start of html block
3299
- if (htmlBeginRegex.test(nextLine)) {
3300
- break;
3301
- }
3302
- // End list item if found start of new bullet
3303
- if (nextBulletRegex.test(nextLine)) {
3304
- break;
3305
- }
3306
- // Horizontal rule found
3307
- if (hrRegex.test(nextLine)) {
3308
- break;
3309
- }
3310
- if (nextLineWithoutTabs.search(this.rules.other.nonSpaceChar) >= indent || !nextLine.trim()) {
3311
- // Dedent if possible
3312
- itemContents += '\n' + nextLineWithoutTabs.slice(indent);
3313
- } else {
3314
- // not enough indentation
3315
- if (blankLine) {
3316
- break;
3317
- }
3318
- // paragraph continuation unless last line was a different block level element
3319
- if (line.replace(this.rules.other.tabCharGlobal, ' ').search(this.rules.other.nonSpaceChar) >= 4) {
3320
- // indented code block
3321
- break;
3322
- }
3323
- if (fencesBeginRegex.test(line)) {
3324
- break;
3325
- }
3326
- if (headingBeginRegex.test(line)) {
3327
- break;
3328
- }
3329
- if (hrRegex.test(line)) {
3330
- break;
3331
- }
3332
- itemContents += '\n' + nextLine;
3333
- }
3334
- if (!blankLine && !nextLine.trim()) {
3335
- // Check if current line is blank
3336
- blankLine = true;
3337
- }
3338
- raw += rawLine + '\n';
3339
- src = src.substring(rawLine.length + 1);
3340
- line = nextLineWithoutTabs.slice(indent);
3341
- }
3342
- }
3343
- if (!list.loose) {
3344
- // If the previous item ended with a blank line, the list is loose
3345
- if (endsWithBlankLine) {
3346
- list.loose = true;
3347
- } else if (this.rules.other.doubleBlankLine.test(raw)) {
3348
- endsWithBlankLine = true;
3349
- }
3350
- }
3351
- let istask = null;
3352
- let ischecked;
3353
- // Check for task list items
3354
- if (this.options.gfm) {
3355
- istask = this.rules.other.listIsTask.exec(itemContents);
3356
- if (istask) {
3357
- ischecked = istask[0] !== '[ ] ';
3358
- itemContents = itemContents.replace(this.rules.other.listReplaceTask, '');
3359
- }
3360
- }
3361
- list.items.push({
3362
- type: 'list_item',
3363
- raw,
3364
- task: !!istask,
3365
- checked: ischecked,
3366
- loose: false,
3367
- text: itemContents,
3368
- tokens: []
3369
- });
3370
- list.raw += raw;
3371
- }
3372
- // Do not consume newlines at end of final item. Alternatively, make itemRegex *start* with any newlines to simplify/speed up endsWithBlankLine logic
3373
- const lastItem = list.items.at(-1);
3374
- if (lastItem) {
3375
- lastItem.raw = lastItem.raw.trimEnd();
3376
- lastItem.text = lastItem.text.trimEnd();
3377
- } else {
3378
- // not a list since there were no items
3379
- return;
3380
- }
3381
- list.raw = list.raw.trimEnd();
3382
- // Item child tokens handled here at end because we needed to have the final item to trim it first
3383
- for (let i = 0; i < list.items.length; i++) {
3384
- this.lexer.state.top = false;
3385
- list.items[i].tokens = this.lexer.blockTokens(list.items[i].text, []);
3386
- if (!list.loose) {
3387
- // Check if list should be loose
3388
- const spacers = list.items[i].tokens.filter(t => t.type === 'space');
3389
- const hasMultipleLineBreaks = spacers.length > 0 && spacers.some(t => this.rules.other.anyLine.test(t.raw));
3390
- list.loose = hasMultipleLineBreaks;
3391
- }
3392
- }
3393
- // Set all items to loose if list is loose
3394
- if (list.loose) {
3395
- for (let i = 0; i < list.items.length; i++) {
3396
- list.items[i].loose = true;
3397
- }
3398
- }
3399
- return list;
3400
- }
3401
- }
3402
- html(src) {
3403
- const cap = this.rules.block.html.exec(src);
3404
- if (cap) {
3405
- const token = {
3406
- type: 'html',
3407
- block: true,
3408
- raw: cap[0],
3409
- pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style',
3410
- text: cap[0]
3411
- };
3412
- return token;
3413
- }
3414
- }
3415
- def(src) {
3416
- const cap = this.rules.block.def.exec(src);
3417
- if (cap) {
3418
- const tag = cap[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal, ' ');
3419
- const href = cap[2] ? cap[2].replace(this.rules.other.hrefBrackets, '$1').replace(this.rules.inline.anyPunctuation, '$1') : '';
3420
- const title = cap[3] ? cap[3].substring(1, cap[3].length - 1).replace(this.rules.inline.anyPunctuation, '$1') : cap[3];
3421
- return {
3422
- type: 'def',
3423
- tag,
3424
- raw: cap[0],
3425
- href,
3426
- title
3427
- };
3428
- }
3429
- }
3430
- table(src) {
3431
- const cap = this.rules.block.table.exec(src);
3432
- if (!cap) {
3433
- return;
3434
- }
3435
- if (!this.rules.other.tableDelimiter.test(cap[2])) {
3436
- // delimiter row must have a pipe (|) or colon (:) otherwise it is a setext heading
3437
- return;
3438
- }
3439
- const headers = splitCells(cap[1]);
3440
- const aligns = cap[2].replace(this.rules.other.tableAlignChars, '').split('|');
3441
- const rows = cap[3]?.trim() ? cap[3].replace(this.rules.other.tableRowBlankLine, '').split('\n') : [];
3442
- const item = {
3443
- type: 'table',
3444
- raw: cap[0],
3445
- header: [],
3446
- align: [],
3447
- rows: []
3448
- };
3449
- if (headers.length !== aligns.length) {
3450
- // header and align columns must be equal, rows can be different.
3451
- return;
3452
- }
3453
- for (const align of aligns) {
3454
- if (this.rules.other.tableAlignRight.test(align)) {
3455
- item.align.push('right');
3456
- } else if (this.rules.other.tableAlignCenter.test(align)) {
3457
- item.align.push('center');
3458
- } else if (this.rules.other.tableAlignLeft.test(align)) {
3459
- item.align.push('left');
3460
- } else {
3461
- item.align.push(null);
3462
- }
3463
- }
3464
- for (let i = 0; i < headers.length; i++) {
3465
- item.header.push({
3466
- text: headers[i],
3467
- tokens: this.lexer.inline(headers[i]),
3468
- header: true,
3469
- align: item.align[i]
3470
- });
3471
- }
3472
- for (const row of rows) {
3473
- item.rows.push(splitCells(row, item.header.length).map((cell, i) => {
3474
- return {
3475
- text: cell,
3476
- tokens: this.lexer.inline(cell),
3477
- header: false,
3478
- align: item.align[i]
3479
- };
3480
- }));
3481
- }
3482
- return item;
3483
- }
3484
- lheading(src) {
3485
- const cap = this.rules.block.lheading.exec(src);
3486
- if (cap) {
3487
- return {
3488
- type: 'heading',
3489
- raw: cap[0],
3490
- depth: cap[2].charAt(0) === '=' ? 1 : 2,
3491
- text: cap[1],
3492
- tokens: this.lexer.inline(cap[1])
3493
- };
3494
- }
3495
- }
3496
- paragraph(src) {
3497
- const cap = this.rules.block.paragraph.exec(src);
3498
- if (cap) {
3499
- const text = cap[1].charAt(cap[1].length - 1) === '\n' ? cap[1].slice(0, -1) : cap[1];
3500
- return {
3501
- type: 'paragraph',
3502
- raw: cap[0],
3503
- text,
3504
- tokens: this.lexer.inline(text)
3505
- };
3506
- }
3507
- }
3508
- text(src) {
3509
- const cap = this.rules.block.text.exec(src);
3510
- if (cap) {
3511
- return {
3512
- type: 'text',
3513
- raw: cap[0],
3514
- text: cap[0],
3515
- tokens: this.lexer.inline(cap[0])
3516
- };
3517
- }
3518
- }
3519
- escape(src) {
3520
- const cap = this.rules.inline.escape.exec(src);
3521
- if (cap) {
3522
- return {
3523
- type: 'escape',
3524
- raw: cap[0],
3525
- text: cap[1]
3526
- };
3527
- }
3528
- }
3529
- tag(src) {
3530
- const cap = this.rules.inline.tag.exec(src);
3531
- if (cap) {
3532
- if (!this.lexer.state.inLink && this.rules.other.startATag.test(cap[0])) {
3533
- this.lexer.state.inLink = true;
3534
- } else if (this.lexer.state.inLink && this.rules.other.endATag.test(cap[0])) {
3535
- this.lexer.state.inLink = false;
3536
- }
3537
- if (!this.lexer.state.inRawBlock && this.rules.other.startPreScriptTag.test(cap[0])) {
3538
- this.lexer.state.inRawBlock = true;
3539
- } else if (this.lexer.state.inRawBlock && this.rules.other.endPreScriptTag.test(cap[0])) {
3540
- this.lexer.state.inRawBlock = false;
3541
- }
3542
- return {
3543
- type: 'html',
3544
- raw: cap[0],
3545
- inLink: this.lexer.state.inLink,
3546
- inRawBlock: this.lexer.state.inRawBlock,
3547
- block: false,
3548
- text: cap[0]
3549
- };
3550
- }
3551
- }
3552
- link(src) {
3553
- const cap = this.rules.inline.link.exec(src);
3554
- if (cap) {
3555
- const trimmedUrl = cap[2].trim();
3556
- if (!this.options.pedantic && this.rules.other.startAngleBracket.test(trimmedUrl)) {
3557
- // commonmark requires matching angle brackets
3558
- if (!this.rules.other.endAngleBracket.test(trimmedUrl)) {
3559
- return;
3560
- }
3561
- // ending angle bracket cannot be escaped
3562
- const rtrimSlash = rtrim(trimmedUrl.slice(0, -1), '\\');
3563
- if ((trimmedUrl.length - rtrimSlash.length) % 2 === 0) {
3564
- return;
3565
- }
3566
- } else {
3567
- // find closing parenthesis
3568
- const lastParenIndex = findClosingBracket(cap[2], '()');
3569
- if (lastParenIndex > -1) {
3570
- const start = cap[0].indexOf('!') === 0 ? 5 : 4;
3571
- const linkLen = start + cap[1].length + lastParenIndex;
3572
- cap[2] = cap[2].substring(0, lastParenIndex);
3573
- cap[0] = cap[0].substring(0, linkLen).trim();
3574
- cap[3] = '';
3575
- }
3576
- }
3577
- let href = cap[2];
3578
- let title = '';
3579
- if (this.options.pedantic) {
3580
- // split pedantic href and title
3581
- const link = this.rules.other.pedanticHrefTitle.exec(href);
3582
- if (link) {
3583
- href = link[1];
3584
- title = link[3];
3585
- }
3586
- } else {
3587
- title = cap[3] ? cap[3].slice(1, -1) : '';
3588
- }
3589
- href = href.trim();
3590
- if (this.rules.other.startAngleBracket.test(href)) {
3591
- if (this.options.pedantic && !this.rules.other.endAngleBracket.test(trimmedUrl)) {
3592
- // pedantic allows starting angle bracket without ending angle bracket
3593
- href = href.slice(1);
3594
- } else {
3595
- href = href.slice(1, -1);
3596
- }
3597
- }
3598
- return outputLink(cap, {
3599
- href: href ? href.replace(this.rules.inline.anyPunctuation, '$1') : href,
3600
- title: title ? title.replace(this.rules.inline.anyPunctuation, '$1') : title
3601
- }, cap[0], this.lexer, this.rules);
3602
- }
3603
- }
3604
- reflink(src, links) {
3605
- let cap;
3606
- if ((cap = this.rules.inline.reflink.exec(src)) || (cap = this.rules.inline.nolink.exec(src))) {
3607
- const linkString = (cap[2] || cap[1]).replace(this.rules.other.multipleSpaceGlobal, ' ');
3608
- const link = links[linkString.toLowerCase()];
3609
- if (!link) {
3610
- const text = cap[0].charAt(0);
3611
- return {
3612
- type: 'text',
3613
- raw: text,
3614
- text
3615
- };
3616
- }
3617
- return outputLink(cap, link, cap[0], this.lexer, this.rules);
3618
- }
3619
- }
3620
- emStrong(src, maskedSrc, prevChar = '') {
3621
- let match = this.rules.inline.emStrongLDelim.exec(src);
3622
- if (!match) return;
3623
- // _ can't be between two alphanumerics. \p{L}\p{N} includes non-english alphabet/numbers as well
3624
- if (match[3] && prevChar.match(this.rules.other.unicodeAlphaNumeric)) return;
3625
- const nextChar = match[1] || match[2] || '';
3626
- if (!nextChar || !prevChar || this.rules.inline.punctuation.exec(prevChar)) {
3627
- // unicode Regex counts emoji as 1 char; spread into array for proper count (used multiple times below)
3628
- const lLength = [...match[0]].length - 1;
3629
- let rDelim,
3630
- rLength,
3631
- delimTotal = lLength,
3632
- midDelimTotal = 0;
3633
- const endReg = match[0][0] === '*' ? this.rules.inline.emStrongRDelimAst : this.rules.inline.emStrongRDelimUnd;
3634
- endReg.lastIndex = 0;
3635
- // Clip maskedSrc to same section of string as src (move to lexer?)
3636
- maskedSrc = maskedSrc.slice(-1 * src.length + lLength);
3637
- while ((match = endReg.exec(maskedSrc)) != null) {
3638
- rDelim = match[1] || match[2] || match[3] || match[4] || match[5] || match[6];
3639
- if (!rDelim) continue; // skip single * in __abc*abc__
3640
- rLength = [...rDelim].length;
3641
- if (match[3] || match[4]) {
3642
- // found another Left Delim
3643
- delimTotal += rLength;
3644
- continue;
3645
- } else if (match[5] || match[6]) {
3646
- // either Left or Right Delim
3647
- if (lLength % 3 && !((lLength + rLength) % 3)) {
3648
- midDelimTotal += rLength;
3649
- continue; // CommonMark Emphasis Rules 9-10
3650
- }
3651
- }
3652
- delimTotal -= rLength;
3653
- if (delimTotal > 0) continue; // Haven't found enough closing delimiters
3654
- // Remove extra characters. *a*** -> *a*
3655
- rLength = Math.min(rLength, rLength + delimTotal + midDelimTotal);
3656
- // char length can be >1 for unicode characters;
3657
- const lastCharLength = [...match[0]][0].length;
3658
- const raw = src.slice(0, lLength + match.index + lastCharLength + rLength);
3659
- // Create `em` if smallest delimiter has odd char count. *a***
3660
- if (Math.min(lLength, rLength) % 2) {
3661
- const text = raw.slice(1, -1);
3662
- return {
3663
- type: 'em',
3664
- raw,
3665
- text,
3666
- tokens: this.lexer.inlineTokens(text)
3667
- };
3668
- }
3669
- // Create 'strong' if smallest delimiter has even char count. **a***
3670
- const text = raw.slice(2, -2);
3671
- return {
3672
- type: 'strong',
3673
- raw,
3674
- text,
3675
- tokens: this.lexer.inlineTokens(text)
3676
- };
3677
- }
3678
- }
3679
- }
3680
- codespan(src) {
3681
- const cap = this.rules.inline.code.exec(src);
3682
- if (cap) {
3683
- let text = cap[2].replace(this.rules.other.newLineCharGlobal, ' ');
3684
- const hasNonSpaceChars = this.rules.other.nonSpaceChar.test(text);
3685
- const hasSpaceCharsOnBothEnds = this.rules.other.startingSpaceChar.test(text) && this.rules.other.endingSpaceChar.test(text);
3686
- if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) {
3687
- text = text.substring(1, text.length - 1);
3688
- }
3689
- return {
3690
- type: 'codespan',
3691
- raw: cap[0],
3692
- text
3693
- };
3694
- }
3695
- }
3696
- br(src) {
3697
- const cap = this.rules.inline.br.exec(src);
3698
- if (cap) {
3699
- return {
3700
- type: 'br',
3701
- raw: cap[0]
3702
- };
3703
- }
3704
- }
3705
- del(src) {
3706
- const cap = this.rules.inline.del.exec(src);
3707
- if (cap) {
3708
- return {
3709
- type: 'del',
3710
- raw: cap[0],
3711
- text: cap[2],
3712
- tokens: this.lexer.inlineTokens(cap[2])
3713
- };
3714
- }
3715
- }
3716
- autolink(src) {
3717
- const cap = this.rules.inline.autolink.exec(src);
3718
- if (cap) {
3719
- let text, href;
3720
- if (cap[2] === '@') {
3721
- text = cap[1];
3722
- href = 'mailto:' + text;
3723
- } else {
3724
- text = cap[1];
3725
- href = text;
3726
- }
3727
- return {
3728
- type: 'link',
3729
- raw: cap[0],
3730
- text,
3731
- href,
3732
- tokens: [{
3733
- type: 'text',
3734
- raw: text,
3735
- text
3736
- }]
3737
- };
3738
- }
3739
- }
3740
- url(src) {
3741
- let cap;
3742
- if (cap = this.rules.inline.url.exec(src)) {
3743
- let text, href;
3744
- if (cap[2] === '@') {
3745
- text = cap[0];
3746
- href = 'mailto:' + text;
3747
- } else {
3748
- // do extended autolink path validation
3749
- let prevCapZero;
3750
- do {
3751
- prevCapZero = cap[0];
3752
- cap[0] = this.rules.inline._backpedal.exec(cap[0])?.[0] ?? '';
3753
- } while (prevCapZero !== cap[0]);
3754
- text = cap[0];
3755
- if (cap[1] === 'www.') {
3756
- href = 'http://' + cap[0];
3757
- } else {
3758
- href = cap[0];
3759
- }
3760
- }
3761
- return {
3762
- type: 'link',
3763
- raw: cap[0],
3764
- text,
3765
- href,
3766
- tokens: [{
3767
- type: 'text',
3768
- raw: text,
3769
- text
3770
- }]
3771
- };
3772
- }
3773
- }
3774
- inlineText(src) {
3775
- const cap = this.rules.inline.text.exec(src);
3776
- if (cap) {
3777
- const escaped = this.lexer.state.inRawBlock;
3778
- return {
3779
- type: 'text',
3780
- raw: cap[0],
3781
- text: cap[0],
3782
- escaped
3783
- };
3784
- }
3785
- }
3786
- }
3787
-
3788
- /**
3789
- * Block Lexer
3790
- */
3791
- class _Lexer {
3792
- tokens;
3793
- options;
3794
- state;
3795
- tokenizer;
3796
- inlineQueue;
3797
- constructor(options) {
3798
- // TokenList cannot be created in one go
3799
- this.tokens = [];
3800
- this.tokens.links = Object.create(null);
3801
- this.options = options || _defaults;
3802
- this.options.tokenizer = this.options.tokenizer || new _Tokenizer();
3803
- this.tokenizer = this.options.tokenizer;
3804
- this.tokenizer.options = this.options;
3805
- this.tokenizer.lexer = this;
3806
- this.inlineQueue = [];
3807
- this.state = {
3808
- inLink: false,
3809
- inRawBlock: false,
3810
- top: true
3811
- };
3812
- const rules = {
3813
- other,
3814
- block: block.normal,
3815
- inline: inline.normal
3816
- };
3817
- if (this.options.pedantic) {
3818
- rules.block = block.pedantic;
3819
- rules.inline = inline.pedantic;
3820
- } else if (this.options.gfm) {
3821
- rules.block = block.gfm;
3822
- if (this.options.breaks) {
3823
- rules.inline = inline.breaks;
3824
- } else {
3825
- rules.inline = inline.gfm;
3826
- }
3827
- }
3828
- this.tokenizer.rules = rules;
3829
- }
3830
- /**
3831
- * Expose Rules
3832
- */
3833
- static get rules() {
3834
- return {
3835
- block,
3836
- inline
3837
- };
3838
- }
3839
- /**
3840
- * Static Lex Method
3841
- */
3842
- static lex(src, options) {
3843
- const lexer = new _Lexer(options);
3844
- return lexer.lex(src);
3845
- }
3846
- /**
3847
- * Static Lex Inline Method
3848
- */
3849
- static lexInline(src, options) {
3850
- const lexer = new _Lexer(options);
3851
- return lexer.inlineTokens(src);
3852
- }
3853
- /**
3854
- * Preprocessing
3855
- */
3856
- lex(src) {
3857
- src = src.replace(other.carriageReturn, '\n');
3858
- this.blockTokens(src, this.tokens);
3859
- for (let i = 0; i < this.inlineQueue.length; i++) {
3860
- const next = this.inlineQueue[i];
3861
- this.inlineTokens(next.src, next.tokens);
3862
- }
3863
- this.inlineQueue = [];
3864
- return this.tokens;
3865
- }
3866
- blockTokens(src, tokens = [], lastParagraphClipped = false) {
3867
- if (this.options.pedantic) {
3868
- src = src.replace(other.tabCharGlobal, ' ').replace(other.spaceLine, '');
3869
- }
3870
- while (src) {
3871
- let token;
3872
- if (this.options.extensions?.block?.some(extTokenizer => {
3873
- if (token = extTokenizer.call({
3874
- lexer: this
3875
- }, src, tokens)) {
3876
- src = src.substring(token.raw.length);
3877
- tokens.push(token);
3878
- return true;
3879
- }
3880
- return false;
3881
- })) {
3882
- continue;
3883
- }
3884
- // newline
3885
- if (token = this.tokenizer.space(src)) {
3886
- src = src.substring(token.raw.length);
3887
- const lastToken = tokens.at(-1);
3888
- if (token.raw.length === 1 && lastToken !== undefined) {
3889
- // if there's a single \n as a spacer, it's terminating the last line,
3890
- // so move it there so that we don't get unnecessary paragraph tags
3891
- lastToken.raw += '\n';
3892
- } else {
3893
- tokens.push(token);
3894
- }
3895
- continue;
3896
- }
3897
- // code
3898
- if (token = this.tokenizer.code(src)) {
3899
- src = src.substring(token.raw.length);
3900
- const lastToken = tokens.at(-1);
3901
- // An indented code block cannot interrupt a paragraph.
3902
- if (lastToken?.type === 'paragraph' || lastToken?.type === 'text') {
3903
- lastToken.raw += '\n' + token.raw;
3904
- lastToken.text += '\n' + token.text;
3905
- this.inlineQueue.at(-1).src = lastToken.text;
3906
- } else {
3907
- tokens.push(token);
3908
- }
3909
- continue;
3910
- }
3911
- // fences
3912
- if (token = this.tokenizer.fences(src)) {
3913
- src = src.substring(token.raw.length);
3914
- tokens.push(token);
3915
- continue;
3916
- }
3917
- // heading
3918
- if (token = this.tokenizer.heading(src)) {
3919
- src = src.substring(token.raw.length);
3920
- tokens.push(token);
3921
- continue;
3922
- }
3923
- // hr
3924
- if (token = this.tokenizer.hr(src)) {
3925
- src = src.substring(token.raw.length);
3926
- tokens.push(token);
3927
- continue;
3928
- }
3929
- // blockquote
3930
- if (token = this.tokenizer.blockquote(src)) {
3931
- src = src.substring(token.raw.length);
3932
- tokens.push(token);
3933
- continue;
3934
- }
3935
- // list
3936
- if (token = this.tokenizer.list(src)) {
3937
- src = src.substring(token.raw.length);
3938
- tokens.push(token);
3939
- continue;
3940
- }
3941
- // html
3942
- if (token = this.tokenizer.html(src)) {
3943
- src = src.substring(token.raw.length);
3944
- tokens.push(token);
3945
- continue;
3946
- }
3947
- // def
3948
- if (token = this.tokenizer.def(src)) {
3949
- src = src.substring(token.raw.length);
3950
- const lastToken = tokens.at(-1);
3951
- if (lastToken?.type === 'paragraph' || lastToken?.type === 'text') {
3952
- lastToken.raw += '\n' + token.raw;
3953
- lastToken.text += '\n' + token.raw;
3954
- this.inlineQueue.at(-1).src = lastToken.text;
3955
- } else if (!this.tokens.links[token.tag]) {
3956
- this.tokens.links[token.tag] = {
3957
- href: token.href,
3958
- title: token.title
3959
- };
3960
- }
3961
- continue;
3962
- }
3963
- // table (gfm)
3964
- if (token = this.tokenizer.table(src)) {
3965
- src = src.substring(token.raw.length);
3966
- tokens.push(token);
3967
- continue;
3968
- }
3969
- // lheading
3970
- if (token = this.tokenizer.lheading(src)) {
3971
- src = src.substring(token.raw.length);
3972
- tokens.push(token);
3973
- continue;
3974
- }
3975
- // top-level paragraph
3976
- // prevent paragraph consuming extensions by clipping 'src' to extension start
3977
- let cutSrc = src;
3978
- if (this.options.extensions?.startBlock) {
3979
- let startIndex = Infinity;
3980
- const tempSrc = src.slice(1);
3981
- let tempStart;
3982
- this.options.extensions.startBlock.forEach(getStartIndex => {
3983
- tempStart = getStartIndex.call({
3984
- lexer: this
3985
- }, tempSrc);
3986
- if (typeof tempStart === 'number' && tempStart >= 0) {
3987
- startIndex = Math.min(startIndex, tempStart);
3988
- }
3989
- });
3990
- if (startIndex < Infinity && startIndex >= 0) {
3991
- cutSrc = src.substring(0, startIndex + 1);
3992
- }
3993
- }
3994
- if (this.state.top && (token = this.tokenizer.paragraph(cutSrc))) {
3995
- const lastToken = tokens.at(-1);
3996
- if (lastParagraphClipped && lastToken?.type === 'paragraph') {
3997
- lastToken.raw += '\n' + token.raw;
3998
- lastToken.text += '\n' + token.text;
3999
- this.inlineQueue.pop();
4000
- this.inlineQueue.at(-1).src = lastToken.text;
4001
- } else {
4002
- tokens.push(token);
4003
- }
4004
- lastParagraphClipped = cutSrc.length !== src.length;
4005
- src = src.substring(token.raw.length);
4006
- continue;
4007
- }
4008
- // text
4009
- if (token = this.tokenizer.text(src)) {
4010
- src = src.substring(token.raw.length);
4011
- const lastToken = tokens.at(-1);
4012
- if (lastToken?.type === 'text') {
4013
- lastToken.raw += '\n' + token.raw;
4014
- lastToken.text += '\n' + token.text;
4015
- this.inlineQueue.pop();
4016
- this.inlineQueue.at(-1).src = lastToken.text;
4017
- } else {
4018
- tokens.push(token);
4019
- }
4020
- continue;
4021
- }
4022
- if (src) {
4023
- const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);
4024
- if (this.options.silent) {
4025
- console.error(errMsg);
4026
- break;
4027
- } else {
4028
- throw new Error(errMsg);
4029
- }
4030
- }
4031
- }
4032
- this.state.top = true;
4033
- return tokens;
4034
- }
4035
- inline(src, tokens = []) {
4036
- this.inlineQueue.push({
4037
- src,
4038
- tokens
4039
- });
4040
- return tokens;
4041
- }
4042
- /**
4043
- * Lexing/Compiling
4044
- */
4045
- inlineTokens(src, tokens = []) {
4046
- // String with links masked to avoid interference with em and strong
4047
- let maskedSrc = src;
4048
- let match = null;
4049
- // Mask out reflinks
4050
- if (this.tokens.links) {
4051
- const links = Object.keys(this.tokens.links);
4052
- if (links.length > 0) {
4053
- while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) {
4054
- if (links.includes(match[0].slice(match[0].lastIndexOf('[') + 1, -1))) {
4055
- maskedSrc = maskedSrc.slice(0, match.index) + '[' + 'a'.repeat(match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex);
4056
- }
4057
- }
4058
- }
4059
- }
4060
- // Mask out other blocks
4061
- while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) {
4062
- maskedSrc = maskedSrc.slice(0, match.index) + '[' + 'a'.repeat(match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
4063
- }
4064
- // Mask out escaped characters
4065
- while ((match = this.tokenizer.rules.inline.anyPunctuation.exec(maskedSrc)) != null) {
4066
- maskedSrc = maskedSrc.slice(0, match.index) + '++' + maskedSrc.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);
4067
- }
4068
- let keepPrevChar = false;
4069
- let prevChar = '';
4070
- while (src) {
4071
- if (!keepPrevChar) {
4072
- prevChar = '';
4073
- }
4074
- keepPrevChar = false;
4075
- let token;
4076
- // extensions
4077
- if (this.options.extensions?.inline?.some(extTokenizer => {
4078
- if (token = extTokenizer.call({
4079
- lexer: this
4080
- }, src, tokens)) {
4081
- src = src.substring(token.raw.length);
4082
- tokens.push(token);
4083
- return true;
4084
- }
4085
- return false;
4086
- })) {
4087
- continue;
4088
- }
4089
- // escape
4090
- if (token = this.tokenizer.escape(src)) {
4091
- src = src.substring(token.raw.length);
4092
- tokens.push(token);
4093
- continue;
4094
- }
4095
- // tag
4096
- if (token = this.tokenizer.tag(src)) {
4097
- src = src.substring(token.raw.length);
4098
- tokens.push(token);
4099
- continue;
4100
- }
4101
- // link
4102
- if (token = this.tokenizer.link(src)) {
4103
- src = src.substring(token.raw.length);
4104
- tokens.push(token);
4105
- continue;
4106
- }
4107
- // reflink, nolink
4108
- if (token = this.tokenizer.reflink(src, this.tokens.links)) {
4109
- src = src.substring(token.raw.length);
4110
- const lastToken = tokens.at(-1);
4111
- if (token.type === 'text' && lastToken?.type === 'text') {
4112
- lastToken.raw += token.raw;
4113
- lastToken.text += token.text;
4114
- } else {
4115
- tokens.push(token);
4116
- }
4117
- continue;
4118
- }
4119
- // em & strong
4120
- if (token = this.tokenizer.emStrong(src, maskedSrc, prevChar)) {
4121
- src = src.substring(token.raw.length);
4122
- tokens.push(token);
4123
- continue;
4124
- }
4125
- // code
4126
- if (token = this.tokenizer.codespan(src)) {
4127
- src = src.substring(token.raw.length);
4128
- tokens.push(token);
4129
- continue;
4130
- }
4131
- // br
4132
- if (token = this.tokenizer.br(src)) {
4133
- src = src.substring(token.raw.length);
4134
- tokens.push(token);
4135
- continue;
4136
- }
4137
- // del (gfm)
4138
- if (token = this.tokenizer.del(src)) {
4139
- src = src.substring(token.raw.length);
4140
- tokens.push(token);
4141
- continue;
4142
- }
4143
- // autolink
4144
- if (token = this.tokenizer.autolink(src)) {
4145
- src = src.substring(token.raw.length);
4146
- tokens.push(token);
4147
- continue;
4148
- }
4149
- // url (gfm)
4150
- if (!this.state.inLink && (token = this.tokenizer.url(src))) {
4151
- src = src.substring(token.raw.length);
4152
- tokens.push(token);
4153
- continue;
4154
- }
4155
- // text
4156
- // prevent inlineText consuming extensions by clipping 'src' to extension start
4157
- let cutSrc = src;
4158
- if (this.options.extensions?.startInline) {
4159
- let startIndex = Infinity;
4160
- const tempSrc = src.slice(1);
4161
- let tempStart;
4162
- this.options.extensions.startInline.forEach(getStartIndex => {
4163
- tempStart = getStartIndex.call({
4164
- lexer: this
4165
- }, tempSrc);
4166
- if (typeof tempStart === 'number' && tempStart >= 0) {
4167
- startIndex = Math.min(startIndex, tempStart);
4168
- }
4169
- });
4170
- if (startIndex < Infinity && startIndex >= 0) {
4171
- cutSrc = src.substring(0, startIndex + 1);
4172
- }
4173
- }
4174
- if (token = this.tokenizer.inlineText(cutSrc)) {
4175
- src = src.substring(token.raw.length);
4176
- if (token.raw.slice(-1) !== '_') {
4177
- // Track prevChar before string of ____ started
4178
- prevChar = token.raw.slice(-1);
4179
- }
4180
- keepPrevChar = true;
4181
- const lastToken = tokens.at(-1);
4182
- if (lastToken?.type === 'text') {
4183
- lastToken.raw += token.raw;
4184
- lastToken.text += token.text;
4185
- } else {
4186
- tokens.push(token);
4187
- }
4188
- continue;
4189
- }
4190
- if (src) {
4191
- const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);
4192
- if (this.options.silent) {
4193
- console.error(errMsg);
4194
- break;
4195
- } else {
4196
- throw new Error(errMsg);
4197
- }
4198
- }
4199
- }
4200
- return tokens;
4201
- }
4202
- }
4203
-
4204
- /**
4205
- * Renderer
4206
- */
4207
- class _Renderer {
4208
- options;
4209
- parser; // set by the parser
4210
- constructor(options) {
4211
- this.options = options || _defaults;
4212
- }
4213
- space(token) {
4214
- return '';
4215
- }
4216
- code({
4217
- text,
4218
- lang,
4219
- escaped
4220
- }) {
4221
- const langString = (lang || '').match(other.notSpaceStart)?.[0];
4222
- const code = text.replace(other.endingNewline, '') + '\n';
4223
- if (!langString) {
4224
- return '<pre><code>' + (escaped ? code : escape(code, true)) + '</code></pre>\n';
4225
- }
4226
- return '<pre><code class="language-' + escape(langString) + '">' + (escaped ? code : escape(code, true)) + '</code></pre>\n';
4227
- }
4228
- blockquote({
4229
- tokens
4230
- }) {
4231
- const body = this.parser.parse(tokens);
4232
- return `<blockquote>\n${body}</blockquote>\n`;
4233
- }
4234
- html({
4235
- text
4236
- }) {
4237
- return text;
4238
- }
4239
- heading({
4240
- tokens,
4241
- depth
4242
- }) {
4243
- return `<h${depth}>${this.parser.parseInline(tokens)}</h${depth}>\n`;
4244
- }
4245
- hr(token) {
4246
- return '<hr>\n';
4247
- }
4248
- list(token) {
4249
- const ordered = token.ordered;
4250
- const start = token.start;
4251
- let body = '';
4252
- for (let j = 0; j < token.items.length; j++) {
4253
- const item = token.items[j];
4254
- body += this.listitem(item);
4255
- }
4256
- const type = ordered ? 'ol' : 'ul';
4257
- const startAttr = ordered && start !== 1 ? ' start="' + start + '"' : '';
4258
- return '<' + type + startAttr + '>\n' + body + '</' + type + '>\n';
4259
- }
4260
- listitem(item) {
4261
- let itemBody = '';
4262
- if (item.task) {
4263
- const checkbox = this.checkbox({
4264
- checked: !!item.checked
4265
- });
4266
- if (item.loose) {
4267
- if (item.tokens[0]?.type === 'paragraph') {
4268
- item.tokens[0].text = checkbox + ' ' + item.tokens[0].text;
4269
- if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') {
4270
- item.tokens[0].tokens[0].text = checkbox + ' ' + escape(item.tokens[0].tokens[0].text);
4271
- item.tokens[0].tokens[0].escaped = true;
4272
- }
4273
- } else {
4274
- item.tokens.unshift({
4275
- type: 'text',
4276
- raw: checkbox + ' ',
4277
- text: checkbox + ' ',
4278
- escaped: true
4279
- });
4280
- }
4281
- } else {
4282
- itemBody += checkbox + ' ';
4283
- }
4284
- }
4285
- itemBody += this.parser.parse(item.tokens, !!item.loose);
4286
- return `<li>${itemBody}</li>\n`;
4287
- }
4288
- checkbox({
4289
- checked
4290
- }) {
4291
- return '<input ' + (checked ? 'checked="" ' : '') + 'disabled="" type="checkbox">';
4292
- }
4293
- paragraph({
4294
- tokens
4295
- }) {
4296
- return `<p>${this.parser.parseInline(tokens)}</p>\n`;
4297
- }
4298
- table(token) {
4299
- let header = '';
4300
- // header
4301
- let cell = '';
4302
- for (let j = 0; j < token.header.length; j++) {
4303
- cell += this.tablecell(token.header[j]);
4304
- }
4305
- header += this.tablerow({
4306
- text: cell
4307
- });
4308
- let body = '';
4309
- for (let j = 0; j < token.rows.length; j++) {
4310
- const row = token.rows[j];
4311
- cell = '';
4312
- for (let k = 0; k < row.length; k++) {
4313
- cell += this.tablecell(row[k]);
4314
- }
4315
- body += this.tablerow({
4316
- text: cell
4317
- });
4318
- }
4319
- if (body) body = `<tbody>${body}</tbody>`;
4320
- return '<table>\n' + '<thead>\n' + header + '</thead>\n' + body + '</table>\n';
4321
- }
4322
- tablerow({
4323
- text
4324
- }) {
4325
- return `<tr>\n${text}</tr>\n`;
4326
- }
4327
- tablecell(token) {
4328
- const content = this.parser.parseInline(token.tokens);
4329
- const type = token.header ? 'th' : 'td';
4330
- const tag = token.align ? `<${type} align="${token.align}">` : `<${type}>`;
4331
- return tag + content + `</${type}>\n`;
4332
- }
4333
- /**
4334
- * span level renderer
4335
- */
4336
- strong({
4337
- tokens
4338
- }) {
4339
- return `<strong>${this.parser.parseInline(tokens)}</strong>`;
4340
- }
4341
- em({
4342
- tokens
4343
- }) {
4344
- return `<em>${this.parser.parseInline(tokens)}</em>`;
4345
- }
4346
- codespan({
4347
- text
4348
- }) {
4349
- return `<code>${escape(text, true)}</code>`;
4350
- }
4351
- br(token) {
4352
- return '<br>';
4353
- }
4354
- del({
4355
- tokens
4356
- }) {
4357
- return `<del>${this.parser.parseInline(tokens)}</del>`;
4358
- }
4359
- link({
4360
- href,
4361
- title,
4362
- tokens
4363
- }) {
4364
- const text = this.parser.parseInline(tokens);
4365
- const cleanHref = cleanUrl(href);
4366
- if (cleanHref === null) {
4367
- return text;
4368
- }
4369
- href = cleanHref;
4370
- let out = '<a href="' + href + '"';
4371
- if (title) {
4372
- out += ' title="' + escape(title) + '"';
4373
- }
4374
- out += '>' + text + '</a>';
4375
- return out;
4376
- }
4377
- image({
4378
- href,
4379
- title,
4380
- text
4381
- }) {
4382
- const cleanHref = cleanUrl(href);
4383
- if (cleanHref === null) {
4384
- return escape(text);
4385
- }
4386
- href = cleanHref;
4387
- let out = `<img src="${href}" alt="${text}"`;
4388
- if (title) {
4389
- out += ` title="${escape(title)}"`;
4390
- }
4391
- out += '>';
4392
- return out;
4393
- }
4394
- text(token) {
4395
- return 'tokens' in token && token.tokens ? this.parser.parseInline(token.tokens) : 'escaped' in token && token.escaped ? token.text : escape(token.text);
4396
- }
4397
- }
4398
-
4399
- /**
4400
- * TextRenderer
4401
- * returns only the textual part of the token
4402
- */
4403
- class _TextRenderer {
4404
- // no need for block level renderers
4405
- strong({
4406
- text
4407
- }) {
4408
- return text;
4409
- }
4410
- em({
4411
- text
4412
- }) {
4413
- return text;
4414
- }
4415
- codespan({
4416
- text
4417
- }) {
4418
- return text;
4419
- }
4420
- del({
4421
- text
4422
- }) {
4423
- return text;
4424
- }
4425
- html({
4426
- text
4427
- }) {
4428
- return text;
4429
- }
4430
- text({
4431
- text
4432
- }) {
4433
- return text;
4434
- }
4435
- link({
4436
- text
4437
- }) {
4438
- return '' + text;
4439
- }
4440
- image({
4441
- text
4442
- }) {
4443
- return '' + text;
4444
- }
4445
- br() {
4446
- return '';
4447
- }
4448
- }
4449
-
4450
- /**
4451
- * Parsing & Compiling
4452
- */
4453
- class _Parser {
4454
- options;
4455
- renderer;
4456
- textRenderer;
4457
- constructor(options) {
4458
- this.options = options || _defaults;
4459
- this.options.renderer = this.options.renderer || new _Renderer();
4460
- this.renderer = this.options.renderer;
4461
- this.renderer.options = this.options;
4462
- this.renderer.parser = this;
4463
- this.textRenderer = new _TextRenderer();
4464
- }
4465
- /**
4466
- * Static Parse Method
4467
- */
4468
- static parse(tokens, options) {
4469
- const parser = new _Parser(options);
4470
- return parser.parse(tokens);
4471
- }
4472
- /**
4473
- * Static Parse Inline Method
4474
- */
4475
- static parseInline(tokens, options) {
4476
- const parser = new _Parser(options);
4477
- return parser.parseInline(tokens);
4478
- }
4479
- /**
4480
- * Parse Loop
4481
- */
4482
- parse(tokens, top = true) {
4483
- let out = '';
4484
- for (let i = 0; i < tokens.length; i++) {
4485
- const anyToken = tokens[i];
4486
- // Run any renderer extensions
4487
- if (this.options.extensions?.renderers?.[anyToken.type]) {
4488
- const genericToken = anyToken;
4489
- const ret = this.options.extensions.renderers[genericToken.type].call({
4490
- parser: this
4491
- }, genericToken);
4492
- if (ret !== false || !['space', 'hr', 'heading', 'code', 'table', 'blockquote', 'list', 'html', 'paragraph', 'text'].includes(genericToken.type)) {
4493
- out += ret || '';
4494
- continue;
4495
- }
4496
- }
4497
- const token = anyToken;
4498
- switch (token.type) {
4499
- case 'space':
4500
- {
4501
- out += this.renderer.space(token);
4502
- continue;
4503
- }
4504
- case 'hr':
4505
- {
4506
- out += this.renderer.hr(token);
4507
- continue;
4508
- }
4509
- case 'heading':
4510
- {
4511
- out += this.renderer.heading(token);
4512
- continue;
4513
- }
4514
- case 'code':
4515
- {
4516
- out += this.renderer.code(token);
4517
- continue;
4518
- }
4519
- case 'table':
4520
- {
4521
- out += this.renderer.table(token);
4522
- continue;
4523
- }
4524
- case 'blockquote':
4525
- {
4526
- out += this.renderer.blockquote(token);
4527
- continue;
4528
- }
4529
- case 'list':
4530
- {
4531
- out += this.renderer.list(token);
4532
- continue;
4533
- }
4534
- case 'html':
4535
- {
4536
- out += this.renderer.html(token);
4537
- continue;
4538
- }
4539
- case 'paragraph':
4540
- {
4541
- out += this.renderer.paragraph(token);
4542
- continue;
4543
- }
4544
- case 'text':
4545
- {
4546
- let textToken = token;
4547
- let body = this.renderer.text(textToken);
4548
- while (i + 1 < tokens.length && tokens[i + 1].type === 'text') {
4549
- textToken = tokens[++i];
4550
- body += '\n' + this.renderer.text(textToken);
4551
- }
4552
- if (top) {
4553
- out += this.renderer.paragraph({
4554
- type: 'paragraph',
4555
- raw: body,
4556
- text: body,
4557
- tokens: [{
4558
- type: 'text',
4559
- raw: body,
4560
- text: body,
4561
- escaped: true
4562
- }]
4563
- });
4564
- } else {
4565
- out += body;
4566
- }
4567
- continue;
4568
- }
4569
- default:
4570
- {
4571
- const errMsg = 'Token with "' + token.type + '" type was not found.';
4572
- if (this.options.silent) {
4573
- console.error(errMsg);
4574
- return '';
4575
- } else {
4576
- throw new Error(errMsg);
4577
- }
4578
- }
4579
- }
4580
- }
4581
- return out;
4582
- }
4583
- /**
4584
- * Parse Inline Tokens
4585
- */
4586
- parseInline(tokens, renderer = this.renderer) {
4587
- let out = '';
4588
- for (let i = 0; i < tokens.length; i++) {
4589
- const anyToken = tokens[i];
4590
- // Run any renderer extensions
4591
- if (this.options.extensions?.renderers?.[anyToken.type]) {
4592
- const ret = this.options.extensions.renderers[anyToken.type].call({
4593
- parser: this
4594
- }, anyToken);
4595
- if (ret !== false || !['escape', 'html', 'link', 'image', 'strong', 'em', 'codespan', 'br', 'del', 'text'].includes(anyToken.type)) {
4596
- out += ret || '';
4597
- continue;
4598
- }
4599
- }
4600
- const token = anyToken;
4601
- switch (token.type) {
4602
- case 'escape':
4603
- {
4604
- out += renderer.text(token);
4605
- break;
4606
- }
4607
- case 'html':
4608
- {
4609
- out += renderer.html(token);
4610
- break;
4611
- }
4612
- case 'link':
4613
- {
4614
- out += renderer.link(token);
4615
- break;
4616
- }
4617
- case 'image':
4618
- {
4619
- out += renderer.image(token);
4620
- break;
4621
- }
4622
- case 'strong':
4623
- {
4624
- out += renderer.strong(token);
4625
- break;
4626
- }
4627
- case 'em':
4628
- {
4629
- out += renderer.em(token);
4630
- break;
4631
- }
4632
- case 'codespan':
4633
- {
4634
- out += renderer.codespan(token);
4635
- break;
4636
- }
4637
- case 'br':
4638
- {
4639
- out += renderer.br(token);
4640
- break;
4641
- }
4642
- case 'del':
4643
- {
4644
- out += renderer.del(token);
4645
- break;
4646
- }
4647
- case 'text':
4648
- {
4649
- out += renderer.text(token);
4650
- break;
4651
- }
4652
- default:
4653
- {
4654
- const errMsg = 'Token with "' + token.type + '" type was not found.';
4655
- if (this.options.silent) {
4656
- console.error(errMsg);
4657
- return '';
4658
- } else {
4659
- throw new Error(errMsg);
4660
- }
4661
- }
4662
- }
4663
- }
4664
- return out;
4665
- }
4666
- }
4667
- class _Hooks {
4668
- options;
4669
- block;
4670
- constructor(options) {
4671
- this.options = options || _defaults;
4672
- }
4673
- static passThroughHooks = new Set(['preprocess', 'postprocess', 'processAllTokens']);
4674
- /**
4675
- * Process markdown before marked
4676
- */
4677
- preprocess(markdown) {
4678
- return markdown;
4679
- }
4680
- /**
4681
- * Process HTML after marked is finished
4682
- */
4683
- postprocess(html) {
4684
- return html;
4685
- }
4686
- /**
4687
- * Process all tokens before walk tokens
4688
- */
4689
- processAllTokens(tokens) {
4690
- return tokens;
4691
- }
4692
- /**
4693
- * Provide function to tokenize markdown
4694
- */
4695
- provideLexer() {
4696
- return this.block ? _Lexer.lex : _Lexer.lexInline;
4697
- }
4698
- /**
4699
- * Provide function to parse tokens
4700
- */
4701
- provideParser() {
4702
- return this.block ? _Parser.parse : _Parser.parseInline;
4703
- }
4704
- }
4705
- class Marked {
4706
- defaults = _getDefaults();
4707
- options = this.setOptions;
4708
- parse = this.parseMarkdown(true);
4709
- parseInline = this.parseMarkdown(false);
4710
- Parser = _Parser;
4711
- Renderer = _Renderer;
4712
- TextRenderer = _TextRenderer;
4713
- Lexer = _Lexer;
4714
- Tokenizer = _Tokenizer;
4715
- Hooks = _Hooks;
4716
- constructor(...args) {
4717
- this.use(...args);
4718
- }
4719
- /**
4720
- * Run callback for every token
4721
- */
4722
- walkTokens(tokens, callback) {
4723
- let values = [];
4724
- for (const token of tokens) {
4725
- values = values.concat(callback.call(this, token));
4726
- switch (token.type) {
4727
- case 'table':
4728
- {
4729
- const tableToken = token;
4730
- for (const cell of tableToken.header) {
4731
- values = values.concat(this.walkTokens(cell.tokens, callback));
4732
- }
4733
- for (const row of tableToken.rows) {
4734
- for (const cell of row) {
4735
- values = values.concat(this.walkTokens(cell.tokens, callback));
4736
- }
4737
- }
4738
- break;
4739
- }
4740
- case 'list':
4741
- {
4742
- const listToken = token;
4743
- values = values.concat(this.walkTokens(listToken.items, callback));
4744
- break;
4745
- }
4746
- default:
4747
- {
4748
- const genericToken = token;
4749
- if (this.defaults.extensions?.childTokens?.[genericToken.type]) {
4750
- this.defaults.extensions.childTokens[genericToken.type].forEach(childTokens => {
4751
- const tokens = genericToken[childTokens].flat(Infinity);
4752
- values = values.concat(this.walkTokens(tokens, callback));
4753
- });
4754
- } else if (genericToken.tokens) {
4755
- values = values.concat(this.walkTokens(genericToken.tokens, callback));
4756
- }
4757
- }
4758
- }
4759
- }
4760
- return values;
4761
- }
4762
- use(...args) {
4763
- const extensions = this.defaults.extensions || {
4764
- renderers: {},
4765
- childTokens: {}
4766
- };
4767
- args.forEach(pack => {
4768
- // copy options to new object
4769
- const opts = {
4770
- ...pack
4771
- };
4772
- // set async to true if it was set to true before
4773
- opts.async = this.defaults.async || opts.async || false;
4774
- // ==-- Parse "addon" extensions --== //
4775
- if (pack.extensions) {
4776
- pack.extensions.forEach(ext => {
4777
- if (!ext.name) {
4778
- throw new Error('extension name required');
4779
- }
4780
- if ('renderer' in ext) {
4781
- // Renderer extensions
4782
- const prevRenderer = extensions.renderers[ext.name];
4783
- if (prevRenderer) {
4784
- // Replace extension with func to run new extension but fall back if false
4785
- extensions.renderers[ext.name] = function (...args) {
4786
- let ret = ext.renderer.apply(this, args);
4787
- if (ret === false) {
4788
- ret = prevRenderer.apply(this, args);
4789
- }
4790
- return ret;
4791
- };
4792
- } else {
4793
- extensions.renderers[ext.name] = ext.renderer;
4794
- }
4795
- }
4796
- if ('tokenizer' in ext) {
4797
- // Tokenizer Extensions
4798
- if (!ext.level || ext.level !== 'block' && ext.level !== 'inline') {
4799
- throw new Error("extension level must be 'block' or 'inline'");
4800
- }
4801
- const extLevel = extensions[ext.level];
4802
- if (extLevel) {
4803
- extLevel.unshift(ext.tokenizer);
4804
- } else {
4805
- extensions[ext.level] = [ext.tokenizer];
4806
- }
4807
- if (ext.start) {
4808
- // Function to check for start of token
4809
- if (ext.level === 'block') {
4810
- if (extensions.startBlock) {
4811
- extensions.startBlock.push(ext.start);
4812
- } else {
4813
- extensions.startBlock = [ext.start];
4814
- }
4815
- } else if (ext.level === 'inline') {
4816
- if (extensions.startInline) {
4817
- extensions.startInline.push(ext.start);
4818
- } else {
4819
- extensions.startInline = [ext.start];
4820
- }
4821
- }
4822
- }
4823
- }
4824
- if ('childTokens' in ext && ext.childTokens) {
4825
- // Child tokens to be visited by walkTokens
4826
- extensions.childTokens[ext.name] = ext.childTokens;
4827
- }
4828
- });
4829
- opts.extensions = extensions;
4830
- }
4831
- // ==-- Parse "overwrite" extensions --== //
4832
- if (pack.renderer) {
4833
- const renderer = this.defaults.renderer || new _Renderer(this.defaults);
4834
- for (const prop in pack.renderer) {
4835
- if (!(prop in renderer)) {
4836
- throw new Error(`renderer '${prop}' does not exist`);
4837
- }
4838
- if (['options', 'parser'].includes(prop)) {
4839
- // ignore options property
4840
- continue;
4841
- }
4842
- const rendererProp = prop;
4843
- const rendererFunc = pack.renderer[rendererProp];
4844
- const prevRenderer = renderer[rendererProp];
4845
- // Replace renderer with func to run extension, but fall back if false
4846
- renderer[rendererProp] = (...args) => {
4847
- let ret = rendererFunc.apply(renderer, args);
4848
- if (ret === false) {
4849
- ret = prevRenderer.apply(renderer, args);
4850
- }
4851
- return ret || '';
4852
- };
4853
- }
4854
- opts.renderer = renderer;
4855
- }
4856
- if (pack.tokenizer) {
4857
- const tokenizer = this.defaults.tokenizer || new _Tokenizer(this.defaults);
4858
- for (const prop in pack.tokenizer) {
4859
- if (!(prop in tokenizer)) {
4860
- throw new Error(`tokenizer '${prop}' does not exist`);
4861
- }
4862
- if (['options', 'rules', 'lexer'].includes(prop)) {
4863
- // ignore options, rules, and lexer properties
4864
- continue;
4865
- }
4866
- const tokenizerProp = prop;
4867
- const tokenizerFunc = pack.tokenizer[tokenizerProp];
4868
- const prevTokenizer = tokenizer[tokenizerProp];
4869
- // Replace tokenizer with func to run extension, but fall back if false
4870
- // @ts-expect-error cannot type tokenizer function dynamically
4871
- tokenizer[tokenizerProp] = (...args) => {
4872
- let ret = tokenizerFunc.apply(tokenizer, args);
4873
- if (ret === false) {
4874
- ret = prevTokenizer.apply(tokenizer, args);
4875
- }
4876
- return ret;
4877
- };
4878
- }
4879
- opts.tokenizer = tokenizer;
4880
- }
4881
- // ==-- Parse Hooks extensions --== //
4882
- if (pack.hooks) {
4883
- const hooks = this.defaults.hooks || new _Hooks();
4884
- for (const prop in pack.hooks) {
4885
- if (!(prop in hooks)) {
4886
- throw new Error(`hook '${prop}' does not exist`);
4887
- }
4888
- if (['options', 'block'].includes(prop)) {
4889
- // ignore options and block properties
4890
- continue;
4891
- }
4892
- const hooksProp = prop;
4893
- const hooksFunc = pack.hooks[hooksProp];
4894
- const prevHook = hooks[hooksProp];
4895
- if (_Hooks.passThroughHooks.has(prop)) {
4896
- // @ts-expect-error cannot type hook function dynamically
4897
- hooks[hooksProp] = arg => {
4898
- if (this.defaults.async) {
4899
- return Promise.resolve(hooksFunc.call(hooks, arg)).then(ret => {
4900
- return prevHook.call(hooks, ret);
4901
- });
4902
- }
4903
- const ret = hooksFunc.call(hooks, arg);
4904
- return prevHook.call(hooks, ret);
4905
- };
4906
- } else {
4907
- // @ts-expect-error cannot type hook function dynamically
4908
- hooks[hooksProp] = (...args) => {
4909
- let ret = hooksFunc.apply(hooks, args);
4910
- if (ret === false) {
4911
- ret = prevHook.apply(hooks, args);
4912
- }
4913
- return ret;
4914
- };
4915
- }
4916
- }
4917
- opts.hooks = hooks;
4918
- }
4919
- // ==-- Parse WalkTokens extensions --== //
4920
- if (pack.walkTokens) {
4921
- const walkTokens = this.defaults.walkTokens;
4922
- const packWalktokens = pack.walkTokens;
4923
- opts.walkTokens = function (token) {
4924
- let values = [];
4925
- values.push(packWalktokens.call(this, token));
4926
- if (walkTokens) {
4927
- values = values.concat(walkTokens.call(this, token));
4928
- }
4929
- return values;
4930
- };
4931
- }
4932
- this.defaults = {
4933
- ...this.defaults,
4934
- ...opts
4935
- };
4936
- });
4937
- return this;
4938
- }
4939
- setOptions(opt) {
4940
- this.defaults = {
4941
- ...this.defaults,
4942
- ...opt
4943
- };
4944
- return this;
4945
- }
4946
- lexer(src, options) {
4947
- return _Lexer.lex(src, options ?? this.defaults);
4948
- }
4949
- parser(tokens, options) {
4950
- return _Parser.parse(tokens, options ?? this.defaults);
4951
- }
4952
- parseMarkdown(blockType) {
4953
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
4954
- const parse = (src, options) => {
4955
- const origOpt = {
4956
- ...options
4957
- };
4958
- const opt = {
4959
- ...this.defaults,
4960
- ...origOpt
4961
- };
4962
- const throwError = this.onError(!!opt.silent, !!opt.async);
4963
- // throw error if an extension set async to true but parse was called with async: false
4964
- if (this.defaults.async === true && origOpt.async === false) {
4965
- 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.'));
4966
- }
4967
- // throw error in case of non string input
4968
- if (typeof src === 'undefined' || src === null) {
4969
- return throwError(new Error('marked(): input parameter is undefined or null'));
4970
- }
4971
- if (typeof src !== 'string') {
4972
- return throwError(new Error('marked(): input parameter is of type ' + Object.prototype.toString.call(src) + ', string expected'));
4973
- }
4974
- if (opt.hooks) {
4975
- opt.hooks.options = opt;
4976
- opt.hooks.block = blockType;
4977
- }
4978
- const lexer = opt.hooks ? opt.hooks.provideLexer() : blockType ? _Lexer.lex : _Lexer.lexInline;
4979
- const parser = opt.hooks ? opt.hooks.provideParser() : blockType ? _Parser.parse : _Parser.parseInline;
4980
- if (opt.async) {
4981
- 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);
4982
- }
4983
- try {
4984
- if (opt.hooks) {
4985
- src = opt.hooks.preprocess(src);
4986
- }
4987
- let tokens = lexer(src, opt);
4988
- if (opt.hooks) {
4989
- tokens = opt.hooks.processAllTokens(tokens);
4990
- }
4991
- if (opt.walkTokens) {
4992
- this.walkTokens(tokens, opt.walkTokens);
4993
- }
4994
- let html = parser(tokens, opt);
4995
- if (opt.hooks) {
4996
- html = opt.hooks.postprocess(html);
4997
- }
4998
- return html;
4999
- } catch (e) {
5000
- return throwError(e);
5001
- }
5002
- };
5003
- return parse;
5004
- }
5005
- onError(silent, async) {
5006
- return e => {
5007
- e.message += '\nPlease report this to https://github.com/markedjs/marked.';
5008
- if (silent) {
5009
- const msg = '<p>An error occurred:</p><pre>' + escape(e.message + '', true) + '</pre>';
5010
- if (async) {
5011
- return Promise.resolve(msg);
5012
- }
5013
- return msg;
5014
- }
5015
- if (async) {
5016
- return Promise.reject(e);
5017
- }
5018
- throw e;
5019
- };
5020
- }
5021
- }
5022
- const markedInstance = new Marked();
5023
- function marked(src, opt) {
5024
- return markedInstance.parse(src, opt);
5025
- }
5026
- /**
5027
- * Sets the default options.
5028
- *
5029
- * @param options Hash of options
5030
- */
5031
- marked.options = marked.setOptions = function (options) {
5032
- markedInstance.setOptions(options);
5033
- marked.defaults = markedInstance.defaults;
5034
- changeDefaults(marked.defaults);
5035
- return marked;
5036
- };
5037
- /**
5038
- * Gets the original marked default options.
5039
- */
5040
- marked.getDefaults = _getDefaults;
5041
- marked.defaults = _defaults;
5042
- /**
5043
- * Use Extension
5044
- */
5045
- marked.use = function (...args) {
5046
- markedInstance.use(...args);
5047
- marked.defaults = markedInstance.defaults;
5048
- changeDefaults(marked.defaults);
5049
- return marked;
5050
- };
5051
- /**
5052
- * Run callback for every token
5053
- */
5054
- marked.walkTokens = function (tokens, callback) {
5055
- return markedInstance.walkTokens(tokens, callback);
5056
- };
5057
- /**
5058
- * Compiles markdown to HTML without enclosing `p` tag.
5059
- *
5060
- * @param src String of markdown source to be compiled
5061
- * @param options Hash of options
5062
- * @return String of compiled HTML
5063
- */
5064
- marked.parseInline = markedInstance.parseInline;
5065
- /**
5066
- * Expose
5067
- */
5068
- marked.Parser = _Parser;
5069
- marked.parser = _Parser.parse;
5070
- marked.Renderer = _Renderer;
5071
- marked.TextRenderer = _TextRenderer;
5072
- marked.Lexer = _Lexer;
5073
- marked.lexer = _Lexer.lex;
5074
- marked.Tokenizer = _Tokenizer;
5075
- marked.Hooks = _Hooks;
5076
- marked.parse = marked;
5077
-
5078
2129
  const renderMarkdown = async (markdown, options = {}) => {
5079
- const html = await marked(markdown, {});
2130
+ const html = await invoke('Markdown.renderMarkdown', markdown, options);
5080
2131
  return html;
5081
2132
  };
5082
2133
 
@@ -5426,11 +2477,7 @@ const commandMap = {
5426
2477
  'ExtensionDetail.resize': resize,
5427
2478
  'ExtensionDetail.saveState': saveState,
5428
2479
  'ExtensionDetail.selectTab': wrapCommand(selectTab),
5429
- 'ExtensionDetail.terminate': terminate,
5430
- // deprecated
5431
- 'ExtensionDetail.getVirtualDom': wrapCommand(getExtensionDetailVirtualDom),
5432
- 'HandleIconError.handleIconError': handleIconError,
5433
- 'RenderMarkdown.renderMarkdown': renderMarkdown
2480
+ 'ExtensionDetail.terminate': terminate
5434
2481
  };
5435
2482
 
5436
2483
  const listen = async () => {