Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
//
// * but this is not part of the same item
const LIST_ITEM_R = new RegExp(
LIST_ITEM_PREFIX +
'[^\\n]*(?:\\n' +
`(?!\\1${LIST_BULLET} )[^\\n]*)*(\n|$)`,
'gm'
);
const BLOCK_END_R = /\n{2,}$/;
// recognize the end of a paragraph block inside a list item:
// two or more newlines at end end of the item
const LIST_BLOCK_END_R = BLOCK_END_R;
const LIST_ITEM_END_R = / *\n+$/;
const rule = {
...SimpleMarkdown.defaultRules.list,
match: function (source, state, prevCapture) {
// We only want to break into a list if we are at the start of a
// line. This is to avoid parsing "hi * there" with "* there"
// becoming a part of a list.
// You might wonder, "but that's inline, so of course it wouldn't
// start a list?". You would be correct! Except that some of our
// lists can be inline, because they might be inside another list,
// in which case we can parse with inline scope, but need to allow
// nested lists inside this inline scope.
const isStartOfLine = LIST_LOOKBEHIND_R.test(prevCapture);
if (isStartOfLine) {
return LIST_R.exec(source);
} else {
_.merge(
{},
SimpleMarkdown.defaultRules,
initialRules(mergedStyles),
this.props.rules,
),
)
const child = Array.isArray(this.props.children)
? this.props.children.join('')
: this.props.children
// @TODO: Add another \n?
const blockSource = `${child}\n`
const tree = SimpleMarkdown.parserFor(rules)(blockSource, {
inline: false,
})
return SimpleMarkdown.reactFor(SimpleMarkdown.ruleOutput(rules, 'react'))(
tree,
)
}
catch (errors) {
this.props.errorHandler
? this.props.errorHandler(errors, children)
: console.error(errors)
}
return null
}
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: {
["list", "heading"].forEach((type) => {
simpleMarkdown.defaultRules[type] = {
order: Number.POSITIVE_INFINITY,
match: () => null // Never match anything in order to ignore this rule
};
});