@khanacademy/simple-markdown 0.0.0-PR443-20230328215601

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.
@@ -0,0 +1,1582 @@
1
+ /* eslint-disable prefer-spread, no-regex-spaces, @typescript-eslint/no-unused-vars, guard-for-in, no-console, no-var */
2
+ /**
3
+ * Simple-Markdown
4
+ * ===============
5
+ *
6
+ * Simple-Markdown's primary goal is to be easy to adapt. It aims
7
+ * to be compliant with John Gruber's [Markdown Syntax page][1],
8
+ * but compatiblity with other markdown implementations' edge-cases
9
+ * will be sacrificed where it conflicts with simplicity or
10
+ * extensibility.
11
+ *
12
+ * If your goal is to simply embed a standard markdown implementation
13
+ * in your website, simple-markdown is probably not the best library
14
+ * for you (although it should work). But if you have struggled to
15
+ * customize an existing library to meet your needs, simple-markdown
16
+ * might be able to help.
17
+ *
18
+ * Many of the regexes and original logic has been adapted from
19
+ * the wonderful [marked.js](https://github.com/chjj/marked)
20
+ */
21
+
22
+ // Type Definitions:
23
+
24
+ // We want to clarify our defaultRules types a little bit more so clients can
25
+ // reuse defaultRules built-ins. So we make some stronger guarantess when
26
+ // we can:
27
+
28
+ // End Flow Definitions
29
+
30
+ var CR_NEWLINE_R = /\r\n?/g;
31
+ var TAB_R = /\t/g;
32
+ var FORMFEED_R = /\f/g;
33
+
34
+ /**
35
+ * Turn various whitespace into easy-to-process whitespace
36
+ */
37
+ var preprocess = function preprocess(source) {
38
+ return source.replace(CR_NEWLINE_R, "\n").replace(FORMFEED_R, "").replace(TAB_R, " ");
39
+ };
40
+ var populateInitialState = function populateInitialState(givenState, defaultState) {
41
+ var state = givenState || {};
42
+ if (defaultState != null) {
43
+ for (var prop in defaultState) {
44
+ if (Object.prototype.hasOwnProperty.call(defaultState, prop)) {
45
+ state[prop] = defaultState[prop];
46
+ }
47
+ }
48
+ }
49
+ return state;
50
+ };
51
+
52
+ /**
53
+ * Creates a parser for a given set of rules, with the precedence
54
+ * specified as a list of rules.
55
+ *
56
+ * @param {SimpleMarkdown.ParserRules} rules
57
+ * an object containing
58
+ * rule type -> {match, order, parse} objects
59
+ * (lower order is higher precedence)
60
+ * @param {SimpleMarkdown.OptionalState} [defaultState]
61
+ *
62
+ * @returns {SimpleMarkdown.Parser}
63
+ * The resulting parse function, with the following parameters:
64
+ * @source: the input source string to be parsed
65
+ * @state: an optional object to be threaded through parse
66
+ * calls. Allows clients to add stateful operations to
67
+ * parsing, such as keeping track of how many levels deep
68
+ * some nesting is. For an example use-case, see passage-ref
69
+ * parsing in src/widgets/passage/passage-markdown.jsx
70
+ */
71
+ var parserFor = function parserFor(rules, defaultState) {
72
+ // Sorts rules in order of increasing order, then
73
+ // ascending rule name in case of ties.
74
+ var ruleList = Object.keys(rules).filter(function (type) {
75
+ var rule = rules[type];
76
+ if (rule == null || rule.match == null) {
77
+ return false;
78
+ }
79
+ var order = rule.order;
80
+ if ((typeof order !== "number" || !isFinite(order)) && typeof console !== "undefined") {
81
+ console.warn("simple-markdown: Invalid order for rule `" + type + "`: " + String(order));
82
+ }
83
+ return true;
84
+ });
85
+ ruleList.sort(function (typeA, typeB) {
86
+ var ruleA = rules[typeA];
87
+ var ruleB = rules[typeB];
88
+ var orderA = ruleA.order;
89
+ var orderB = ruleB.order;
90
+
91
+ // First sort based on increasing order
92
+ if (orderA !== orderB) {
93
+ return orderA - orderB;
94
+ }
95
+ var secondaryOrderA = ruleA.quality ? 0 : 1;
96
+ var secondaryOrderB = ruleB.quality ? 0 : 1;
97
+ if (secondaryOrderA !== secondaryOrderB) {
98
+ return secondaryOrderA - secondaryOrderB;
99
+
100
+ // Then based on increasing unicode lexicographic ordering
101
+ } else if (typeA < typeB) {
102
+ return -1;
103
+ } else if (typeA > typeB) {
104
+ return 1;
105
+ } else {
106
+ // Rules should never have the same name,
107
+ // but this is provided for completeness.
108
+ return 0;
109
+ }
110
+ });
111
+ var latestState;
112
+ var nestedParse = function nestedParse(source, state) {
113
+ var result = [];
114
+ state = state || latestState;
115
+ latestState = state;
116
+ while (source) {
117
+ // store the best match, it's rule, and quality:
118
+ var ruleType = null;
119
+ var rule = null;
120
+ var capture = null;
121
+ var quality = NaN;
122
+
123
+ // loop control variables:
124
+ var i = 0;
125
+ var currRuleType = ruleList[0];
126
+ var currRule = rules[currRuleType];
127
+ do {
128
+ var currOrder = currRule.order;
129
+ var prevCaptureStr = state.prevCapture == null ? "" : state.prevCapture[0];
130
+ var currCapture = currRule.match(source, state, prevCaptureStr);
131
+ if (currCapture) {
132
+ var currQuality = currRule.quality ? currRule.quality(currCapture, state, prevCaptureStr) : 0;
133
+ // This should always be true the first time because
134
+ // the initial quality is NaN (that's why there's the
135
+ // condition negation).
136
+ if (!(currQuality <= quality)) {
137
+ // @ts-expect-error [FEI-5003] - TS2322 - Type 'string' is not assignable to type 'null'.
138
+ ruleType = currRuleType;
139
+ // @ts-expect-error [FEI-5003] - TS2322 - Type 'ParserRule' is not assignable to type 'null'.
140
+ rule = currRule;
141
+ // @ts-expect-error [FEI-5003] - TS2322 - Type 'Capture' is not assignable to type 'null'.
142
+ capture = currCapture;
143
+ quality = currQuality;
144
+ }
145
+ }
146
+
147
+ // Move on to the next item.
148
+ // Note that this makes `currRule` be the next item
149
+ i++;
150
+ currRuleType = ruleList[i];
151
+ currRule = rules[currRuleType];
152
+ } while (
153
+ // keep looping while we're still within the ruleList
154
+ currRule && (
155
+ // if we don't have a match yet, continue
156
+ !capture ||
157
+ // or if we have a match, but the next rule is
158
+ // at the same order, and has a quality measurement
159
+ // functions, then this rule must have a quality
160
+ // measurement function (since they are sorted before
161
+ // those without), and we need to check if there is
162
+ // a better quality match
163
+ currRule.order === currOrder && currRule.quality));
164
+
165
+ // TODO(aria): Write tests for these
166
+ if (rule == null || capture == null) {
167
+ throw new Error("Could not find a matching rule for the below " + "content. The rule with highest `order` should " + "always match content provided to it. Check " + "the definition of `match` for '" + ruleList[ruleList.length - 1] + "'. It seems to not match the following source:\n" + source);
168
+ }
169
+ // @ts-expect-error [FEI-5003] - TS2339 - Property 'index' does not exist on type 'never'.
170
+ if (capture.index) {
171
+ // If present and non-zero, i.e. a non-^ regexp result:
172
+ throw new Error("`match` must return a capture starting at index 0 " + "(the current parse index). Did you forget a ^ at the " + "start of the RegExp?");
173
+ }
174
+
175
+ // @ts-expect-error [FEI-5003] - TS2339 - Property 'parse' does not exist on type 'never'.
176
+ var parsed = rule.parse(capture, nestedParse, state);
177
+ // We maintain the same object here so that rules can
178
+ // store references to the objects they return and
179
+ // modify them later. (oops sorry! but this adds a lot
180
+ // of power--see reflinks.)
181
+ if (Array.isArray(parsed)) {
182
+ Array.prototype.push.apply(result, parsed);
183
+ } else {
184
+ if (parsed == null || typeof parsed !== "object") {
185
+ throw new Error("parse() function returned invalid parse result: '".concat(parsed, "'"));
186
+ }
187
+
188
+ // We also let rules override the default type of
189
+ // their parsed node if they would like to, so that
190
+ // there can be a single output function for all links,
191
+ // even if there are several rules to parse them.
192
+ if (parsed.type == null) {
193
+ parsed.type = ruleType;
194
+ }
195
+ result.push(parsed);
196
+ }
197
+ state.prevCapture = capture;
198
+ source = source.substring(state.prevCapture[0].length);
199
+ }
200
+ return result;
201
+ };
202
+ var outerParse = function outerParse(source, state) {
203
+ latestState = populateInitialState(state, defaultState);
204
+ if (!latestState.inline && !latestState.disableAutoBlockNewlines) {
205
+ source = source + "\n\n";
206
+ }
207
+ // We store the previous capture so that match functions can
208
+ // use some limited amount of lookbehind. Lists use this to
209
+ // ensure they don't match arbitrary '- ' or '* ' in inline
210
+ // text (see the list rule for more information). This stores
211
+ // the full regex capture object, if there is one.
212
+ latestState.prevCapture = null;
213
+ return nestedParse(preprocess(source), latestState);
214
+ };
215
+ return outerParse;
216
+ };
217
+
218
+ // Creates a match function for an inline scoped element from a regex
219
+ var inlineRegex = function inlineRegex(regex) {
220
+ var match = function match(source, state, prevCapture) {
221
+ if (state.inline) {
222
+ return regex.exec(source);
223
+ } else {
224
+ return null;
225
+ }
226
+ };
227
+ // @ts-expect-error [FEI-5003] - TS2339 - Property 'regex' does not exist on type '(source: string, state: State, prevCapture: string) => Capture | null | undefined'.
228
+ match.regex = regex;
229
+ return match;
230
+ };
231
+
232
+ // Creates a match function for a block scoped element from a regex
233
+ var blockRegex = function blockRegex(regex) {
234
+ var match = function match(source, state) {
235
+ if (state.inline) {
236
+ return null;
237
+ } else {
238
+ return regex.exec(source);
239
+ }
240
+ };
241
+ match.regex = regex;
242
+ return match;
243
+ };
244
+
245
+ // Creates a match function from a regex, ignoring block/inline scope
246
+ var anyScopeRegex = function anyScopeRegex(regex) {
247
+ var match = function match(source, state) {
248
+ return regex.exec(source);
249
+ };
250
+ match.regex = regex;
251
+ return match;
252
+ };
253
+ var TYPE_SYMBOL = typeof Symbol === "function" && Symbol.for && Symbol.for("react.element") || 0xeac7;
254
+ var reactElement = function reactElement(type, key, props) {
255
+ var element = {
256
+ $$typeof: TYPE_SYMBOL,
257
+ type: type,
258
+ key: key == null ? undefined : key,
259
+ ref: null,
260
+ props: props,
261
+ _owner: null
262
+ };
263
+ return element;
264
+ };
265
+
266
+ /** Returns a closed HTML tag.
267
+ * @param {string} tagName - Name of HTML tag (eg. "em" or "a")
268
+ * @param {string} content - Inner content of tag
269
+ * @param {{ [attr: string]: SimpleMarkdown.Attr }} [attributes] - Optional extra attributes of tag as an object of key-value pairs
270
+ * eg. { "href": "http://google.com" }. Falsey attributes are filtered out.
271
+ * @param {boolean} [isClosed] - boolean that controls whether tag is closed or not (eg. img tags).
272
+ * defaults to true
273
+ */
274
+ var htmlTag = function htmlTag(tagName, content, attributes, isClosed) {
275
+ attributes = attributes || {};
276
+ isClosed = typeof isClosed !== "undefined" ? isClosed : true;
277
+ var attributeString = "";
278
+ for (var attr in attributes) {
279
+ var attribute = attributes[attr];
280
+ // Removes falsey attributes
281
+ if (
282
+ // $FlowFixMe
283
+ Object.prototype.hasOwnProperty.call(attributes, attr) && attribute) {
284
+ attributeString += " " + sanitizeText(attr) + '="' + sanitizeText(attribute) + '"';
285
+ }
286
+ }
287
+ var unclosedTag = "<" + tagName + attributeString + ">";
288
+ if (isClosed) {
289
+ return unclosedTag + content + "</" + tagName + ">";
290
+ } else {
291
+ return unclosedTag;
292
+ }
293
+ };
294
+ var EMPTY_PROPS = {};
295
+
296
+ /**
297
+ * @param {string | null | undefined} url - url to sanitize
298
+ * @returns {string | null} - url if safe, or null if a safe url could not be made
299
+ */
300
+ var sanitizeUrl = function sanitizeUrl(url) {
301
+ if (url == null) {
302
+ return null;
303
+ }
304
+ try {
305
+ var prot = new URL(url, "https://localhost").protocol;
306
+ if (prot.indexOf("javascript:") === 0 || prot.indexOf("vbscript:") === 0 || prot.indexOf("data:") === 0) {
307
+ return null;
308
+ }
309
+ } catch (e) {
310
+ // invalid URLs should throw a TypeError
311
+ // see for instance: `new URL("");`
312
+ return null;
313
+ }
314
+ return url;
315
+ };
316
+ var SANITIZE_TEXT_R = /[<>&"']/g;
317
+ var SANITIZE_TEXT_CODES = {
318
+ "<": "&lt;",
319
+ ">": "&gt;",
320
+ "&": "&amp;",
321
+ '"': "&quot;",
322
+ "'": "&#x27;",
323
+ "/": "&#x2F;",
324
+ "`": "&#96;"
325
+ };
326
+ var sanitizeText = function sanitizeText(text) {
327
+ return String(text).replace(SANITIZE_TEXT_R, function (chr) {
328
+ return SANITIZE_TEXT_CODES[chr];
329
+ });
330
+ };
331
+ var UNESCAPE_URL_R = /\\([^0-9A-Za-z\s])/g;
332
+ var unescapeUrl = function unescapeUrl(rawUrlString) {
333
+ return rawUrlString.replace(UNESCAPE_URL_R, "$1");
334
+ };
335
+
336
+ /**
337
+ * Parse some content with the parser `parse`, with state.inline
338
+ * set to true. Useful for block elements; not generally necessary
339
+ * to be used by inline elements (where state.inline is already true.
340
+ */
341
+ var parseInline = function parseInline(parse, content, state) {
342
+ var isCurrentlyInline = state.inline || false;
343
+ state.inline = true;
344
+ var result = parse(content, state);
345
+ state.inline = isCurrentlyInline;
346
+ return result;
347
+ };
348
+ var parseBlock = function parseBlock(parse, content, state) {
349
+ var isCurrentlyInline = state.inline || false;
350
+ state.inline = false;
351
+ var result = parse(content + "\n\n", state);
352
+ state.inline = isCurrentlyInline;
353
+ return result;
354
+ };
355
+ var parseCaptureInline = function parseCaptureInline(capture, parse, state) {
356
+ return {
357
+ content: parseInline(parse, capture[1], state)
358
+ };
359
+ };
360
+ var ignoreCapture = function ignoreCapture() {
361
+ return {};
362
+ };
363
+
364
+ // recognize a `*` `-`, `+`, `1.`, `2.`... list bullet
365
+ var LIST_BULLET = "(?:[*+-]|\\d+\\.)";
366
+ // recognize the start of a list item:
367
+ // leading space plus a bullet plus a space (` * `)
368
+ var LIST_ITEM_PREFIX = "( *)(" + LIST_BULLET + ") +";
369
+ var LIST_ITEM_PREFIX_R = new RegExp("^" + LIST_ITEM_PREFIX);
370
+ // recognize an individual list item:
371
+ // * hi
372
+ // this is part of the same item
373
+ //
374
+ // as is this, which is a new paragraph in the same item
375
+ //
376
+ // * but this is not part of the same item
377
+ var LIST_ITEM_R = new RegExp(LIST_ITEM_PREFIX + "[^\\n]*(?:\\n" + "(?!\\1" + LIST_BULLET + " )[^\\n]*)*(\n|$)", "gm");
378
+ var BLOCK_END_R = /\n{2,}$/;
379
+ var INLINE_CODE_ESCAPE_BACKTICKS_R = /^ (?= *`)|(` *) $/g;
380
+ // recognize the end of a paragraph block inside a list item:
381
+ // two or more newlines at end end of the item
382
+ var LIST_BLOCK_END_R = BLOCK_END_R;
383
+ var LIST_ITEM_END_R = / *\n+$/;
384
+ // check whether a list item has paragraphs: if it does,
385
+ // we leave the newlines at the end
386
+ var LIST_R = new RegExp("^( *)(" + LIST_BULLET + ") " + "[\\s\\S]+?(?:\n{2,}(?! )" + "(?!\\1" + LIST_BULLET + " )\\n*" +
387
+ // the \\s*$ here is so that we can parse the inside of nested
388
+ // lists, where our content might end before we receive two `\n`s
389
+ "|\\s*\n*$)");
390
+ var LIST_LOOKBEHIND_R = /(?:^|\n)( *)$/;
391
+ var TABLES = function () {
392
+ var TABLE_ROW_SEPARATOR_TRIM = /^ *\| *| *\| *$/g;
393
+ var TABLE_CELL_END_TRIM = / *$/;
394
+ var TABLE_RIGHT_ALIGN = /^ *-+: *$/;
395
+ var TABLE_CENTER_ALIGN = /^ *:-+: *$/;
396
+ var TABLE_LEFT_ALIGN = /^ *:-+ *$/;
397
+
398
+ // TODO: This needs a real type
399
+
400
+ var parseTableAlignCapture = function parseTableAlignCapture(alignCapture) {
401
+ if (TABLE_RIGHT_ALIGN.test(alignCapture)) {
402
+ return "right";
403
+ } else if (TABLE_CENTER_ALIGN.test(alignCapture)) {
404
+ return "center";
405
+ } else if (TABLE_LEFT_ALIGN.test(alignCapture)) {
406
+ return "left";
407
+ } else {
408
+ return null;
409
+ }
410
+ };
411
+ var parseTableAlign = function parseTableAlign(source, parse, state, trimEndSeparators) {
412
+ if (trimEndSeparators) {
413
+ source = source.replace(TABLE_ROW_SEPARATOR_TRIM, "");
414
+ }
415
+ var alignText = source.trim().split("|");
416
+ return alignText.map(parseTableAlignCapture);
417
+ };
418
+ var parseTableRow = function parseTableRow(source, parse, state, trimEndSeparators) {
419
+ var prevInTable = state.inTable;
420
+ state.inTable = true;
421
+ var tableRow = parse(source.trim(), state);
422
+ state.inTable = prevInTable;
423
+ var cells = [[]];
424
+ tableRow.forEach(function (node, i) {
425
+ if (node.type === "tableSeparator") {
426
+ // Filter out empty table separators at the start/end:
427
+ if (!trimEndSeparators || i !== 0 && i !== tableRow.length - 1) {
428
+ // Split the current row:
429
+ cells.push([]);
430
+ }
431
+ } else {
432
+ if (node.type === "text" && (tableRow[i + 1] == null || tableRow[i + 1].type === "tableSeparator")) {
433
+ node.content = node.content.replace(TABLE_CELL_END_TRIM, "");
434
+ }
435
+ // @ts-expect-error [FEI-5003] - TS2345 - Argument of type 'SingleASTNode' is not assignable to parameter of type 'never'.
436
+ cells[cells.length - 1].push(node);
437
+ }
438
+ });
439
+ return cells;
440
+ };
441
+
442
+ /**
443
+ * @param {string} source
444
+ * @param {SimpleMarkdown.Parser} parse
445
+ * @param {SimpleMarkdown.State} state
446
+ * @param {boolean} trimEndSeparators
447
+ * @returns {SimpleMarkdown.ASTNode[][]}
448
+ */
449
+ var parseTableCells = function parseTableCells(source, parse, state, trimEndSeparators) {
450
+ var rowsText = source.trim().split("\n");
451
+ return rowsText.map(function (rowText) {
452
+ return parseTableRow(rowText, parse, state, trimEndSeparators);
453
+ });
454
+ };
455
+
456
+ /**
457
+ * @param {boolean} trimEndSeparators
458
+ * @returns {SimpleMarkdown.SingleNodeParseFunction}
459
+ */
460
+ var parseTable = function parseTable(trimEndSeparators) {
461
+ return function (capture, parse, state) {
462
+ state.inline = true;
463
+ var header = parseTableRow(capture[1], parse, state, trimEndSeparators);
464
+ var align = parseTableAlign(capture[2], parse, state, trimEndSeparators);
465
+ var cells = parseTableCells(capture[3], parse, state, trimEndSeparators);
466
+ state.inline = false;
467
+ return {
468
+ type: "table",
469
+ header: header,
470
+ align: align,
471
+ cells: cells
472
+ };
473
+ };
474
+ };
475
+ return {
476
+ parseTable: parseTable(true),
477
+ parseNpTable: parseTable(false),
478
+ TABLE_REGEX: /^ *(\|.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/,
479
+ NPTABLE_REGEX: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/
480
+ };
481
+ }();
482
+ var LINK_INSIDE = "(?:\\[[^\\]]*\\]|[^\\[\\]]|\\](?=[^\\[]*\\]))*";
483
+ var LINK_HREF_AND_TITLE = "\\s*<?((?:\\([^)]*\\)|[^\\s\\\\]|\\\\.)*?)>?(?:\\s+['\"]([\\s\\S]*?)['\"])?\\s*";
484
+ var AUTOLINK_MAILTO_CHECK_R = /mailto:/i;
485
+ var parseRef = function parseRef(capture, state, refNode) {
486
+ var ref = (capture[2] || capture[1]).replace(/\s+/g, " ").toLowerCase();
487
+
488
+ // We store information about previously seen defs on
489
+ // state._defs (_ to deconflict with client-defined
490
+ // state). If the def for this reflink/refimage has
491
+ // already been seen, we can use its target/source
492
+ // and title here:
493
+ if (state._defs && state._defs[ref]) {
494
+ var def = state._defs[ref];
495
+ // `refNode` can be a link or an image. Both use
496
+ // target and title properties.
497
+ refNode.target = def.target;
498
+ refNode.title = def.title;
499
+ }
500
+
501
+ // In case we haven't seen our def yet (or if someone
502
+ // overwrites that def later on), we add this node
503
+ // to the list of ref nodes for that def. Then, when
504
+ // we find the def, we can modify this link/image AST
505
+ // node :).
506
+ // I'm sorry.
507
+ state._refs = state._refs || {};
508
+ state._refs[ref] = state._refs[ref] || [];
509
+ state._refs[ref].push(refNode);
510
+ return refNode;
511
+ };
512
+ var currOrder = 0;
513
+ var defaultRules = {
514
+ Array: {
515
+ react: function react(arr, output, state) {
516
+ var oldKey = state.key;
517
+ var result = [];
518
+
519
+ // map output over the ast, except group any text
520
+ // nodes together into a single string output.
521
+ for (var i = 0, key = 0; i < arr.length; i++, key++) {
522
+ // `key` is our numerical `state.key`, which we increment for
523
+ // every output node, but don't change for joined text nodes.
524
+ // (i, however, must change for joined text nodes)
525
+ state.key = "" + i;
526
+ var node = arr[i];
527
+ if (node.type === "text") {
528
+ node = {
529
+ type: "text",
530
+ content: node.content
531
+ };
532
+ for (; i + 1 < arr.length && arr[i + 1].type === "text"; i++) {
533
+ node.content += arr[i + 1].content;
534
+ }
535
+ }
536
+ result.push(output(node, state));
537
+ }
538
+ state.key = oldKey;
539
+ return result;
540
+ },
541
+ html: function html(arr, output, state) {
542
+ var result = "";
543
+
544
+ // map output over the ast, except group any text
545
+ // nodes together into a single string output.
546
+ for (var i = 0; i < arr.length; i++) {
547
+ var node = arr[i];
548
+ if (node.type === "text") {
549
+ node = {
550
+ type: "text",
551
+ content: node.content
552
+ };
553
+ for (; i + 1 < arr.length && arr[i + 1].type === "text"; i++) {
554
+ node.content += arr[i + 1].content;
555
+ }
556
+ }
557
+ result += output(node, state);
558
+ }
559
+ return result;
560
+ }
561
+ },
562
+ heading: {
563
+ order: currOrder++,
564
+ match: blockRegex(/^ *(#{1,6})([^\n]+?)#* *(?:\n *)+\n/),
565
+ parse: function (_parse) {
566
+ function parse(_x, _x2, _x3) {
567
+ return _parse.apply(this, arguments);
568
+ }
569
+ parse.toString = function () {
570
+ return _parse.toString();
571
+ };
572
+ return parse;
573
+ }(function (capture, parse, state) {
574
+ return {
575
+ level: capture[1].length,
576
+ content: parseInline(parse, capture[2].trim(), state)
577
+ };
578
+ }),
579
+ react: function react(node, output, state) {
580
+ return reactElement("h" + node.level, state.key, {
581
+ children: output(node.content, state)
582
+ });
583
+ },
584
+ html: function html(node, output, state) {
585
+ return htmlTag("h" + node.level, output(node.content, state));
586
+ }
587
+ },
588
+ nptable: {
589
+ order: currOrder++,
590
+ match: blockRegex(TABLES.NPTABLE_REGEX),
591
+ parse: TABLES.parseNpTable,
592
+ react: null,
593
+ html: null
594
+ },
595
+ lheading: {
596
+ order: currOrder++,
597
+ match: blockRegex(/^([^\n]+)\n *(=|-){3,} *(?:\n *)+\n/),
598
+ parse: function (_parse2) {
599
+ function parse(_x4, _x5, _x6) {
600
+ return _parse2.apply(this, arguments);
601
+ }
602
+ parse.toString = function () {
603
+ return _parse2.toString();
604
+ };
605
+ return parse;
606
+ }(function (capture, parse, state) {
607
+ return {
608
+ type: "heading",
609
+ level: capture[2] === "=" ? 1 : 2,
610
+ content: parseInline(parse, capture[1], state)
611
+ };
612
+ }),
613
+ react: null,
614
+ html: null
615
+ },
616
+ hr: {
617
+ order: currOrder++,
618
+ match: blockRegex(/^( *[-*_]){3,} *(?:\n *)+\n/),
619
+ parse: ignoreCapture,
620
+ react: function react(node, output, state) {
621
+ return reactElement("hr", state.key, EMPTY_PROPS);
622
+ },
623
+ html: function html(node, output, state) {
624
+ return "<hr>";
625
+ }
626
+ },
627
+ codeBlock: {
628
+ order: currOrder++,
629
+ match: blockRegex(/^(?: [^\n]+\n*)+(?:\n *)+\n/),
630
+ parse: function (_parse3) {
631
+ function parse(_x7, _x8, _x9) {
632
+ return _parse3.apply(this, arguments);
633
+ }
634
+ parse.toString = function () {
635
+ return _parse3.toString();
636
+ };
637
+ return parse;
638
+ }(function (capture, parse, state) {
639
+ var content = capture[0].replace(/^ /gm, "").replace(/\n+$/, "");
640
+ return {
641
+ lang: undefined,
642
+ content: content
643
+ };
644
+ }),
645
+ react: function react(node, output, state) {
646
+ var className = node.lang ? "markdown-code-" + node.lang : undefined;
647
+ return reactElement("pre", state.key, {
648
+ children: reactElement("code", null, {
649
+ className: className,
650
+ children: node.content
651
+ })
652
+ });
653
+ },
654
+ html: function html(node, output, state) {
655
+ var className = node.lang ? "markdown-code-" + node.lang : undefined;
656
+ var codeBlock = htmlTag("code", sanitizeText(node.content), {
657
+ class: className
658
+ });
659
+ return htmlTag("pre", codeBlock);
660
+ }
661
+ },
662
+ fence: {
663
+ order: currOrder++,
664
+ match: blockRegex(/^ *(`{3,}|~{3,}) *(?:(\S+) *)?\n([\s\S]+?)\n?\1 *(?:\n *)+\n/),
665
+ parse: function (_parse4) {
666
+ function parse(_x10, _x11, _x12) {
667
+ return _parse4.apply(this, arguments);
668
+ }
669
+ parse.toString = function () {
670
+ return _parse4.toString();
671
+ };
672
+ return parse;
673
+ }(function (capture, parse, state) {
674
+ return {
675
+ type: "codeBlock",
676
+ lang: capture[2] || undefined,
677
+ content: capture[3]
678
+ };
679
+ }),
680
+ react: null,
681
+ html: null
682
+ },
683
+ blockQuote: {
684
+ order: currOrder++,
685
+ match: blockRegex(/^( *>[^\n]+(\n[^\n]+)*\n*)+\n{2,}/),
686
+ parse: function (_parse5) {
687
+ function parse(_x13, _x14, _x15) {
688
+ return _parse5.apply(this, arguments);
689
+ }
690
+ parse.toString = function () {
691
+ return _parse5.toString();
692
+ };
693
+ return parse;
694
+ }(function (capture, parse, state) {
695
+ var content = capture[0].replace(/^ *> ?/gm, "");
696
+ return {
697
+ content: parse(content, state)
698
+ };
699
+ }),
700
+ react: function react(node, output, state) {
701
+ return reactElement("blockquote", state.key, {
702
+ children: output(node.content, state)
703
+ });
704
+ },
705
+ html: function html(node, output, state) {
706
+ return htmlTag("blockquote", output(node.content, state));
707
+ }
708
+ },
709
+ list: {
710
+ order: currOrder++,
711
+ // $FlowFixMe
712
+ match: function match(source, state) {
713
+ // We only want to break into a list if we are at the start of a
714
+ // line. This is to avoid parsing "hi * there" with "* there"
715
+ // becoming a part of a list.
716
+ // You might wonder, "but that's inline, so of course it wouldn't
717
+ // start a list?". You would be correct! Except that some of our
718
+ // lists can be inline, because they might be inside another list,
719
+ // in which case we can parse with inline scope, but need to allow
720
+ // nested lists inside this inline scope.
721
+ var prevCaptureStr = state.prevCapture == null ? "" : state.prevCapture[0];
722
+ var isStartOfLineCapture = LIST_LOOKBEHIND_R.exec(prevCaptureStr);
723
+ var isListBlock = state._list || !state.inline;
724
+ if (isStartOfLineCapture && isListBlock) {
725
+ source = isStartOfLineCapture[1] + source;
726
+ return LIST_R.exec(source);
727
+ } else {
728
+ return null;
729
+ }
730
+ },
731
+ parse: function (_parse6) {
732
+ function parse(_x16, _x17, _x18) {
733
+ return _parse6.apply(this, arguments);
734
+ }
735
+ parse.toString = function () {
736
+ return _parse6.toString();
737
+ };
738
+ return parse;
739
+ }(function (capture, parse, state) {
740
+ var bullet = capture[2];
741
+ var ordered = bullet.length > 1;
742
+ var start = ordered ? +bullet : undefined;
743
+ // @ts-expect-error [FEI-5003] - TS2322 - Type 'RegExpMatchArray | null' is not assignable to type 'string[]'.
744
+ var items = capture[0].replace(LIST_BLOCK_END_R, "\n").match(LIST_ITEM_R);
745
+
746
+ // We know this will match here, because of how the regexes are
747
+ // defined
748
+
749
+ var lastItemWasAParagraph = false;
750
+ var itemContent = items.map(function (item, i) {
751
+ // We need to see how far indented this item is:
752
+ var prefixCapture = LIST_ITEM_PREFIX_R.exec(item);
753
+ var space = prefixCapture ? prefixCapture[0].length : 0;
754
+ // And then we construct a regex to "unindent" the subsequent
755
+ // lines of the items by that amount:
756
+ var spaceRegex = new RegExp("^ {1," + space + "}", "gm");
757
+
758
+ // Before processing the item, we need a couple things
759
+ var content = item
760
+ // remove indents on trailing lines:
761
+ .replace(spaceRegex, "")
762
+ // remove the bullet:
763
+ .replace(LIST_ITEM_PREFIX_R, "");
764
+
765
+ // I'm not sur4 why this is necessary again?
766
+
767
+ // Handling "loose" lists, like:
768
+ //
769
+ // * this is wrapped in a paragraph
770
+ //
771
+ // * as is this
772
+ //
773
+ // * as is this
774
+ var isLastItem = i === items.length - 1;
775
+ var containsBlocks = content.indexOf("\n\n") !== -1;
776
+
777
+ // Any element in a list is a block if it contains multiple
778
+ // newlines. The last element in the list can also be a block
779
+ // if the previous item in the list was a block (this is
780
+ // because non-last items in the list can end with \n\n, but
781
+ // the last item can't, so we just "inherit" this property
782
+ // from our previous element).
783
+ var thisItemIsAParagraph = containsBlocks || isLastItem && lastItemWasAParagraph;
784
+ lastItemWasAParagraph = thisItemIsAParagraph;
785
+
786
+ // backup our state for restoration afterwards. We're going to
787
+ // want to set state._list to true, and state.inline depending
788
+ // on our list's looseness.
789
+ var oldStateInline = state.inline;
790
+ var oldStateList = state._list;
791
+ state._list = true;
792
+
793
+ // Parse inline if we're in a tight list, or block if we're in
794
+ // a loose list.
795
+ var adjustedContent;
796
+ if (thisItemIsAParagraph) {
797
+ state.inline = false;
798
+ adjustedContent = content.replace(LIST_ITEM_END_R, "\n\n");
799
+ } else {
800
+ state.inline = true;
801
+ adjustedContent = content.replace(LIST_ITEM_END_R, "");
802
+ }
803
+ var result = parse(adjustedContent, state);
804
+
805
+ // Restore our state before returning
806
+ state.inline = oldStateInline;
807
+ state._list = oldStateList;
808
+ return result;
809
+ });
810
+ return {
811
+ ordered: ordered,
812
+ start: start,
813
+ items: itemContent
814
+ };
815
+ }),
816
+ react: function react(node, output, state) {
817
+ var ListWrapper = node.ordered ? "ol" : "ul";
818
+ return reactElement(ListWrapper, state.key, {
819
+ start: node.start,
820
+ children: node.items.map(function (item, i) {
821
+ return reactElement("li", "" + i, {
822
+ children: output(item, state)
823
+ });
824
+ })
825
+ });
826
+ },
827
+ html: function html(node, output, state) {
828
+ var listItems = node.items.map(function (item) {
829
+ return htmlTag("li", output(item, state));
830
+ }).join("");
831
+ var listTag = node.ordered ? "ol" : "ul";
832
+ var attributes = {
833
+ start: node.start
834
+ };
835
+ return htmlTag(listTag, listItems, attributes);
836
+ }
837
+ },
838
+ def: {
839
+ order: currOrder++,
840
+ // TODO(aria): This will match without a blank line before the next
841
+ // block element, which is inconsistent with most of the rest of
842
+ // simple-markdown.
843
+ match: blockRegex(/^ *\[([^\]]+)\]: *<?([^\s>]*)>?(?: +["(]([^\n]+)[")])? *\n(?: *\n)*/),
844
+ parse: function (_parse7) {
845
+ function parse(_x19, _x20, _x21) {
846
+ return _parse7.apply(this, arguments);
847
+ }
848
+ parse.toString = function () {
849
+ return _parse7.toString();
850
+ };
851
+ return parse;
852
+ }(function (capture, parse, state) {
853
+ var def = capture[1].replace(/\s+/g, " ").toLowerCase();
854
+ var target = capture[2];
855
+ var title = capture[3];
856
+
857
+ // Look for previous links/images using this def
858
+ // If any links/images using this def have already been declared,
859
+ // they will have added themselves to the state._refs[def] list
860
+ // (_ to deconflict with client-defined state). We look through
861
+ // that list of reflinks for this def, and modify those AST nodes
862
+ // with our newly found information now.
863
+ // Sorry :(.
864
+ if (state._refs && state._refs[def]) {
865
+ // `refNode` can be a link or an image
866
+ state._refs[def].forEach(function (refNode) {
867
+ refNode.target = target;
868
+ refNode.title = title;
869
+ });
870
+ }
871
+
872
+ // Add this def to our map of defs for any future links/images
873
+ // In case we haven't found any or all of the refs referring to
874
+ // this def yet, we add our def to the table of known defs, so
875
+ // that future reflinks can modify themselves appropriately with
876
+ // this information.
877
+ state._defs = state._defs || {};
878
+ state._defs[def] = {
879
+ target: target,
880
+ title: title
881
+ };
882
+
883
+ // return the relevant parsed information
884
+ // for debugging only.
885
+ return {
886
+ def: def,
887
+ target: target,
888
+ title: title
889
+ };
890
+ }),
891
+ react: function react() {
892
+ return null;
893
+ },
894
+ html: function html() {
895
+ return "";
896
+ }
897
+ },
898
+ table: {
899
+ order: currOrder++,
900
+ match: blockRegex(TABLES.TABLE_REGEX),
901
+ parse: TABLES.parseTable,
902
+ react: function react(node, output, state) {
903
+ var getStyle = function getStyle(colIndex) {
904
+ return node.align[colIndex] == null ? {} : {
905
+ textAlign: node.align[colIndex]
906
+ };
907
+ };
908
+ var headers = node.header.map(function (content, i) {
909
+ return reactElement("th", "" + i, {
910
+ style: getStyle(i),
911
+ scope: "col",
912
+ children: output(content, state)
913
+ });
914
+ });
915
+ var rows = node.cells.map(function (row, r) {
916
+ return reactElement("tr", "" + r, {
917
+ children: row.map(function (content, c) {
918
+ return reactElement("td", "" + c, {
919
+ style: getStyle(c),
920
+ children: output(content, state)
921
+ });
922
+ })
923
+ });
924
+ });
925
+ return reactElement("table", state.key, {
926
+ children: [reactElement("thead", "thead", {
927
+ children: reactElement("tr", null, {
928
+ children: headers
929
+ })
930
+ }), reactElement("tbody", "tbody", {
931
+ children: rows
932
+ })]
933
+ });
934
+ },
935
+ html: function html(node, output, state) {
936
+ var getStyle = function getStyle(colIndex) {
937
+ return node.align[colIndex] == null ? "" : "text-align:" + node.align[colIndex] + ";";
938
+ };
939
+ var headers = node.header.map(function (content, i) {
940
+ return htmlTag("th", output(content, state), {
941
+ style: getStyle(i),
942
+ scope: "col"
943
+ });
944
+ }).join("");
945
+ var rows = node.cells.map(function (row) {
946
+ var cols = row.map(function (content, c) {
947
+ return htmlTag("td", output(content, state), {
948
+ style: getStyle(c)
949
+ });
950
+ }).join("");
951
+ return htmlTag("tr", cols);
952
+ }).join("");
953
+ var thead = htmlTag("thead", htmlTag("tr", headers));
954
+ var tbody = htmlTag("tbody", rows);
955
+ return htmlTag("table", thead + tbody);
956
+ }
957
+ },
958
+ newline: {
959
+ order: currOrder++,
960
+ match: blockRegex(/^(?:\n *)*\n/),
961
+ parse: ignoreCapture,
962
+ react: function react(node, output, state) {
963
+ return "\n";
964
+ },
965
+ html: function html(node, output, state) {
966
+ return "\n";
967
+ }
968
+ },
969
+ paragraph: {
970
+ order: currOrder++,
971
+ match: blockRegex(/^((?:[^\n]|\n(?! *\n))+)(?:\n *)+\n/),
972
+ parse: parseCaptureInline,
973
+ react: function react(node, output, state) {
974
+ return reactElement("div", state.key, {
975
+ className: "paragraph",
976
+ children: output(node.content, state)
977
+ });
978
+ },
979
+ html: function html(node, output, state) {
980
+ var attributes = {
981
+ class: "paragraph"
982
+ };
983
+ return htmlTag("div", output(node.content, state), attributes);
984
+ }
985
+ },
986
+ escape: {
987
+ order: currOrder++,
988
+ // We don't allow escaping numbers, letters, or spaces here so that
989
+ // backslashes used in plain text still get rendered. But allowing
990
+ // escaping anything else provides a very flexible escape mechanism,
991
+ // regardless of how this grammar is extended.
992
+ match: inlineRegex(/^\\([^0-9A-Za-z\s])/),
993
+ parse: function (_parse8) {
994
+ function parse(_x22, _x23, _x24) {
995
+ return _parse8.apply(this, arguments);
996
+ }
997
+ parse.toString = function () {
998
+ return _parse8.toString();
999
+ };
1000
+ return parse;
1001
+ }(function (capture, parse, state) {
1002
+ return {
1003
+ type: "text",
1004
+ content: capture[1]
1005
+ };
1006
+ }),
1007
+ react: null,
1008
+ html: null
1009
+ },
1010
+ tableSeparator: {
1011
+ order: currOrder++,
1012
+ // $FlowFixMe
1013
+ match: function match(source, state) {
1014
+ if (!state.inTable) {
1015
+ return null;
1016
+ }
1017
+ return /^ *\| */.exec(source);
1018
+ },
1019
+ parse: function parse() {
1020
+ return {
1021
+ type: "tableSeparator"
1022
+ };
1023
+ },
1024
+ // These shouldn't be reached, but in case they are, be reasonable:
1025
+ react: function react() {
1026
+ return " | ";
1027
+ },
1028
+ html: function html() {
1029
+ return " &vert; ";
1030
+ }
1031
+ },
1032
+ autolink: {
1033
+ order: currOrder++,
1034
+ match: inlineRegex(/^<([^: >]+:\/[^ >]+)>/),
1035
+ parse: function (_parse9) {
1036
+ function parse(_x25, _x26, _x27) {
1037
+ return _parse9.apply(this, arguments);
1038
+ }
1039
+ parse.toString = function () {
1040
+ return _parse9.toString();
1041
+ };
1042
+ return parse;
1043
+ }(function (capture, parse, state) {
1044
+ return {
1045
+ type: "link",
1046
+ content: [{
1047
+ type: "text",
1048
+ content: capture[1]
1049
+ }],
1050
+ target: capture[1]
1051
+ };
1052
+ }),
1053
+ react: null,
1054
+ html: null
1055
+ },
1056
+ mailto: {
1057
+ order: currOrder++,
1058
+ match: inlineRegex(/^<([^ >]+@[^ >]+)>/),
1059
+ parse: function (_parse10) {
1060
+ function parse(_x28, _x29, _x30) {
1061
+ return _parse10.apply(this, arguments);
1062
+ }
1063
+ parse.toString = function () {
1064
+ return _parse10.toString();
1065
+ };
1066
+ return parse;
1067
+ }(function (capture, parse, state) {
1068
+ var address = capture[1];
1069
+ var target = capture[1];
1070
+
1071
+ // Check for a `mailto:` already existing in the link:
1072
+ if (!AUTOLINK_MAILTO_CHECK_R.test(target)) {
1073
+ target = "mailto:" + target;
1074
+ }
1075
+ return {
1076
+ type: "link",
1077
+ content: [{
1078
+ type: "text",
1079
+ content: address
1080
+ }],
1081
+ target: target
1082
+ };
1083
+ }),
1084
+ react: null,
1085
+ html: null
1086
+ },
1087
+ url: {
1088
+ order: currOrder++,
1089
+ match: inlineRegex(/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/),
1090
+ parse: function (_parse11) {
1091
+ function parse(_x31, _x32, _x33) {
1092
+ return _parse11.apply(this, arguments);
1093
+ }
1094
+ parse.toString = function () {
1095
+ return _parse11.toString();
1096
+ };
1097
+ return parse;
1098
+ }(function (capture, parse, state) {
1099
+ return {
1100
+ type: "link",
1101
+ content: [{
1102
+ type: "text",
1103
+ content: capture[1]
1104
+ }],
1105
+ target: capture[1],
1106
+ title: undefined
1107
+ };
1108
+ }),
1109
+ react: null,
1110
+ html: null
1111
+ },
1112
+ link: {
1113
+ order: currOrder++,
1114
+ match: inlineRegex(new RegExp("^\\[(" + LINK_INSIDE + ")\\]\\(" + LINK_HREF_AND_TITLE + "\\)")),
1115
+ parse: function (_parse12) {
1116
+ function parse(_x34, _x35, _x36) {
1117
+ return _parse12.apply(this, arguments);
1118
+ }
1119
+ parse.toString = function () {
1120
+ return _parse12.toString();
1121
+ };
1122
+ return parse;
1123
+ }(function (capture, parse, state) {
1124
+ var link = {
1125
+ content: parse(capture[1], state),
1126
+ target: unescapeUrl(capture[2]),
1127
+ title: capture[3]
1128
+ };
1129
+ return link;
1130
+ }),
1131
+ react: function react(node, output, state) {
1132
+ return reactElement("a", state.key, {
1133
+ href: sanitizeUrl(node.target),
1134
+ title: node.title,
1135
+ children: output(node.content, state)
1136
+ });
1137
+ },
1138
+ html: function html(node, output, state) {
1139
+ var attributes = {
1140
+ href: sanitizeUrl(node.target),
1141
+ title: node.title
1142
+ };
1143
+ return htmlTag("a", output(node.content, state), attributes);
1144
+ }
1145
+ },
1146
+ image: {
1147
+ order: currOrder++,
1148
+ match: inlineRegex(new RegExp("^!\\[(" + LINK_INSIDE + ")\\]\\(" + LINK_HREF_AND_TITLE + "\\)")),
1149
+ parse: function (_parse13) {
1150
+ function parse(_x37, _x38, _x39) {
1151
+ return _parse13.apply(this, arguments);
1152
+ }
1153
+ parse.toString = function () {
1154
+ return _parse13.toString();
1155
+ };
1156
+ return parse;
1157
+ }(function (capture, parse, state) {
1158
+ var image = {
1159
+ alt: capture[1],
1160
+ target: unescapeUrl(capture[2]),
1161
+ title: capture[3]
1162
+ };
1163
+ return image;
1164
+ }),
1165
+ react: function react(node, output, state) {
1166
+ return reactElement("img", state.key, {
1167
+ src: sanitizeUrl(node.target),
1168
+ alt: node.alt,
1169
+ title: node.title
1170
+ });
1171
+ },
1172
+ html: function html(node, output, state) {
1173
+ var attributes = {
1174
+ src: sanitizeUrl(node.target),
1175
+ alt: node.alt,
1176
+ title: node.title
1177
+ };
1178
+ return htmlTag("img", "", attributes, false);
1179
+ }
1180
+ },
1181
+ reflink: {
1182
+ order: currOrder++,
1183
+ match: inlineRegex(new RegExp(
1184
+ // The first [part] of the link
1185
+ "^\\[(" + LINK_INSIDE + ")\\]" +
1186
+ // The [ref] target of the link
1187
+ "\\s*\\[([^\\]]*)\\]")),
1188
+ parse: function (_parse14) {
1189
+ function parse(_x40, _x41, _x42) {
1190
+ return _parse14.apply(this, arguments);
1191
+ }
1192
+ parse.toString = function () {
1193
+ return _parse14.toString();
1194
+ };
1195
+ return parse;
1196
+ }(function (capture, parse, state) {
1197
+ return parseRef(capture, state, {
1198
+ type: "link",
1199
+ content: parse(capture[1], state)
1200
+ });
1201
+ }),
1202
+ react: null,
1203
+ html: null
1204
+ },
1205
+ refimage: {
1206
+ order: currOrder++,
1207
+ match: inlineRegex(new RegExp(
1208
+ // The first [part] of the link
1209
+ "^!\\[(" + LINK_INSIDE + ")\\]" +
1210
+ // The [ref] target of the link
1211
+ "\\s*\\[([^\\]]*)\\]")),
1212
+ parse: function (_parse15) {
1213
+ function parse(_x43, _x44, _x45) {
1214
+ return _parse15.apply(this, arguments);
1215
+ }
1216
+ parse.toString = function () {
1217
+ return _parse15.toString();
1218
+ };
1219
+ return parse;
1220
+ }(function (capture, parse, state) {
1221
+ return parseRef(capture, state, {
1222
+ type: "image",
1223
+ alt: capture[1]
1224
+ });
1225
+ }),
1226
+ react: null,
1227
+ html: null
1228
+ },
1229
+ em: {
1230
+ order: currOrder /* same as strong/u */,
1231
+ match: inlineRegex(new RegExp(
1232
+ // only match _s surrounding words.
1233
+ "^\\b_" + "((?:__|\\\\[\\s\\S]|[^\\\\_])+?)_" + "\\b" +
1234
+ // Or match *s:
1235
+ "|" +
1236
+ // Only match *s that are followed by a non-space:
1237
+ "^\\*(?=\\S)(" +
1238
+ // Match at least one of:
1239
+ "(?:" +
1240
+ // - `**`: so that bolds inside italics don't close the
1241
+ // italics
1242
+ "\\*\\*|" +
1243
+ // - escape sequence: so escaped *s don't close us
1244
+ "\\\\[\\s\\S]|" +
1245
+ // - whitespace: followed by a non-* (we don't
1246
+ // want ' *' to close an italics--it might
1247
+ // start a list)
1248
+ "\\s+(?:\\\\[\\s\\S]|[^\\s\\*\\\\]|\\*\\*)|" +
1249
+ // - non-whitespace, non-*, non-backslash characters
1250
+ "[^\\s\\*\\\\]" + ")+?" +
1251
+ // followed by a non-space, non-* then *
1252
+ ")\\*(?!\\*)")),
1253
+ quality: function quality(capture) {
1254
+ // precedence by length, `em` wins ties:
1255
+ return capture[0].length + 0.2;
1256
+ },
1257
+ parse: function (_parse16) {
1258
+ function parse(_x46, _x47, _x48) {
1259
+ return _parse16.apply(this, arguments);
1260
+ }
1261
+ parse.toString = function () {
1262
+ return _parse16.toString();
1263
+ };
1264
+ return parse;
1265
+ }(function (capture, parse, state) {
1266
+ return {
1267
+ content: parse(capture[2] || capture[1], state)
1268
+ };
1269
+ }),
1270
+ react: function react(node, output, state) {
1271
+ return reactElement("em", state.key, {
1272
+ children: output(node.content, state)
1273
+ });
1274
+ },
1275
+ html: function html(node, output, state) {
1276
+ return htmlTag("em", output(node.content, state));
1277
+ }
1278
+ },
1279
+ strong: {
1280
+ order: currOrder /* same as em */,
1281
+ match: inlineRegex(/^\*\*((?:\\[\s\S]|[^\\])+?)\*\*(?!\*)/),
1282
+ quality: function quality(capture) {
1283
+ // precedence by length, wins ties vs `u`:
1284
+ return capture[0].length + 0.1;
1285
+ },
1286
+ parse: parseCaptureInline,
1287
+ react: function react(node, output, state) {
1288
+ return reactElement("strong", state.key, {
1289
+ children: output(node.content, state)
1290
+ });
1291
+ },
1292
+ html: function html(node, output, state) {
1293
+ return htmlTag("strong", output(node.content, state));
1294
+ }
1295
+ },
1296
+ u: {
1297
+ order: currOrder++ /* same as em&strong; increment for next rule */,
1298
+ match: inlineRegex(/^__((?:\\[\s\S]|[^\\])+?)__(?!_)/),
1299
+ quality: function quality(capture) {
1300
+ // precedence by length, loses all ties
1301
+ return capture[0].length;
1302
+ },
1303
+ parse: parseCaptureInline,
1304
+ react: function react(node, output, state) {
1305
+ return reactElement("u", state.key, {
1306
+ children: output(node.content, state)
1307
+ });
1308
+ },
1309
+ html: function html(node, output, state) {
1310
+ return htmlTag("u", output(node.content, state));
1311
+ }
1312
+ },
1313
+ del: {
1314
+ order: currOrder++,
1315
+ match: inlineRegex(/^~~(?=\S)((?:\\[\s\S]|~(?!~)|[^\s~\\]|\s(?!~~))+?)~~/),
1316
+ parse: parseCaptureInline,
1317
+ react: function react(node, output, state) {
1318
+ return reactElement("del", state.key, {
1319
+ children: output(node.content, state)
1320
+ });
1321
+ },
1322
+ html: function html(node, output, state) {
1323
+ return htmlTag("del", output(node.content, state));
1324
+ }
1325
+ },
1326
+ inlineCode: {
1327
+ order: currOrder++,
1328
+ match: inlineRegex(/^(`+)([\s\S]*?[^`])\1(?!`)/),
1329
+ parse: function (_parse17) {
1330
+ function parse(_x49, _x50, _x51) {
1331
+ return _parse17.apply(this, arguments);
1332
+ }
1333
+ parse.toString = function () {
1334
+ return _parse17.toString();
1335
+ };
1336
+ return parse;
1337
+ }(function (capture, parse, state) {
1338
+ return {
1339
+ content: capture[2].replace(INLINE_CODE_ESCAPE_BACKTICKS_R, "$1")
1340
+ };
1341
+ }),
1342
+ react: function react(node, output, state) {
1343
+ return reactElement("code", state.key, {
1344
+ children: node.content
1345
+ });
1346
+ },
1347
+ html: function html(node, output, state) {
1348
+ return htmlTag("code", sanitizeText(node.content));
1349
+ }
1350
+ },
1351
+ br: {
1352
+ order: currOrder++,
1353
+ match: anyScopeRegex(/^ {2,}\n/),
1354
+ parse: ignoreCapture,
1355
+ react: function react(node, output, state) {
1356
+ return reactElement("br", state.key, EMPTY_PROPS);
1357
+ },
1358
+ html: function html(node, output, state) {
1359
+ return "<br>";
1360
+ }
1361
+ },
1362
+ text: {
1363
+ order: currOrder++,
1364
+ // Here we look for anything followed by non-symbols,
1365
+ // double newlines, or double-space-newlines
1366
+ // We break on any symbol characters so that this grammar
1367
+ // is easy to extend without needing to modify this regex
1368
+ match: anyScopeRegex(/^[\s\S]+?(?=[^0-9A-Za-z\s\u00c0-\uffff]|\n\n| {2,}\n|\w+:\S|$)/),
1369
+ parse: function (_parse18) {
1370
+ function parse(_x52, _x53, _x54) {
1371
+ return _parse18.apply(this, arguments);
1372
+ }
1373
+ parse.toString = function () {
1374
+ return _parse18.toString();
1375
+ };
1376
+ return parse;
1377
+ }(function (capture, parse, state) {
1378
+ return {
1379
+ content: capture[0]
1380
+ };
1381
+ }),
1382
+ react: function react(node, output, state) {
1383
+ return node.content;
1384
+ },
1385
+ html: function html(node, output, state) {
1386
+ return sanitizeText(node.content);
1387
+ }
1388
+ }
1389
+ };
1390
+
1391
+ /** (deprecated) */
1392
+ var ruleOutput = function ruleOutput(
1393
+ // $FlowFixMe
1394
+ rules, property) {
1395
+ if (!property && typeof console !== "undefined") {
1396
+ console.warn("simple-markdown ruleOutput should take 'react' or " + "'html' as the second argument.");
1397
+ }
1398
+ var nestedRuleOutput = function nestedRuleOutput(ast, outputFunc, state) {
1399
+ // @ts-expect-error [FEI-5003] - TS2349 - This expression is not callable.
1400
+ // Type 'unknown' has no call signatures.
1401
+ return rules[ast.type][property](ast, outputFunc, state);
1402
+ };
1403
+ return nestedRuleOutput;
1404
+ };
1405
+
1406
+ /** (deprecated)
1407
+ */
1408
+ var reactFor = function reactFor(outputFunc) {
1409
+ var nestedOutput = function nestedOutput(ast, state) {
1410
+ state = state || {};
1411
+ if (Array.isArray(ast)) {
1412
+ var oldKey = state.key;
1413
+ var result = [];
1414
+
1415
+ // map nestedOutput over the ast, except group any text
1416
+ // nodes together into a single string output.
1417
+ var lastResult = null;
1418
+ for (var i = 0; i < ast.length; i++) {
1419
+ state.key = "" + i;
1420
+ var nodeOut = nestedOutput(ast[i], state);
1421
+ if (typeof nodeOut === "string" && typeof lastResult === "string") {
1422
+ // @ts-expect-error [FEI-5003] - TS2322 - Type 'string' is not assignable to type 'null'.
1423
+ lastResult = lastResult + nodeOut;
1424
+ result[result.length - 1] = lastResult;
1425
+ } else {
1426
+ result.push(nodeOut);
1427
+ // @ts-expect-error [FEI-5003] - TS2322 - Type 'ReactNode' is not assignable to type 'null'.
1428
+ lastResult = nodeOut;
1429
+ }
1430
+ }
1431
+ state.key = oldKey;
1432
+ return result;
1433
+ } else {
1434
+ return outputFunc(ast, nestedOutput, state);
1435
+ }
1436
+ };
1437
+ return nestedOutput;
1438
+ };
1439
+
1440
+ /** (deprecated)
1441
+ */
1442
+ var htmlFor = function htmlFor(outputFunc) {
1443
+ var nestedOutput = function nestedOutput(ast, state) {
1444
+ state = state || {};
1445
+ if (Array.isArray(ast)) {
1446
+ return ast.map(function (node) {
1447
+ return nestedOutput(node, state);
1448
+ }).join("");
1449
+ } else {
1450
+ return outputFunc(ast, nestedOutput, state);
1451
+ }
1452
+ };
1453
+ return nestedOutput;
1454
+ };
1455
+ var outputFor = function outputFor(rules, property) {
1456
+ var defaultState = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
1457
+ if (!property) {
1458
+ throw new Error("simple-markdown: outputFor: `property` must be " + "defined. " + "if you just upgraded, you probably need to replace `outputFor` " + "with `reactFor`");
1459
+ }
1460
+ var latestState;
1461
+ var arrayRule = rules.Array || defaultRules.Array;
1462
+
1463
+ // Tricks to convince tsc that this var is not null:
1464
+ // @ts-expect-error [FEI-5003] - TS2538 - Type 'symbol' cannot be used as an index type.
1465
+ var arrayRuleCheck = arrayRule[property];
1466
+ if (!arrayRuleCheck) {
1467
+ throw new Error("simple-markdown: outputFor: to join nodes of type `" +
1468
+ // @ts-expect-error [FEI-5003] - TS2469 - The '+' operator cannot be applied to type 'symbol'.
1469
+ property + "` you must provide an `Array:` joiner rule with that type, " + "Please see the docs for details on specifying an Array rule.");
1470
+ }
1471
+ var arrayRuleOutput = arrayRuleCheck;
1472
+ var nestedOutput = function nestedOutput(ast, state) {
1473
+ state = state || latestState;
1474
+ latestState = state;
1475
+ if (Array.isArray(ast)) {
1476
+ return arrayRuleOutput(ast, nestedOutput, state);
1477
+ } else {
1478
+ // @ts-expect-error [FEI-5003] - TS2349 - This expression is not callable.
1479
+ // Type 'unknown' has no call signatures.
1480
+ return rules[ast.type][property](ast, nestedOutput, state);
1481
+ }
1482
+ };
1483
+ var outerOutput = function outerOutput(ast, state) {
1484
+ latestState = populateInitialState(state, defaultState);
1485
+ return nestedOutput(ast, latestState);
1486
+ };
1487
+ return outerOutput;
1488
+ };
1489
+
1490
+ // @ts-expect-error [FEI-5003] - TS2345 - Argument of type 'DefaultRules' is not assignable to parameter of type 'ParserRules'.
1491
+ var defaultRawParse = parserFor(defaultRules);
1492
+ var defaultBlockParse = function defaultBlockParse(source, state) {
1493
+ state = state || {};
1494
+ state.inline = false;
1495
+ return defaultRawParse(source, state);
1496
+ };
1497
+ var defaultInlineParse = function defaultInlineParse(source, state) {
1498
+ state = state || {};
1499
+ state.inline = true;
1500
+ return defaultRawParse(source, state);
1501
+ };
1502
+ var defaultImplicitParse = function defaultImplicitParse(source, state) {
1503
+ var isBlock = BLOCK_END_R.test(source);
1504
+ state = state || {};
1505
+ state.inline = !isBlock;
1506
+ return defaultRawParse(source, state);
1507
+ };
1508
+ var defaultReactOutput = outputFor(defaultRules, "react");
1509
+ var defaultHtmlOutput = outputFor(defaultRules, "html");
1510
+ var markdownToReact = function markdownToReact(source, state) {
1511
+ return defaultReactOutput(defaultBlockParse(source, state), state);
1512
+ };
1513
+ var markdownToHtml = function markdownToHtml(source, state) {
1514
+ return defaultHtmlOutput(defaultBlockParse(source, state), state);
1515
+ };
1516
+
1517
+ // TODO: This needs definition
1518
+
1519
+ var ReactMarkdown = function ReactMarkdown(props) {
1520
+ var divProps = {};
1521
+ for (var prop in props) {
1522
+ if (prop !== "source" &&
1523
+ // $FlowFixMe
1524
+ Object.prototype.hasOwnProperty.call(props, prop)) {
1525
+ divProps[prop] = props[prop];
1526
+ }
1527
+ }
1528
+ divProps.children = markdownToReact(props.source);
1529
+ return reactElement("div", null, divProps);
1530
+ };
1531
+ var SimpleMarkdown = {
1532
+ defaultRules: defaultRules,
1533
+ parserFor: parserFor,
1534
+ outputFor: outputFor,
1535
+ inlineRegex: inlineRegex,
1536
+ blockRegex: blockRegex,
1537
+ anyScopeRegex: anyScopeRegex,
1538
+ parseInline: parseInline,
1539
+ parseBlock: parseBlock,
1540
+ // default wrappers:
1541
+ markdownToReact: markdownToReact,
1542
+ markdownToHtml: markdownToHtml,
1543
+ // @ts-expect-error [FEI-5003] - TS2322 - Type 'FC<any>' is not assignable to type '(props: { [key: string]: any; source: string; }) => ReactElement'.
1544
+ ReactMarkdown: ReactMarkdown,
1545
+ defaultBlockParse: defaultBlockParse,
1546
+ defaultInlineParse: defaultInlineParse,
1547
+ defaultImplicitParse: defaultImplicitParse,
1548
+ defaultReactOutput: defaultReactOutput,
1549
+ defaultHtmlOutput: defaultHtmlOutput,
1550
+ preprocess: preprocess,
1551
+ sanitizeText: sanitizeText,
1552
+ sanitizeUrl: sanitizeUrl,
1553
+ unescapeUrl: unescapeUrl,
1554
+ htmlTag: htmlTag,
1555
+ reactElement: reactElement,
1556
+ // deprecated:
1557
+ defaultRawParse: defaultRawParse,
1558
+ ruleOutput: ruleOutput,
1559
+ reactFor: reactFor,
1560
+ htmlFor: htmlFor,
1561
+ defaultParse: function defaultParse() {
1562
+ if (typeof console !== "undefined") {
1563
+ console.warn("defaultParse is deprecated, please use `defaultImplicitParse`");
1564
+ }
1565
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
1566
+ args[_key] = arguments[_key];
1567
+ }
1568
+ return defaultImplicitParse.apply(null, args);
1569
+ },
1570
+ defaultOutput: function defaultOutput() {
1571
+ if (typeof console !== "undefined") {
1572
+ console.warn("defaultOutput is deprecated, please use `defaultReactOutput`");
1573
+ }
1574
+ for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
1575
+ args[_key2] = arguments[_key2];
1576
+ }
1577
+ return defaultReactOutput.apply(null, args);
1578
+ }
1579
+ };
1580
+
1581
+ export { SimpleMarkdown as default };
1582
+ //# sourceMappingURL=index.js.map