forked from Ivasoft/mattermost-mobile
352 lines
12 KiB
Diff
352 lines
12 KiB
Diff
diff --git a/node_modules/commonmark-react-renderer/src/commonmark-react-renderer.js b/node_modules/commonmark-react-renderer/src/commonmark-react-renderer.js
|
|
index 91b0001..05b80fa 100644
|
|
--- a/node_modules/commonmark-react-renderer/src/commonmark-react-renderer.js
|
|
+++ b/node_modules/commonmark-react-renderer/src/commonmark-react-renderer.js
|
|
@@ -12,7 +12,12 @@ var typeAliases = {
|
|
htmlblock: 'html_block',
|
|
htmlinline: 'html_inline',
|
|
codeblock: 'code_block',
|
|
- hardbreak: 'linebreak'
|
|
+ hardbreak: 'linebreak',
|
|
+ atmention: 'at_mention',
|
|
+ channellink: 'channel_link',
|
|
+ editedindicator: 'edited_indicator',
|
|
+ tableRow: 'table_row',
|
|
+ tableCell: 'table_cell'
|
|
};
|
|
|
|
var defaultRenderers = {
|
|
@@ -24,6 +29,7 @@ var defaultRenderers = {
|
|
link: 'a',
|
|
paragraph: 'p',
|
|
strong: 'strong',
|
|
+ del: 'del',
|
|
thematic_break: 'hr', // eslint-disable-line camelcase
|
|
|
|
html_block: HtmlRenderer, // eslint-disable-line camelcase
|
|
@@ -52,7 +58,71 @@ var defaultRenderers = {
|
|
},
|
|
|
|
text: null,
|
|
- softbreak: null
|
|
+ softbreak: null,
|
|
+
|
|
+ at_mention: function AtMention(props) {
|
|
+ var newProps = getCoreProps(props);
|
|
+ if (props.username) {
|
|
+ props['data-mention-name'] = props.username;
|
|
+ }
|
|
+
|
|
+ return createElement('span', newProps, props.children);
|
|
+ },
|
|
+ channel_link: function ChannelLink(props) {
|
|
+ var newProps = getCoreProps(props);
|
|
+ if (props.channelName) {
|
|
+ props['data-channel-name'] = props.channelName;
|
|
+ }
|
|
+
|
|
+ return createElement('span', newProps, props.children);
|
|
+ },
|
|
+ emoji: function Emoji(props) {
|
|
+ var newProps = getCoreProps(props);
|
|
+ if (props.emojiName) {
|
|
+ props['data-emoji-name'] = props.emojiName;
|
|
+ }
|
|
+
|
|
+ return createElement('span', newProps, props.children);
|
|
+ },
|
|
+ edited_indicator: null,
|
|
+ hashtag: function Hashtag(props) {
|
|
+ var newProps = getCoreProps(props);
|
|
+ if (props.hashtag) {
|
|
+ props['data-hashtag'] = props.hashtag;
|
|
+ }
|
|
+
|
|
+ return createElement('span', newProps, props.children);
|
|
+ },
|
|
+ mention_highlight: function MentionHighlight(props) {
|
|
+ var newProps = getCoreProps(props);
|
|
+ newProps['data-mention-highlight'] = 'true';
|
|
+ return createElement('span', newProps, props.children);
|
|
+ },
|
|
+ search_highlight: function SearchHighlight(props) {
|
|
+ var newProps = getCoreProps(props);
|
|
+ newProps['data-search-highlight'] = 'true';
|
|
+ return createElement('span', newProps, props.children);
|
|
+ },
|
|
+
|
|
+ table: function Table(props) {
|
|
+ var childrenArray = React.Children.toArray(props.children);
|
|
+
|
|
+ var children = [createElement('thead', {'key': 'thead'}, childrenArray.slice(0, 1))];
|
|
+ if (childrenArray.length > 1) {
|
|
+ children.push(createElement('tbody', {'key': 'tbody'}, childrenArray.slice(1)));
|
|
+ }
|
|
+
|
|
+ return createElement('table', getCoreProps(props), children);
|
|
+ },
|
|
+ table_row: 'tr',
|
|
+ table_cell: function TableCell(props) {
|
|
+ var newProps = getCoreProps(props);
|
|
+ if (props.align) {
|
|
+ newProps.className = 'align-' + props.align;
|
|
+ }
|
|
+
|
|
+ return createElement('td', newProps, props.children);
|
|
+ }
|
|
};
|
|
|
|
var coreTypes = Object.keys(defaultRenderers);
|
|
@@ -147,7 +217,7 @@ function flattenPosition(pos) {
|
|
}
|
|
|
|
// For some nodes, we want to include more props than for others
|
|
-function getNodeProps(node, key, opts, renderer) {
|
|
+function getNodeProps(node, key, opts, renderer, context) {
|
|
var props = { key: key }, undef;
|
|
|
|
// `sourcePos` is true if the user wants source information (line/column info from markdown source)
|
|
@@ -194,16 +264,49 @@ function getNodeProps(node, key, opts, renderer) {
|
|
|
|
// Commonmark treats image description as children. We just want the text
|
|
props.alt = node.react.children.join('');
|
|
- node.react.children = undef;
|
|
break;
|
|
case 'list':
|
|
props.start = node.listStart;
|
|
props.type = node.listType;
|
|
props.tight = node.listTight;
|
|
break;
|
|
+ case 'at_mention':
|
|
+ props.mentionName = node.mentionName;
|
|
+ break;
|
|
+ case 'channel_link':
|
|
+ props.channelName = node.channelName;
|
|
+ break;
|
|
+ case 'emoji':
|
|
+ props.emojiName = node.emojiName;
|
|
+ props.literal = node.literal;
|
|
+ break;
|
|
+ case 'hashtag':
|
|
+ props.hashtag = node.hashtag;
|
|
+ break;
|
|
+ case 'paragraph':
|
|
+ props.first = !(node._prev && node._prev.type === 'paragraph');
|
|
+ props.last = !(node._next && node._next.type === 'paragraph');
|
|
+ break;
|
|
+ case 'edited_indicator':
|
|
+ break;
|
|
+ case 'table':
|
|
+ props.numRows = countRows(node);
|
|
+ props.numColumns = countColumns(node);
|
|
+ break;
|
|
+ case 'table_row':
|
|
+ props.isHeading = node.isHeading;
|
|
+ break;
|
|
+ case 'table_cell':
|
|
+ props.isHeading = node.isHeading;
|
|
+ props.align = node.align;
|
|
+ break;
|
|
default:
|
|
}
|
|
|
|
+ if (opts.getExtraPropsForNode) {
|
|
+ props = Object.assign(props, opts.getExtraPropsForNode(node));
|
|
+ }
|
|
+
|
|
if (typeof renderer !== 'string') {
|
|
props.literal = node.literal;
|
|
}
|
|
@@ -213,9 +316,29 @@ function getNodeProps(node, key, opts, renderer) {
|
|
props.children = children.reduce(reduceChildren, []) || null;
|
|
}
|
|
|
|
+ props.context = context.slice();
|
|
+
|
|
return props;
|
|
}
|
|
|
|
+function countChildren(node) {
|
|
+ var count = 0;
|
|
+
|
|
+ for (var child = node.firstChild; child; child = child.next) {
|
|
+ count += 1;
|
|
+ }
|
|
+
|
|
+ return count;
|
|
+}
|
|
+
|
|
+function countRows(table) {
|
|
+ return countChildren(table);
|
|
+}
|
|
+
|
|
+function countColumns(table) {
|
|
+ return countChildren(table.firstChild);
|
|
+}
|
|
+
|
|
function getPosition(node) {
|
|
if (!node) {
|
|
return null;
|
|
@@ -238,26 +361,23 @@ function renderNodes(block) {
|
|
transformLinkUri: this.transformLinkUri,
|
|
transformImageUri: this.transformImageUri,
|
|
softBreak: this.softBreak,
|
|
- linkTarget: this.linkTarget
|
|
+ linkTarget: this.linkTarget,
|
|
+ getExtraPropsForNode: this.getExtraPropsForNode
|
|
};
|
|
|
|
- var e, node, entering, leaving, type, doc, key, nodeProps, prevPos, prevIndex = 0;
|
|
+ var e;
|
|
+ var doc;
|
|
+ var context = [];
|
|
+ var index = 0;
|
|
while ((e = walker.next())) {
|
|
- var pos = getPosition(e.node.sourcepos ? e.node : e.node.parent);
|
|
- if (prevPos === pos) {
|
|
- key = pos + prevIndex;
|
|
- prevIndex++;
|
|
- } else {
|
|
- key = pos;
|
|
- prevIndex = 0;
|
|
- }
|
|
+ var key = String(index);
|
|
+ index += 1;
|
|
|
|
- prevPos = pos;
|
|
- entering = e.entering;
|
|
- leaving = !entering;
|
|
- node = e.node;
|
|
- type = normalizeTypeName(node.type);
|
|
- nodeProps = null;
|
|
+ var entering = e.entering;
|
|
+ var leaving = !entering;
|
|
+ var node = e.node;
|
|
+ var type = normalizeTypeName(node.type);
|
|
+ var nodeProps = null;
|
|
|
|
// If we have not assigned a document yet, assume the current node is just that
|
|
if (!doc) {
|
|
@@ -270,7 +390,7 @@ function renderNodes(block) {
|
|
}
|
|
|
|
// In HTML, we don't want paragraphs inside of list items
|
|
- if (type === 'paragraph' && isGrandChildOfList(node)) {
|
|
+ if (!this.renderParagraphsInLists && type === 'paragraph' && isGrandChildOfList(node)) {
|
|
continue;
|
|
}
|
|
|
|
@@ -289,7 +409,7 @@ function renderNodes(block) {
|
|
if (this.allowNode && (isCompleteParent || !node.isContainer)) {
|
|
var nodeChildren = isCompleteParent ? node.react.children : [];
|
|
|
|
- nodeProps = getNodeProps(node, key, propOptions, renderer);
|
|
+ nodeProps = getNodeProps(node, key, propOptions, renderer, context);
|
|
disallowedByUser = !this.allowNode({
|
|
type: pascalCase(type),
|
|
renderer: this.renderers[type],
|
|
@@ -298,6 +418,30 @@ function renderNodes(block) {
|
|
});
|
|
}
|
|
|
|
+ if (node.isContainer) {
|
|
+ var contextType = node.type;
|
|
+ if (node.level) {
|
|
+ contextType = node.type + node.level;
|
|
+ } else if (node.type === 'table_row' && node.parent.firstChild === node) {
|
|
+ contextType = 'table_header_row';
|
|
+ } else {
|
|
+ contextType = node.type;
|
|
+ }
|
|
+
|
|
+ if (entering) {
|
|
+ context.push(contextType);
|
|
+ } else {
|
|
+ var popped = context.pop();
|
|
+
|
|
+ if (!popped) {
|
|
+ throw new Error('Attempted to pop empty stack');
|
|
+ } else if (!popped === contextType) {
|
|
+ throw new Error('Popped context of type `' + pascalCase(popped) +
|
|
+ '` when expecting context of type `' + pascalCase(contextType) + '`');
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
if (!isDocument && (disallowedByUser || disallowedByConfig)) {
|
|
if (!this.unwrapDisallowed && entering && node.isContainer) {
|
|
walker.resumeAt(node, false);
|
|
@@ -313,15 +457,25 @@ function renderNodes(block) {
|
|
);
|
|
}
|
|
|
|
- if (node.isContainer && entering) {
|
|
+ if (context.length > this.maxDepth) {
|
|
+ // Do nothing, we should not regularly be nested this deeply and we don't want to cause React to
|
|
+ // overflow the stack
|
|
+ } else if (node.isContainer && entering) {
|
|
node.react = {
|
|
component: renderer,
|
|
props: {},
|
|
children: []
|
|
};
|
|
} else {
|
|
- var childProps = nodeProps || getNodeProps(node, key, propOptions, renderer);
|
|
- if (renderer) {
|
|
+ var childProps = nodeProps || getNodeProps(node, key, propOptions, renderer, context);
|
|
+ if (renderer === ReactRenderer.forwardChildren) {
|
|
+ if (childProps.children) {
|
|
+ for (var i = 0; i < childProps.children.length; i++) {
|
|
+ var child = childProps.children[i];
|
|
+ addChild(node, child);
|
|
+ }
|
|
+ }
|
|
+ } else if (renderer) {
|
|
childProps = typeof renderer === 'string'
|
|
? childProps
|
|
: assign(childProps, {nodeKey: childProps.key});
|
|
@@ -341,6 +495,10 @@ function renderNodes(block) {
|
|
}
|
|
}
|
|
|
|
+ if (context.length !== 0) {
|
|
+ throw new Error('Expected context to be empty after rendering, but has `' + context.join(', ') + '`');
|
|
+ }
|
|
+
|
|
return doc.react.children;
|
|
}
|
|
|
|
@@ -401,21 +559,31 @@ function ReactRenderer(options) {
|
|
renderers: assign({}, defaultRenderers, normalizeRenderers(opts.renderers)),
|
|
escapeHtml: Boolean(opts.escapeHtml),
|
|
skipHtml: Boolean(opts.skipHtml),
|
|
+ renderParagraphsInLists: Boolean(opts.renderParagraphsInLists),
|
|
transformLinkUri: linkFilter,
|
|
transformImageUri: imageFilter,
|
|
allowNode: opts.allowNode,
|
|
allowedTypes: allowedTypes,
|
|
unwrapDisallowed: Boolean(opts.unwrapDisallowed),
|
|
render: renderNodes,
|
|
- linkTarget: opts.linkTarget || false
|
|
+ linkTarget: opts.linkTarget || false,
|
|
+ maxDepth: opts.maxDepth || 30,
|
|
+ getExtraPropsForNode: opts.getExtraPropsForNode
|
|
};
|
|
}
|
|
|
|
+function forwardChildren(props) {
|
|
+ return props.children;
|
|
+}
|
|
+
|
|
ReactRenderer.uriTransformer = defaultLinkUriFilter;
|
|
ReactRenderer.types = coreTypes.map(pascalCase);
|
|
ReactRenderer.renderers = coreTypes.reduce(function(renderers, type) {
|
|
renderers[pascalCase(type)] = defaultRenderers[type];
|
|
return renderers;
|
|
}, {});
|
|
+ReactRenderer.countRows = countRows;
|
|
+ReactRenderer.countColumns = countColumns;
|
|
+ReactRenderer.forwardChildren = forwardChildren;
|
|
|
|
module.exports = ReactRenderer;
|