markdown-to-jsx 5.3.2 → 5.4.2
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/LICENSE +0 -0
- package/README.md +0 -0
- package/{index.es5.js → index.cjs.js} +4 -1
- package/index.esm.js +553 -0
- package/index.js +28 -23
- package/package.json +26 -29
package/LICENSE
CHANGED
|
File without changes
|
package/README.md
CHANGED
|
File without changes
|
|
@@ -34,7 +34,7 @@ function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in ob
|
|
|
34
34
|
|
|
35
35
|
function _toArray(arr) { return Array.isArray(arr) ? arr : Array.from(arr); }
|
|
36
36
|
|
|
37
|
-
var BLOCK_ELEMENT_TAGS = ['article', '
|
|
37
|
+
var BLOCK_ELEMENT_TAGS = ['article', 'aside', 'blockquote', 'body', 'button', 'canvas', 'caption', 'col', 'colgroup', 'dd', 'details', 'div', 'dl', 'dt', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'hr', 'iframe', 'li', 'map', 'object', 'ol', 'output', 'p', 'pre', 'progress', 'script', 'section', 'style', 'summary', 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'tr', 'ul', 'video'];
|
|
38
38
|
var BLOCK_ELEMENT_REGEX = new RegExp('^<(' + BLOCK_ELEMENT_TAGS.join('|') + ')', 'i');
|
|
39
39
|
|
|
40
40
|
// [0] === tag, [...] = attribute pairs
|
|
@@ -289,6 +289,9 @@ function coalesceInlineHTML(ast) {
|
|
|
289
289
|
if (node.type === 'html') {
|
|
290
290
|
if (!isCoalesceableHTML(node.value)) {
|
|
291
291
|
return;
|
|
292
|
+
} else if (node.value.indexOf('<!--') !== -1) {
|
|
293
|
+
// throw out HTML comments
|
|
294
|
+
siblings.splice(index, 1);
|
|
292
295
|
}
|
|
293
296
|
|
|
294
297
|
// are there more html nodes directly after? if so, fold them into the current node
|
package/index.esm.js
ADDED
|
@@ -0,0 +1,553 @@
|
|
|
1
|
+
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
|
2
|
+
|
|
3
|
+
function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
|
|
4
|
+
|
|
5
|
+
function _toArray(arr) { return Array.isArray(arr) ? arr : Array.from(arr); }
|
|
6
|
+
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import PropTypes from 'prop-types';
|
|
9
|
+
import get from 'lodash.get';
|
|
10
|
+
import unified from 'unified';
|
|
11
|
+
import parser from 'remark-parse';
|
|
12
|
+
|
|
13
|
+
var BLOCK_ELEMENT_TAGS = ['article', 'aside', 'blockquote', 'body', 'button', 'canvas', 'caption', 'col', 'colgroup', 'dd', 'details', 'div', 'dl', 'dt', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'hr', 'iframe', 'li', 'map', 'object', 'ol', 'output', 'p', 'pre', 'progress', 'script', 'section', 'style', 'summary', 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'tr', 'ul', 'video'];
|
|
14
|
+
var BLOCK_ELEMENT_REGEX = new RegExp('^<(' + BLOCK_ELEMENT_TAGS.join('|') + ')', 'i');
|
|
15
|
+
|
|
16
|
+
// [0] === tag, [...] = attribute pairs
|
|
17
|
+
var HTML_EXTRACTOR_REGEX = /([-A-Za-z0-9_]+)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g;
|
|
18
|
+
var SELF_CLOSING_ELEMENT_TAGS = ['area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr'];
|
|
19
|
+
var SELF_CLOSING_ELEMENT_REGEX = new RegExp('^<(' + SELF_CLOSING_ELEMENT_TAGS.join('|') + ')', 'i');
|
|
20
|
+
var TEXT_AST_TYPES = ['text', 'textNode'];
|
|
21
|
+
|
|
22
|
+
var ATTRIBUTE_TO_JSX_PROP_MAP = {
|
|
23
|
+
'accept-charset': 'acceptCharset',
|
|
24
|
+
'accesskey': 'accessKey',
|
|
25
|
+
'allowfullscreen': 'allowFullScreen',
|
|
26
|
+
'allowtransparency': 'allowTransparency',
|
|
27
|
+
'autocomplete': 'autoComplete',
|
|
28
|
+
'autofocus': 'autoFocus',
|
|
29
|
+
'autoplay': 'autoPlay',
|
|
30
|
+
'cellpadding': 'cellPadding',
|
|
31
|
+
'cellspacing': 'cellSpacing',
|
|
32
|
+
'charset': 'charSet',
|
|
33
|
+
'class': 'className',
|
|
34
|
+
'classid': 'classId',
|
|
35
|
+
'colspan': 'colSpan',
|
|
36
|
+
'contenteditable': 'contentEditable',
|
|
37
|
+
'contextmenu': 'contextMenu',
|
|
38
|
+
'crossorigin': 'crossOrigin',
|
|
39
|
+
'enctype': 'encType',
|
|
40
|
+
'for': 'htmlFor',
|
|
41
|
+
'formaction': 'formAction',
|
|
42
|
+
'formenctype': 'formEncType',
|
|
43
|
+
'formmethod': 'formMethod',
|
|
44
|
+
'formnovalidate': 'formNoValidate',
|
|
45
|
+
'formtarget': 'formTarget',
|
|
46
|
+
'frameborder': 'frameBorder',
|
|
47
|
+
'hreflang': 'hrefLang',
|
|
48
|
+
'http-equiv': 'httpEquiv',
|
|
49
|
+
'inputmode': 'inputMode',
|
|
50
|
+
'keyparams': 'keyParams',
|
|
51
|
+
'keytype': 'keyType',
|
|
52
|
+
'marginheight': 'marginHeight',
|
|
53
|
+
'marginwidth': 'marginWidth',
|
|
54
|
+
'maxlength': 'maxLength',
|
|
55
|
+
'mediagroup': 'mediaGroup',
|
|
56
|
+
'minlength': 'minLength',
|
|
57
|
+
'novalidate': 'noValidate',
|
|
58
|
+
'radiogroup': 'radioGroup',
|
|
59
|
+
'readonly': 'readOnly',
|
|
60
|
+
'rowspan': 'rowSpan',
|
|
61
|
+
'spellcheck': 'spellCheck',
|
|
62
|
+
'srcdoc': 'srcDoc',
|
|
63
|
+
'srclang': 'srcLang',
|
|
64
|
+
'srcset': 'srcSet',
|
|
65
|
+
'tabindex': 'tabIndex',
|
|
66
|
+
'usemap': 'useMap'
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
var getType = Object.prototype.toString;
|
|
70
|
+
|
|
71
|
+
function extractDefinitionsFromASTTree(ast, parser) {
|
|
72
|
+
function reducer(aggregator, node) {
|
|
73
|
+
if (node.type === 'definition' || node.type === 'footnoteDefinition') {
|
|
74
|
+
aggregator.definitions[node.identifier] = node;
|
|
75
|
+
|
|
76
|
+
if (node.type === 'footnoteDefinition') {
|
|
77
|
+
if (node.children && node.children.length === 1 && node.children[0].type === 'paragraph') {
|
|
78
|
+
node.children[0].children.unshift({
|
|
79
|
+
type: 'textNode',
|
|
80
|
+
value: '[' + node.identifier + ']: '
|
|
81
|
+
});
|
|
82
|
+
} /* package the prefix inside the first child */
|
|
83
|
+
|
|
84
|
+
aggregator.footnotes.push(React.createElement(
|
|
85
|
+
'div',
|
|
86
|
+
{ key: node.identifier, id: node.identifier },
|
|
87
|
+
node.value || node.children.map(parser)
|
|
88
|
+
));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return Array.isArray(node.children) ? node.children.reduce(reducer, aggregator) : aggregator;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
return [ast].reduce(reducer, {
|
|
96
|
+
definitions: {},
|
|
97
|
+
footnotes: []
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function formExtraPropsForHTMLNodeType() {
|
|
102
|
+
var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
103
|
+
var ast = arguments[1];
|
|
104
|
+
var definitions = arguments[2];
|
|
105
|
+
|
|
106
|
+
switch (ast.type) {
|
|
107
|
+
case 'footnoteReference':
|
|
108
|
+
return _extends({}, props, {
|
|
109
|
+
href: '#' + ast.identifier
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
case 'image':
|
|
113
|
+
return _extends({}, props, {
|
|
114
|
+
title: ast.title,
|
|
115
|
+
alt: ast.alt,
|
|
116
|
+
src: ast.url
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
case 'imageReference':
|
|
120
|
+
return _extends({}, props, {
|
|
121
|
+
title: get(definitions, '[\'' + ast.identifier + '\'].title'),
|
|
122
|
+
alt: ast.alt,
|
|
123
|
+
src: get(definitions, '[\'' + ast.identifier + '\'].url')
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
case 'link':
|
|
127
|
+
return _extends({}, props, {
|
|
128
|
+
title: ast.title,
|
|
129
|
+
href: ast.url
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
case 'linkReference':
|
|
133
|
+
return _extends({}, props, {
|
|
134
|
+
title: get(definitions, '[\'' + ast.identifier + '\'].title'),
|
|
135
|
+
href: get(definitions, '[\'' + ast.identifier + '\'].url')
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
case 'list':
|
|
139
|
+
return _extends({}, props, {
|
|
140
|
+
start: ast.start
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
case 'tableCell':
|
|
144
|
+
case 'th':
|
|
145
|
+
return _extends({}, props, {
|
|
146
|
+
style: { textAlign: ast.align }
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return props;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function getHTMLNodeTypeFromASTNodeType(node) {
|
|
154
|
+
switch (node.type) {
|
|
155
|
+
case 'break':
|
|
156
|
+
return 'br';
|
|
157
|
+
|
|
158
|
+
case 'delete':
|
|
159
|
+
return 'del';
|
|
160
|
+
|
|
161
|
+
case 'emphasis':
|
|
162
|
+
return 'em';
|
|
163
|
+
|
|
164
|
+
case 'footnoteReference':
|
|
165
|
+
return 'a';
|
|
166
|
+
|
|
167
|
+
case 'heading':
|
|
168
|
+
return 'h' + node.depth;
|
|
169
|
+
|
|
170
|
+
case 'image':
|
|
171
|
+
case 'imageReference':
|
|
172
|
+
return 'img';
|
|
173
|
+
|
|
174
|
+
case 'inlineCode':
|
|
175
|
+
return 'code';
|
|
176
|
+
|
|
177
|
+
case 'link':
|
|
178
|
+
case 'linkReference':
|
|
179
|
+
return 'a';
|
|
180
|
+
|
|
181
|
+
case 'list':
|
|
182
|
+
return node.ordered ? 'ol' : 'ul';
|
|
183
|
+
|
|
184
|
+
case 'listItem':
|
|
185
|
+
return 'li';
|
|
186
|
+
|
|
187
|
+
case 'paragraph':
|
|
188
|
+
return 'p';
|
|
189
|
+
|
|
190
|
+
case 'root':
|
|
191
|
+
return 'div';
|
|
192
|
+
|
|
193
|
+
case 'tableHeader':
|
|
194
|
+
return 'thead';
|
|
195
|
+
|
|
196
|
+
case 'tableRow':
|
|
197
|
+
return 'tr';
|
|
198
|
+
|
|
199
|
+
case 'tableCell':
|
|
200
|
+
return 'td';
|
|
201
|
+
|
|
202
|
+
case 'thematicBreak':
|
|
203
|
+
return 'hr';
|
|
204
|
+
|
|
205
|
+
case 'definition':
|
|
206
|
+
case 'footnoteDefinition':
|
|
207
|
+
case 'yaml':
|
|
208
|
+
return null;
|
|
209
|
+
|
|
210
|
+
default:
|
|
211
|
+
return node.type;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function seekCellsAndAlignThemIfNecessary(root, alignmentValues) {
|
|
216
|
+
var mapper = function mapper(child, index) {
|
|
217
|
+
if (child.type === 'tableCell') {
|
|
218
|
+
return _extends({}, child, {
|
|
219
|
+
align: alignmentValues[index]
|
|
220
|
+
});
|
|
221
|
+
} else if (Array.isArray(child.children) && child.children.length) {
|
|
222
|
+
return child.children.map(mapper);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return child;
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
if (Array.isArray(root.children) && root.children.length) {
|
|
229
|
+
root.children = root.children.map(mapper);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return root;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function attributeValueToJSXPropValue(key, value) {
|
|
236
|
+
if (key === 'style') {
|
|
237
|
+
return value.split(/;\s?/).reduce(function (styles, kvPair) {
|
|
238
|
+
|
|
239
|
+
var key = kvPair.slice(0, kvPair.indexOf(':'));
|
|
240
|
+
|
|
241
|
+
// snake-case to camelCase
|
|
242
|
+
// also handles PascalCasing vendor prefixes
|
|
243
|
+
var camelCasedKey = key.replace(/(\-[a-z])/g, function (substr) {
|
|
244
|
+
return substr[1].toUpperCase();
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// key.length + 1 to skip over the colon
|
|
248
|
+
styles[camelCasedKey] = kvPair.slice(key.length + 1).trim();
|
|
249
|
+
|
|
250
|
+
return styles;
|
|
251
|
+
}, {});
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return value;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function isCoalesceableHTML(html) {
|
|
258
|
+
// ignore block-level elements
|
|
259
|
+
// ignore self-closing or non-content-bearing elements
|
|
260
|
+
return html.match(BLOCK_ELEMENT_REGEX) || html.match(SELF_CLOSING_ELEMENT_REGEX) ? false : true;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function coalesceInlineHTML(ast) {
|
|
264
|
+
function coalescer(node, index, siblings) {
|
|
265
|
+
if (node.type === 'html') {
|
|
266
|
+
if (!isCoalesceableHTML(node.value)) {
|
|
267
|
+
return;
|
|
268
|
+
} else if (node.value.indexOf('<!--') !== -1) {
|
|
269
|
+
// throw out HTML comments
|
|
270
|
+
siblings.splice(index, 1);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// are there more html nodes directly after? if so, fold them into the current node
|
|
274
|
+
if (index < siblings.length - 1 && siblings[index + 1].type === 'html') {
|
|
275
|
+
// create a new coalescer context
|
|
276
|
+
coalescer(siblings[index + 1], index + 1, siblings);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
var i = index + 1;
|
|
280
|
+
var end = void 0;
|
|
281
|
+
|
|
282
|
+
// where's the end tag?
|
|
283
|
+
while (end === undefined && i < siblings.length) {
|
|
284
|
+
if (siblings[i].type !== 'html' || siblings[i].type === 'html' && !isCoalesceableHTML(siblings[i].value)) {
|
|
285
|
+
i += 1;
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
end = siblings[i];
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/* all interim elements now become children of the current node, and we splice them (including end tag)
|
|
293
|
+
out of the sibling array so they will not be iterated-over by forEach */
|
|
294
|
+
|
|
295
|
+
node.children = siblings.slice(index + 1, i);
|
|
296
|
+
siblings.splice(index + 1, i - index);
|
|
297
|
+
|
|
298
|
+
var _node$value$match = node.value.match(HTML_EXTRACTOR_REGEX),
|
|
299
|
+
_node$value$match2 = _toArray(_node$value$match),
|
|
300
|
+
tag = _node$value$match2[0],
|
|
301
|
+
attributePairs = _node$value$match2.slice(1);
|
|
302
|
+
|
|
303
|
+
// reassign the current node to whatever its tag is
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
node.type = tag.toLowerCase();
|
|
307
|
+
|
|
308
|
+
// make a best-effort conversion to JSX props
|
|
309
|
+
node.props = attributePairs.reduce(function (props, kvPair) {
|
|
310
|
+
var valueIndex = kvPair.indexOf('=');
|
|
311
|
+
var key = kvPair.slice(0, valueIndex === -1 ? undefined : valueIndex);
|
|
312
|
+
|
|
313
|
+
// ignoring inline event handlers at this time - they pose enough of a security risk that they're
|
|
314
|
+
// not worth preserving; there's a reason React calls it "dangerouslySetInnerHTML"!
|
|
315
|
+
|
|
316
|
+
if (key.indexOf('on') !== 0) {
|
|
317
|
+
var value = kvPair.slice(key.length + 1);
|
|
318
|
+
|
|
319
|
+
// strip the outermost single/double quote if it exists
|
|
320
|
+
if (value[0] === '"' || value[0] === '\'') {
|
|
321
|
+
value = value.slice(1, value.length - 1);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
props[ATTRIBUTE_TO_JSX_PROP_MAP[key] || key] = attributeValueToJSXPropValue(key, value) || true;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
return props;
|
|
328
|
+
}, {});
|
|
329
|
+
|
|
330
|
+
// null out .value or astToJSX() will set it as the child
|
|
331
|
+
node.value = null;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
if (node.children) {
|
|
335
|
+
node.children.forEach(coalescer);
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
ast.children.forEach(coalescer);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
export function compiler(markdown) {
|
|
343
|
+
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
|
|
344
|
+
_ref$overrides = _ref.overrides,
|
|
345
|
+
overrides = _ref$overrides === undefined ? {} : _ref$overrides;
|
|
346
|
+
|
|
347
|
+
var definitions = void 0;
|
|
348
|
+
var footnotes = void 0;
|
|
349
|
+
|
|
350
|
+
function astToJSX(ast, index) {
|
|
351
|
+
/* `this` is the dictionary of definitions */
|
|
352
|
+
if (TEXT_AST_TYPES.indexOf(ast.type) !== -1) {
|
|
353
|
+
return ast.value;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
var key = index || '0';
|
|
357
|
+
|
|
358
|
+
if (ast.type === 'code' && ast.value) {
|
|
359
|
+
var preProps = _extends({}, get(overrides, 'pre.props', {}), {
|
|
360
|
+
key: key
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
var langClassName = 'lang-' + ast.lang;
|
|
364
|
+
var codeBaseProps = get(overrides, 'code.props', {});
|
|
365
|
+
var codeProps = _extends({}, codeBaseProps, {
|
|
366
|
+
className: codeBaseProps.className ? codeBaseProps.className + ' ' + langClassName : langClassName
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
return React.createElement(get(overrides, 'pre.component', 'pre'), preProps, React.createElement(get(overrides, 'code.component', 'code'), codeProps, ast.value));
|
|
370
|
+
} /* Refers to fenced blocks, need to create a pre:code nested structure */
|
|
371
|
+
|
|
372
|
+
if (ast.type === 'list' && ast.loose === false) {
|
|
373
|
+
ast.children = ast.children.map(function (item) {
|
|
374
|
+
if (item.children.length === 1 && item.children[0].type === 'paragraph') {
|
|
375
|
+
return _extends({}, item, {
|
|
376
|
+
children: item.children[0].children
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
return item;
|
|
381
|
+
});
|
|
382
|
+
} /* tight list, remove the paragraph wrapper just inside the listItem */
|
|
383
|
+
|
|
384
|
+
if (ast.type === 'listItem') {
|
|
385
|
+
if (ast.checked === true || ast.checked === false) {
|
|
386
|
+
var liProps = _extends({}, get(overrides, 'li.props', {}), {
|
|
387
|
+
key: key
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
var inputProps = _extends({}, get(overrides, 'input.props', {}), {
|
|
391
|
+
key: 'checkbox',
|
|
392
|
+
type: 'checkbox',
|
|
393
|
+
checked: ast.checked,
|
|
394
|
+
readOnly: true
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
return React.createElement(get(overrides, 'li.component', 'li'), liProps, [React.createElement(get(overrides, 'input.component', 'input'), inputProps), ast.children.map(astToJSX)]);
|
|
398
|
+
} /* gfm task list, need to add a checkbox */
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
if (ast.type === 'html') {
|
|
402
|
+
return React.createElement('div', { key: key, dangerouslySetInnerHTML: { __html: ast.value } });
|
|
403
|
+
} /* arbitrary HTML, do the gross thing for now */
|
|
404
|
+
|
|
405
|
+
if (ast.type === 'table') {
|
|
406
|
+
var tbody = { type: 'tbody', children: [] };
|
|
407
|
+
|
|
408
|
+
ast.children = ast.children.reduce(function (children, child, index) {
|
|
409
|
+
if (index === 0) {
|
|
410
|
+
/* manually marking the first row as tableHeader since that was removed in remark@4.x; it's important semantically. */
|
|
411
|
+
child.type = 'tableHeader';
|
|
412
|
+
children.unshift(seekCellsAndAlignThemIfNecessary(child, ast.align));
|
|
413
|
+
} else if (child.type === 'tableRow') {
|
|
414
|
+
tbody.children.push(seekCellsAndAlignThemIfNecessary(child, ast.align));
|
|
415
|
+
} else if (child.type === 'tableFooter') {
|
|
416
|
+
children.push(seekCellsAndAlignThemIfNecessary(child, ast.align));
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
return children;
|
|
420
|
+
}, [tbody]);
|
|
421
|
+
} /* React yells if things aren't in the proper structure, so need to
|
|
422
|
+
delve into the immediate children and wrap tablerow(s) in a tbody */
|
|
423
|
+
|
|
424
|
+
if (ast.type === 'tableFooter') {
|
|
425
|
+
ast.children = [{
|
|
426
|
+
type: 'tr',
|
|
427
|
+
children: ast.children
|
|
428
|
+
}];
|
|
429
|
+
} /* React yells if things aren't in the proper structure, so need to
|
|
430
|
+
delve into the immediate children and wrap the cells in a tablerow */
|
|
431
|
+
|
|
432
|
+
if (ast.type === 'tableHeader') {
|
|
433
|
+
ast.children = [{
|
|
434
|
+
type: 'tr',
|
|
435
|
+
children: ast.children.map(function (child) {
|
|
436
|
+
if (child.type === 'tableCell') {
|
|
437
|
+
child.type = 'th';
|
|
438
|
+
} /* et voila, a proper table header */
|
|
439
|
+
|
|
440
|
+
return child;
|
|
441
|
+
})
|
|
442
|
+
}];
|
|
443
|
+
} /* React yells if things aren't in the proper structure, so need to
|
|
444
|
+
delve into the immediate children and wrap the cells in a tablerow */
|
|
445
|
+
|
|
446
|
+
if (ast.type === 'footnoteReference') {
|
|
447
|
+
ast.children = [{ type: 'sup', value: ast.identifier }];
|
|
448
|
+
} /* place the identifier inside a superscript tag for the link */
|
|
449
|
+
|
|
450
|
+
var htmlNodeType = getHTMLNodeTypeFromASTNodeType(ast);
|
|
451
|
+
if (htmlNodeType === null) {
|
|
452
|
+
return null;
|
|
453
|
+
} /* bail out, not convertable to any HTML representation */
|
|
454
|
+
|
|
455
|
+
var props = _extends({ key: key }, ast.props);
|
|
456
|
+
|
|
457
|
+
if (Array.isArray(ast.children) && ast.children.length === 1 && ast.children[0].type === 'html') {
|
|
458
|
+
props.dangerouslySetInnerHTML = { __html: ast.children[0].value };
|
|
459
|
+
ast.children = null;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
var override = overrides[htmlNodeType];
|
|
463
|
+
if (override) {
|
|
464
|
+
if (override.component) {
|
|
465
|
+
htmlNodeType = override.component;
|
|
466
|
+
} /* sub out the normal html tag name for the JSX / ReactFactory
|
|
467
|
+
passed in by the caller */
|
|
468
|
+
|
|
469
|
+
if (override.props) {
|
|
470
|
+
props = _extends({}, override.props, props);
|
|
471
|
+
} /* apply the prop overrides beneath the minimal set that are necessary
|
|
472
|
+
to have the markdown conversion work as expected */
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
/* their props + our props, with any duplicate keys overwritten by us
|
|
476
|
+
(necessary evil, file an issue if something comes up that needs
|
|
477
|
+
extra attention, only props specified in `formExtraPropsForHTMLNodeType`
|
|
478
|
+
will be overwritten on a key collision) */
|
|
479
|
+
var finalProps = formExtraPropsForHTMLNodeType(props, ast, definitions);
|
|
480
|
+
|
|
481
|
+
if (ast.children && ast.children.length === 1) {
|
|
482
|
+
if (TEXT_AST_TYPES.indexOf(ast.children[0].type) !== -1) {
|
|
483
|
+
ast.children = ast.children[0].value;
|
|
484
|
+
}
|
|
485
|
+
} /* solitary text children don't need full parsing or React will add a wrapper */
|
|
486
|
+
|
|
487
|
+
var children = Array.isArray(ast.children) ? ast.children.map(astToJSX) : ast.children;
|
|
488
|
+
|
|
489
|
+
return React.createElement(htmlNodeType, finalProps, ast.value || children);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
if (typeof markdown !== 'string') {
|
|
493
|
+
throw new Error('markdown-to-jsx: the first argument must be\n a string');
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
if (getType.call(overrides) !== '[object Object]') {
|
|
497
|
+
throw new Error('markdown-to-jsx: options.overrides (second argument property) must be\n undefined or an object literal with shape:\n {\n htmltagname: {\n component: string|ReactComponent(optional),\n props: object(optional)\n }\n }');
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
var remarkAST = unified().data('settings', {
|
|
501
|
+
footnotes: true,
|
|
502
|
+
gfm: true,
|
|
503
|
+
position: false
|
|
504
|
+
}).use(parser).parse(markdown);
|
|
505
|
+
|
|
506
|
+
var extracted = extractDefinitionsFromASTTree(remarkAST, astToJSX);
|
|
507
|
+
|
|
508
|
+
definitions = extracted.definitions;
|
|
509
|
+
footnotes = extracted.footnotes;
|
|
510
|
+
|
|
511
|
+
coalesceInlineHTML(remarkAST);
|
|
512
|
+
|
|
513
|
+
var jsx = astToJSX(remarkAST);
|
|
514
|
+
|
|
515
|
+
// discard the root <div> node if there is only one valid initial child
|
|
516
|
+
if (jsx.props.children && jsx.props.children.length === 1) {
|
|
517
|
+
jsx = jsx.props.children[0];
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
if (footnotes.length) {
|
|
521
|
+
jsx.props.children.push(React.createElement(
|
|
522
|
+
'footer',
|
|
523
|
+
{ key: 'footnotes' },
|
|
524
|
+
footnotes
|
|
525
|
+
));
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
return jsx;
|
|
529
|
+
};
|
|
530
|
+
|
|
531
|
+
/**
|
|
532
|
+
* A simple HOC for easy React use. Feed the markdown content as a direct child
|
|
533
|
+
* and the rest is taken care of automatically.
|
|
534
|
+
*
|
|
535
|
+
* @param {String} options.children must be a string
|
|
536
|
+
* @param {Object} options.options markdown-to-jsx options (arg 2 of the compiler)
|
|
537
|
+
*
|
|
538
|
+
* @return {ReactElement} the compiled JSX
|
|
539
|
+
*/
|
|
540
|
+
var Component = function Component(_ref2) {
|
|
541
|
+
var children = _ref2.children,
|
|
542
|
+
options = _ref2.options,
|
|
543
|
+
props = _objectWithoutProperties(_ref2, ['children', 'options']);
|
|
544
|
+
|
|
545
|
+
return compiler(children, options);
|
|
546
|
+
};
|
|
547
|
+
|
|
548
|
+
Component.propTypes = {
|
|
549
|
+
children: PropTypes.string.isRequired,
|
|
550
|
+
options: PropTypes.object
|
|
551
|
+
};
|
|
552
|
+
|
|
553
|
+
export default Component;
|
package/index.js
CHANGED
|
@@ -6,55 +6,57 @@ import parser from 'remark-parse';
|
|
|
6
6
|
|
|
7
7
|
const BLOCK_ELEMENT_TAGS = [
|
|
8
8
|
'article',
|
|
9
|
-
'header',
|
|
10
9
|
'aside',
|
|
11
|
-
'hgroup',
|
|
12
10
|
'blockquote',
|
|
13
|
-
'hr',
|
|
14
|
-
'iframe',
|
|
15
11
|
'body',
|
|
16
|
-
'li',
|
|
17
|
-
'map',
|
|
18
12
|
'button',
|
|
19
|
-
'object',
|
|
20
13
|
'canvas',
|
|
21
|
-
'ol',
|
|
22
14
|
'caption',
|
|
23
|
-
'output',
|
|
24
15
|
'col',
|
|
25
|
-
'p',
|
|
26
16
|
'colgroup',
|
|
27
|
-
'pre',
|
|
28
17
|
'dd',
|
|
29
|
-
'
|
|
18
|
+
'details',
|
|
30
19
|
'div',
|
|
31
|
-
'section',
|
|
32
20
|
'dl',
|
|
33
|
-
'table',
|
|
34
|
-
'td',
|
|
35
21
|
'dt',
|
|
36
|
-
'tbody',
|
|
37
22
|
'embed',
|
|
38
|
-
'textarea',
|
|
39
23
|
'fieldset',
|
|
40
|
-
'tfoot',
|
|
41
24
|
'figcaption',
|
|
42
|
-
'th',
|
|
43
25
|
'figure',
|
|
44
|
-
'thead',
|
|
45
26
|
'footer',
|
|
46
|
-
'tr',
|
|
47
27
|
'form',
|
|
48
|
-
'ul',
|
|
49
28
|
'h1',
|
|
50
29
|
'h2',
|
|
51
30
|
'h3',
|
|
52
31
|
'h4',
|
|
53
32
|
'h5',
|
|
54
33
|
'h6',
|
|
55
|
-
'
|
|
34
|
+
'header',
|
|
35
|
+
'hgroup',
|
|
36
|
+
'hr',
|
|
37
|
+
'iframe',
|
|
38
|
+
'li',
|
|
39
|
+
'map',
|
|
40
|
+
'object',
|
|
41
|
+
'ol',
|
|
42
|
+
'output',
|
|
43
|
+
'p',
|
|
44
|
+
'pre',
|
|
45
|
+
'progress',
|
|
56
46
|
'script',
|
|
47
|
+
'section',
|
|
57
48
|
'style',
|
|
49
|
+
'summary',
|
|
50
|
+
'table',
|
|
51
|
+
'tbody',
|
|
52
|
+
'td',
|
|
53
|
+
'textarea',
|
|
54
|
+
'tfoot',
|
|
55
|
+
'th',
|
|
56
|
+
'thead',
|
|
57
|
+
'tr',
|
|
58
|
+
'ul',
|
|
59
|
+
'video',
|
|
58
60
|
];
|
|
59
61
|
const BLOCK_ELEMENT_REGEX = new RegExp(`^<(${BLOCK_ELEMENT_TAGS.join('|')})`, 'i');
|
|
60
62
|
|
|
@@ -334,6 +336,9 @@ function coalesceInlineHTML(ast) {
|
|
|
334
336
|
if (node.type === 'html') {
|
|
335
337
|
if (!isCoalesceableHTML(node.value)) {
|
|
336
338
|
return;
|
|
339
|
+
} else if (node.value.indexOf('<!--') !== -1) {
|
|
340
|
+
// throw out HTML comments
|
|
341
|
+
siblings.splice(index, 1);
|
|
337
342
|
}
|
|
338
343
|
|
|
339
344
|
// are there more html nodes directly after? if so, fold them into the current node
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Interprets markdown text and outputs a JSX equivalent.",
|
|
4
4
|
"homepage": "http://probablyup.github.io/markdown-to-jsx",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "5.
|
|
6
|
+
"version": "5.4.2",
|
|
7
7
|
"engines": {
|
|
8
8
|
"node": ">= 4"
|
|
9
9
|
},
|
|
@@ -18,38 +18,41 @@
|
|
|
18
18
|
"bugs": "https://github.com/probablyup/markdown-to-jsx/issues",
|
|
19
19
|
"files": [
|
|
20
20
|
"index.js",
|
|
21
|
-
"index.
|
|
21
|
+
"index.cjs.js",
|
|
22
|
+
"index.esm.js",
|
|
22
23
|
"LICENSE",
|
|
23
24
|
"README.md"
|
|
24
25
|
],
|
|
25
|
-
"main": "index.
|
|
26
|
-
"jsnext:main": "index.js",
|
|
27
|
-
"module": "index.js",
|
|
26
|
+
"main": "index.cjs.js",
|
|
27
|
+
"jsnext:main": "index.esm.js",
|
|
28
|
+
"module": "index.esm.js",
|
|
28
29
|
"devDependencies": {
|
|
29
|
-
"autoprefixer-stylus": "^0.13.0",
|
|
30
30
|
"babel-cli": "^6.14.0",
|
|
31
|
-
"babel-jest": "^
|
|
31
|
+
"babel-jest": "^20.0.3",
|
|
32
|
+
"babel-loader": "^7.1.1",
|
|
33
|
+
"babel-plugin-styled-components": "^1.1.7",
|
|
34
|
+
"babel-plugin-transform-react-remove-prop-types": "^0.4.6",
|
|
32
35
|
"babel-preset-es2015": "^6.14.0",
|
|
33
36
|
"babel-preset-react": "^6.11.1",
|
|
34
37
|
"babel-preset-stage-2": "^6.13.0",
|
|
35
|
-
"babelify": "^7.3.0",
|
|
36
|
-
"browserify": "^14.1.0",
|
|
37
|
-
"budo": "^9.2.0",
|
|
38
|
-
"bundle-collapser": "^1.2.1",
|
|
39
38
|
"codecov": "^2.1.0",
|
|
40
39
|
"in-publish": "^2.0.0",
|
|
41
|
-
"jest
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
40
|
+
"jest": "^20.0.4",
|
|
41
|
+
"polished": "^1.3.0",
|
|
42
|
+
"preact": "^8.2.1",
|
|
43
|
+
"preact-compat": "^3.16.0",
|
|
44
|
+
"react": "^15.6.1",
|
|
45
|
+
"react-dom": "^15.6.1",
|
|
46
|
+
"styled-components": "^2.1.1",
|
|
45
47
|
"uglify-js": "^2.7.3",
|
|
46
|
-
"
|
|
48
|
+
"webpack": "^3.4.1",
|
|
49
|
+
"webpack-dev-server": "^2.6.1"
|
|
47
50
|
},
|
|
48
51
|
"dependencies": {
|
|
49
52
|
"lodash.get": "^4.4.2",
|
|
50
|
-
"prop-types": "^15.5.
|
|
51
|
-
"remark-parse": "^
|
|
52
|
-
"unified": "^6.1.
|
|
53
|
+
"prop-types": "^15.5.10",
|
|
54
|
+
"remark-parse": "^4.0.0",
|
|
55
|
+
"unified": "^6.1.5"
|
|
53
56
|
},
|
|
54
57
|
"peerDependencies": {
|
|
55
58
|
"react": ">= 0.14.0"
|
|
@@ -62,16 +65,10 @@
|
|
|
62
65
|
]
|
|
63
66
|
},
|
|
64
67
|
"scripts": {
|
|
65
|
-
"prepublish": "in-publish && npm run
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"site:css:watch": "npm run site:css -- -w -m -l --sourcemap-inline",
|
|
70
|
-
"site:js": "browserify site.js -t babelify -p bundle-collapser/plugin",
|
|
71
|
-
"site:js:release": "NODE_ENV=production npm run -s site:js | uglifyjs -mc drop_console --screw-ie8 -o docs/js/bundle.js",
|
|
72
|
-
"site:js:watch": "budo site.js:js/bundle.js -d docs -H 0.0.0.0 --colors --live --open --pushstate --iw -- -t babelify",
|
|
73
|
-
"site:release": "npm run site:css:release && npm run site:js:release",
|
|
74
|
-
"start": "sh scripts/parallelize.sh \"npm run site:css:watch\" \"npm run site:js:watch\"",
|
|
68
|
+
"prepublish": "in-publish && npm run build || not-in-publish",
|
|
69
|
+
"build": "babel index.js --out-file index.cjs.js && BABEL_ENV=esm babel index.js --out-file index.esm.js",
|
|
70
|
+
"release": "webpack --config ./webpack.release.config.babel.js -p --display-optimization-bailout",
|
|
71
|
+
"start": "webpack-dev-server --hot --inline --open",
|
|
75
72
|
"test": "jest --verbose"
|
|
76
73
|
}
|
|
77
74
|
}
|