Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
parse: (capture, parse, state) => {
const content = capture[0].replace(/^ *> */gm, '')
const blockQuoteRecursionLevel = state.blockQuoteRecursionLevel || 0
const nextState = {...state, blockQuoteRecursionLevel: blockQuoteRecursionLevel + 1}
return {
content: parse(content, nextState),
}
},
},
del: {
...SimpleMarkdown.defaultRules.del,
// original:
// match: inlineRegex(/^~~(?=\S)([\s\S]*?\S)~~/),
// ours: single tilde doesn't cross a newline
match: wordBoundryLookBehindMatch(SimpleMarkdown.inlineRegex(/^~((?:\\[\s\S]|[^\\\n])+?)~(?!~)/)),
},
em: {
...SimpleMarkdown.defaultRules.em,
// original is pretty long so not inlining it here
// ours: wrapped in _'s
match: wordBoundryLookBehindMatch(SimpleMarkdown.inlineRegex(/^_((?:\\[\s\S]|[^\\\n])+?)_(?!_)/)),
},
emoji: {
match: SimpleMarkdown.inlineRegex(emojiRegex),
order: SimpleMarkdown.defaultRules.text.order - 0.5,
parse: function(capture, parse, state) {
// If it's a unicode emoji, let's get it's shortname
const shortName = emojiIndexByChar[capture[0]]
return {content: shortName || capture[0]}
},
},
}
},
text: {
...SimpleMarkdown.defaultRules.text,
parse(capture, recurseParse, state) {
return state.nested ? {
content: capture[0]
} : recurseParse(translateSurrogatesToInlineEmoji(capture[0]), {
...state,
nested: true
});
}
},
s: {
order: SimpleMarkdown.defaultRules.u.order,
match: SimpleMarkdown.inlineRegex(/^~~([\s\S]+?)~~(?!_)/),
parse: SimpleMarkdown.defaultRules.u.parse
}
};
function createRules(r) {
const paragraph = r.paragraph;
const url = r.url;
const link = r.link;
const codeBlock = r.codeBlock;
const inlineCode = r.inlineCode;
return {
// rules we don't care about:
// mention
// channel
// highlight
})();
function translateSurrogatesToInlineEmoji(surrogates) {
return surrogates.replace(replacer, (_, match) => convertSurrogateToName(match));
}
// i am not sure why are these rules split like this.
const baseRules = {
newline: SimpleMarkdown.defaultRules.newline,
paragraph: SimpleMarkdown.defaultRules.paragraph,
escape: SimpleMarkdown.defaultRules.escape,
link: SimpleMarkdown.defaultRules.link,
autolink: {
...SimpleMarkdown.defaultRules.autolink,
match: SimpleMarkdown.inlineRegex(/^<(https?:\/\/[^ >]+)>/)
},
url: SimpleMarkdown.defaultRules.url,
strong: SimpleMarkdown.defaultRules.strong,
em: SimpleMarkdown.defaultRules.em,
u: SimpleMarkdown.defaultRules.u,
br: SimpleMarkdown.defaultRules.br,
inlineCode: SimpleMarkdown.defaultRules.inlineCode,
emoticon: {
order: SimpleMarkdown.defaultRules.text.order,
match: function(source) {
return /^(¯\\_\(ツ\)_\/¯)/.exec(source);
},
parse: function(capture) {
return { type: 'text', content: capture[1] };
}
},
},
});
var RefEnd = React.createClass({
render: function() {
return <span style="{REF_STYLE}">_</span>;
},
});
var rules = {
newline: SimpleMarkdown.defaultRules.newline,
paragraph: SimpleMarkdown.defaultRules.paragraph,
escape: SimpleMarkdown.defaultRules.escape,
passageFootnote: {
order: SimpleMarkdown.defaultRules.escape.order + 0.1,
match: SimpleMarkdown.inlineRegex(/^\^/),
parse: (capture, parse, state) => {
// if no footnotes have been seen, we're id 1. otherwise,
// we're the next subsequent id
var id = state.lastFootnote.id + 1;
var footnote = {
id: id,
// our text is what to output. if there is only one footnote,
// it's a *; otherwise it's a superscript number
text: id === 1 ? "*" : "" + id,
};
// If the previous footnote was a *, we need to adjust it to be
// a number, since now we know there is more than one footnote
if (state.lastFootnote.text === "*") {
state.lastFootnote.text = "" + state.lastFootnote.id;
}
// This copies the functionality of this named group
// $FlowIssue treat this like a RegExp
const linkRegex: RegExp = {
exec: source => {
const result = _linkRegex.exec(source)
if (result) {
result.groups = {tld: result[4]}
return result
}
return null
},
}
// Only allow a small set of characters before a url
const beforeLinkRegex = /[\s/(]/
const inlineLinkMatch = SimpleMarkdown.inlineRegex(linkRegex)
const textMatch = SimpleMarkdown.anyScopeRegex(
new RegExp(
// [\s\S]+? any char, at least 1 - lazy
// (?= // Positive look ahead. It should have these chars ahead
// // This is kinda weird, but for the regex to terminate it should have these cases be true ahead of its termination
// [^0-9A-Za-z\s] not a character in this set. So don't terminate if there is still more normal chars to eat
// | [\u00c0-\uffff] OR any unicode char. If there is a weird unicode ahead, we terminate
// | [\w-_.]+@ // OR something that looks like it starts an email. If there is an email looking thing ahead stop here.
// | (\w+\.)+(${commonTlds.join('|')}) // OR there is a url with a common tld ahead. Stop if there's a common url ahead
// | \w+:\S // OR there's letters before a : so stop here.
// | $ // OR we reach the end of the line
// )
`^[\\s\\S]+?(?=[^0-9A-Za-z\\s]|[\\u00c0-\\uffff]|[\\w-_.]+@|(\\w+\\.)+(${commonTlds.join(
'|'
)})|\\n|\\w+:\\S|$)`
)
serviceDecoration: {
match: (source, state, lookBehind) => {
return serviceDecorationMatcher(source, state, lookBehind)
},
order: 1,
parse: capture => ({
content: capture[1],
type: 'serviceDecoration',
}),
},
strong: {
...SimpleMarkdown.defaultRules.strong,
// original
// match: inlineRegex(/^\*\*((?:\\[\s\S]|[^\\])+?)\*\*(?!\*)/),
// ours: single stars
match: wordBoundryLookBehindMatch(SimpleMarkdown.inlineRegex(/^\*((?:\\[\s\S]|[^\\\n])+?)\*(?!\*)/)),
},
text: {
...SimpleMarkdown.defaultRules.text,
// original:
// /^[\s\S]+?(?=[^0-9A-Za-z\s\u00c0-\uffff]|\n\n| {2,}\n|\w+:\S|$)/
// ours: stop on single new lines and common tlds. We want to stop at common tlds so this regex doesn't
// consume the common case of saying: Checkout google.com, they got all the cool gizmos.
match: (source, state, lookBehind) =>
Styles.isMobile && !state.inParagraph ? null : textMatch(source, state, lookBehind),
},
}
const simpleMarkdownParser = SimpleMarkdown.parserFor(rules)
const isAllEmoji = ast => {
const trimmed = ast.filter(n => n.type !== 'newline')
node.table,
output,
state
) : // :( (middle of the ternary expression)
"//invalid table//";
return <div>
<div>
{output(node.title, state)}
</div>
<div>{tableOutput}</div>
</div>;
},
},
widget: {
order: SimpleMarkdown.defaultRules.link.order - 0.75,
match: SimpleMarkdown.inlineRegex(Util.rWidgetRule),
parse: (capture, parse, state) => {
return {
id: capture[1],
widgetType: capture[2],
};
},
react: (node, output, state) => {
// The actual output is handled in the renderer, where
// we know the current widget props/state. This is
// just a stub for testing.
return <em>
[Widget: {node.id}]
</em>;
},
},
blockMath: {
parse: (capture, parse, state) => {
return {
content: capture[1],
};
},
react: (node, output, state) => {
return [
<span>
{node.content}
</span>,
];
},
},
reviewHighlight: {
order: SimpleMarkdown.defaultRules.escape.order + 0.7,
match: SimpleMarkdown.inlineRegex(
/^{review-highlighting.start}(.+?){review-highlighting.end}/
),
parse: (capture, parse, state) => {
return {
content: capture[1],
};
},
react: (node, output, state) => {
return [
<span>
{node.content}
</span>,
];
},
},
strong: SimpleMarkdown.defaultRules.strong,
}
return image;
},
},
inlineCode: {
parse: parseCaptureInline,
react: function (node, output, {...state}) {
state.withinText = true;
return React.createElement(Text, {
key: state.key,
style: styles.inlineCode,
}, output(node.content, state));
},
},
link: {
match: SimpleMarkdown.inlineRegex(new RegExp(
'^\\[(' + LINK_INSIDE + ')\\]\\(' + LINK_HREF_AND_TITLE + '\\)'
)),
react: function (node, output, {...state}) {
state.withinLink = true;
const _pressHandler = () => {
pressHandler(node.target);
};
const link = React.createElement(Text, {
key: state.key,
style: styles.autolink,
onPress: _pressHandler,
}, output(node.content, state));
state.withinLink = false;
return link;
},
},
react: (node, _, state) => (
{node.content}
),
},
roleMention: {
order: defaultRules.text.order,
match: inlineRegex(/^<@&\d+>/),
parse: () => ({
type: "mention",
content: "@unknown-role",
}),
react: null,
},
channelMention: {
order: defaultRules.text.order,
match: inlineRegex(/^<#\d+>/),
parse: () => ({
type: "mention",
content: "#unknown-channel",
}),
react: null,
},
}
const parseInline = parserFor(inlineRules, { inline: true })
const parseBlock = parserFor(blockRules, { inline: true })
const reactOutput = outputFor({ ...inlineRules, ...blockRules }, "react")
const ellipsize = (text: string, length: number) => {
const shortenedText = text.replace(/\s+/g, " ")
return shortenedText.length <= length
? shortenedText