markdown-to-jsx 6.10.1 → 6.11.1

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/index.js CHANGED
@@ -167,11 +167,12 @@ const REFERENCE_LINK_R = /^\[([^\]]*)\] ?\[([^\]]*)\]/;
167
167
  const SQUARE_BRACKETS_R = /(\[|\])/g;
168
168
  const SHOULD_RENDER_AS_BLOCK_R = /(\n|^[-*]\s|^#|^ {2,}|^-{2,}|^>\s)/;
169
169
  const TAB_R = /\t/g;
170
+ const TABLE_SEPARATOR_R = /^ *\| */;
170
171
  const TABLE_TRIM_PIPES = /(^ *\||\| *$)/g;
172
+ const TABLE_CELL_END_TRIM = / *$/;
171
173
  const TABLE_CENTER_ALIGN = /^ *:-+: *$/;
172
174
  const TABLE_LEFT_ALIGN = /^ *:-+ *$/;
173
175
  const TABLE_RIGHT_ALIGN = /^ *-+: *$/;
174
- const TABLE_ROW_SPLIT = / *\| */;
175
176
 
176
177
  const TEXT_BOLD_R = /^([*_])\1((?:\[.*?\][([].*?[)\]]|<.*?>(?:.*?<.*?>)?|`.*?`|~+.*?~+|.)*?)\1\1(?!\1)/;
177
178
  const TEXT_EMPHASIZED_R = /^([*_])((?:\[.*?\][([].*?[)\]]|<.*?>(?:.*?<.*?>)?|`.*?`|~+.*?~+|.)*?)\1(?!\1)/;
@@ -179,7 +180,7 @@ const TEXT_STRIKETHROUGHED_R = /^~~((?:\[.*?\]|<.*?>(?:.*?<.*?>)?|`.*?`|.)*?)~~/
179
180
 
180
181
  const TEXT_ESCAPED_R = /^\\([^0-9A-Za-z\s])/;
181
182
  const TEXT_PLAIN_R = /^[\s\S]+?(?=[^0-9A-Z\s\u00c0-\uffff&;.()'"]|\d+\.|\n\n| {2,}\n|\w+:\S|$)/i;
182
- const TRIM_NEWLINES_AND_TRAILING_WHITESPACE_R = /(^\n+|(\n|\s)+$)/g;
183
+ const TRIM_NEWLINES_AND_TRAILING_WHITESPACE_R = /(^\n+|\n+$|\s+$)/g;
183
184
 
184
185
  const HTML_LEFT_TRIM_AMOUNT_R = /^([ \t]*)/;
185
186
 
@@ -287,46 +288,56 @@ function parseTableAlignCapture(alignCapture) {
287
288
  return null;
288
289
  }
289
290
 
290
- function parseTableHeader(capture, parse, state) {
291
- const headerText = capture[1]
292
- .replace(TABLE_TRIM_PIPES, '')
293
- .trim()
294
- .split(TABLE_ROW_SPLIT);
295
-
296
- return headerText.map(function(text) {
297
- return parse(text, state);
291
+ function parseTableRow(source, parse, state) {
292
+ const prevInTable = state.inTable;
293
+ state.inTable = true;
294
+ const tableRow = parse(source.trim(), state);
295
+ state.inTable = prevInTable;
296
+
297
+ let cells = [[]];
298
+ tableRow.forEach(function(node, i) {
299
+ if (node.type === 'tableSeparator') {
300
+ // Filter out empty table separators at the start/end:
301
+ if (i !== 0 && i !== tableRow.length - 1) {
302
+ // Split the current row:
303
+ cells.push([]);
304
+ }
305
+ } else {
306
+ if (node.type === 'text' && (
307
+ tableRow[i + 1] == null ||
308
+ tableRow[i + 1].type === 'tableSeparator'
309
+ )) {
310
+ node.content = node.content.replace(TABLE_CELL_END_TRIM, "");
311
+ }
312
+ cells[cells.length - 1].push(node);
313
+ }
298
314
  });
315
+ return cells;
299
316
  }
300
317
 
301
- function parseTableAlign(capture /*, parse, state*/) {
302
- const alignText = capture[2]
318
+ function parseTableAlign(source /*, parse, state*/) {
319
+ const alignText = source
303
320
  .replace(TABLE_TRIM_PIPES, '')
304
- .trim()
305
- .split(TABLE_ROW_SPLIT);
321
+ .split('|');
306
322
 
307
323
  return alignText.map(parseTableAlignCapture);
308
324
  }
309
325
 
310
- function parseTableCells(capture, parse, state) {
311
- const rowsText = capture[3]
326
+ function parseTableCells(source, parse, state) {
327
+ const rowsText = source
312
328
  .trim()
313
329
  .split('\n');
314
330
 
315
331
  return rowsText.map(function(rowText) {
316
- return rowText
317
- .replace(TABLE_TRIM_PIPES, '')
318
- .split(TABLE_ROW_SPLIT)
319
- .map(function(text) {
320
- return parse(text.trim(), state);
321
- });
332
+ return parseTableRow(rowText, parse, state);
322
333
  });
323
334
  }
324
335
 
325
336
  function parseTable(capture, parse, state) {
326
337
  state.inline = true;
327
- const header = parseTableHeader(capture, parse, state);
328
- const align = parseTableAlign(capture, parse, state);
329
- const cells = parseTableCells(capture, parse, state);
338
+ const header = parseTableRow(capture[1], parse, state);
339
+ const align = parseTableAlign(capture[2], parse, state);
340
+ const cells = parseTableCells(capture[3], parse, state);
330
341
  state.inline = false;
331
342
 
332
343
  return {
@@ -374,6 +385,8 @@ function attributeValueToJSXPropValue(key, value) {
374
385
 
375
386
  return styles;
376
387
  }, {});
388
+ } else if (key === 'href') {
389
+ return sanitizeUrl(value)
377
390
  } else if (value.match(INTERPOLATION_R)) {
378
391
  // return as a string and let the consumer decide what to do with it
379
392
  value = value.slice(1, value.length - 1);
@@ -805,7 +818,7 @@ export function compiler(markdown, options) {
805
818
  { key: index }
806
819
  );
807
820
  }
808
- } else {
821
+ } else if (raw !== 'style') {
809
822
  map[ATTRIBUTE_TO_JSX_PROP_MAP[raw] || raw] = true;
810
823
  }
811
824
 
@@ -814,6 +827,10 @@ export function compiler(markdown, options) {
814
827
  : undefined;
815
828
  }
816
829
 
830
+ function stripHtmlComments(html) {
831
+ return html.replace(/<!--[\s\S]*?(?:-->)/g, '')
832
+ }
833
+
817
834
  /* istanbul ignore next */
818
835
  if (process.env.NODE_ENV !== 'production') {
819
836
  if (typeof markdown !== 'string') {
@@ -1013,47 +1030,6 @@ export function compiler(markdown, options) {
1013
1030
  },
1014
1031
  },
1015
1032
 
1016
- htmlBlock: {
1017
- /**
1018
- * find the first matching end tag and process the interior
1019
- */
1020
- match: anyScopeRegex(HTML_BLOCK_ELEMENT_R),
1021
- order: PARSE_PRIORITY_HIGH,
1022
- parse(capture, parse, state) {
1023
- const [, whitespace] = capture[3].match(HTML_LEFT_TRIM_AMOUNT_R);
1024
- const trimmer = new RegExp(`^${whitespace}`, 'gm');
1025
- const trimmed = capture[3].replace(trimmer, '');
1026
-
1027
- const parseFunc = containsBlockSyntax(trimmed)
1028
- ? parseBlock
1029
- : parseInline;
1030
-
1031
- const tagName = capture[1].toLowerCase();
1032
- const noInnerParse =
1033
- DO_NOT_PROCESS_HTML_ELEMENTS.indexOf(tagName) !== -1;
1034
-
1035
- return {
1036
- attrs: attrStringToMap(capture[2]),
1037
- /**
1038
- * if another html block is detected within, parse as block,
1039
- * otherwise parse as inline to pick up any further markdown
1040
- */
1041
- content: noInnerParse ? capture[3] : parseFunc(parse, trimmed, state),
1042
-
1043
- noInnerParse,
1044
-
1045
- tag: noInnerParse ? tagName : capture[1]
1046
- };
1047
- },
1048
- react(node, output, state) {
1049
- return (
1050
- <node.tag key={state.key} {...node.attrs}>
1051
- {node.noInnerParse ? node.content : output(node.content, state)}
1052
- </node.tag>
1053
- );
1054
- },
1055
- },
1056
-
1057
1033
  htmlComment: {
1058
1034
  match: anyScopeRegex(HTML_COMMENT_R),
1059
1035
  order: PARSE_PRIORITY_HIGH,
@@ -1063,23 +1039,6 @@ export function compiler(markdown, options) {
1063
1039
  react: renderNothing,
1064
1040
  },
1065
1041
 
1066
- htmlSelfClosing: {
1067
- /**
1068
- * find the first matching end tag and process the interior
1069
- */
1070
- match: anyScopeRegex(HTML_SELF_CLOSING_ELEMENT_R),
1071
- order: PARSE_PRIORITY_HIGH,
1072
- parse(capture /*, parse, state*/) {
1073
- return {
1074
- attrs: attrStringToMap(capture[2] || ''),
1075
- tag: capture[1],
1076
- };
1077
- },
1078
- react(node, output, state) {
1079
- return <node.tag {...node.attrs} key={state.key} />;
1080
- },
1081
- },
1082
-
1083
1042
  image: {
1084
1043
  match: simpleInlineRegex(IMAGE_R),
1085
1044
  order: PARSE_PRIORITY_HIGH,
@@ -1411,6 +1370,21 @@ export function compiler(markdown, options) {
1411
1370
  },
1412
1371
  },
1413
1372
 
1373
+ tableSeparator: {
1374
+ match: function(source, state) {
1375
+ if (!state.inTable) {
1376
+ return null;
1377
+ }
1378
+ return TABLE_SEPARATOR_R.exec(source);
1379
+ },
1380
+ order: PARSE_PRIORITY_HIGH,
1381
+ parse: function() {
1382
+ return { type: 'tableSeparator' };
1383
+ },
1384
+ // These shouldn't be reached, but in case they are, be reasonable:
1385
+ react() { return ' | '; }
1386
+ },
1387
+
1414
1388
  text: {
1415
1389
  // Here we look for anything followed by non-symbols,
1416
1390
  // double newlines, or double-space-newlines
@@ -1521,10 +1495,70 @@ export function compiler(markdown, options) {
1521
1495
  // };
1522
1496
  // });
1523
1497
 
1498
+ if (options.disableParsingRawHTML !== true) {
1499
+ rules.htmlBlock = {
1500
+ /**
1501
+ * find the first matching end tag and process the interior
1502
+ */
1503
+ match: anyScopeRegex(HTML_BLOCK_ELEMENT_R),
1504
+ order: PARSE_PRIORITY_HIGH,
1505
+ parse(capture, parse, state) {
1506
+ const [, whitespace] = capture[3].match(HTML_LEFT_TRIM_AMOUNT_R);
1507
+ const trimmer = new RegExp(`^${whitespace}`, 'gm');
1508
+ const trimmed = capture[3].replace(trimmer, '');
1509
+
1510
+ const parseFunc = containsBlockSyntax(trimmed)
1511
+ ? parseBlock
1512
+ : parseInline;
1513
+
1514
+ const tagName = capture[1].toLowerCase();
1515
+ const noInnerParse =
1516
+ DO_NOT_PROCESS_HTML_ELEMENTS.indexOf(tagName) !== -1;
1517
+
1518
+ return {
1519
+ attrs: attrStringToMap(capture[2]),
1520
+ /**
1521
+ * if another html block is detected within, parse as block,
1522
+ * otherwise parse as inline to pick up any further markdown
1523
+ */
1524
+ content: noInnerParse ? capture[3] : parseFunc(parse, trimmed, state),
1525
+
1526
+ noInnerParse,
1527
+
1528
+ tag: noInnerParse ? tagName : capture[1]
1529
+ };
1530
+ },
1531
+ react(node, output, state) {
1532
+ return (
1533
+ <node.tag key={state.key} {...node.attrs}>
1534
+ {node.noInnerParse ? node.content : output(node.content, state)}
1535
+ </node.tag>
1536
+ );
1537
+ },
1538
+ }
1539
+
1540
+ rules.htmlSelfClosing = {
1541
+ /**
1542
+ * find the first matching end tag and process the interior
1543
+ */
1544
+ match: anyScopeRegex(HTML_SELF_CLOSING_ELEMENT_R),
1545
+ order: PARSE_PRIORITY_HIGH,
1546
+ parse(capture /*, parse, state*/) {
1547
+ return {
1548
+ attrs: attrStringToMap(capture[2] || ''),
1549
+ tag: capture[1],
1550
+ };
1551
+ },
1552
+ react(node, output, state) {
1553
+ return <node.tag {...node.attrs} key={state.key} />;
1554
+ },
1555
+ };
1556
+ }
1557
+
1524
1558
  const parser = parserFor(rules);
1525
1559
  const emitter = reactFor(ruleOutput(rules));
1526
1560
 
1527
- const jsx = compile(markdown);
1561
+ const jsx = compile(stripHtmlComments(markdown));
1528
1562
 
1529
1563
  if (footnotes.length) {
1530
1564
  jsx.props.children.push(
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Convert markdown to JSX with ease for React and React-like projects. Super lightweight and highly configurable.",
4
4
  "homepage": "https://probablyup.github.io/markdown-to-jsx",
5
5
  "license": "MIT",
6
- "version": "6.10.1",
6
+ "version": "6.11.1",
7
7
  "engines": {
8
8
  "node": ">= 4"
9
9
  },
@@ -90,7 +90,7 @@
90
90
  "size-limit": [
91
91
  {
92
92
  "path": "dist/cjs.js",
93
- "limit": "5.15 kB"
93
+ "limit": "5.28 kB"
94
94
  }
95
95
  ],
96
96
  "jest": {