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