Newer
Older
mergeText,
setConsumeCount,
consumeDynamically
} = require('./util');
return parseFunc(input, startRule ? { startRule } : { });
const emojiRegex = require('twemoji-parser/dist/lib/regex').default;
const anchoredEmojiRegex = RegExp(`^(?:${emojiRegex.source})`);
/**
* check if the input matches the emoji regexp.
* if they match, set the byte length of the emoji.
*/
function matchUnicodeEmoji() {
const offset = location().start.offset;
const src = input.substr(offset);
const result = anchoredEmojiRegex.exec(src);
if (result != null) {
setConsumeCount(result[0].length); // length(utf-16 byte length) of emoji sequence.
//
// parsers
//
fullParser
= nodes:(&. n:(block / inline) { return n; })* { return mergeText(nodes); }
= nodes:(&. n:(emoji / text) { return n; })* { return mergeText(nodes); }
= nodes:(&. n:inline { return n; })* { return mergeText(nodes); }
//
// block rules
//
const lines = [head, ...tails];
const children = applyParser(lines.join('\n'), 'fullParser');
return createNode('quote', { }, children);
codeBlock
= BEGIN "```" lang:$(CHAR*) LF code:codeBlockLines LF "```" END
codeBlockLines
= head:codeBlockLine tails:(LF line:codeBlockLine { return line; })*
{ return text(); }
codeBlockLine
= BEGIN (!(BEGIN "```" END) CHAR)* END { return text(); }
mathBlockLines
= mathBlockLine (LF mathBlockLine)*
{ return text(); }
mathBlockLine
= (!("\\]" END) CHAR)+
const children = applyParser(content, 'inlineParser');
return createNode('center', { }, children);
centerLines
= centerLine (LF centerLine)*
{ return text(); }
centerLine
= (!("</center>" END) CHAR)+
//
// inline rules
//
inline
// inline: emoji
emoji
= customEmoji / unicodeEmoji
customEmoji
= ":" name:emojiName ":"
{
return createNode('emoji', { name: name });
}
emojiName
= [a-z0-9_+-]i+ { return text(); }
// NOTE: if the text matches one of the emojis, it will count the length of the emoji sequence and consume it.
unicodeEmoji
= &{ return matchUnicodeEmoji(); } (&{ return consumeDynamically(); } .)+
// inline: small
small
= "<small>" content:(!"</small>" i:inline { return i; })+ "</small>"
{
// inline: italic
italic
= "<i>" content:(!"</i>" i:inline { return i; })+ "</i>"
{
return createNode('italic', { }, mergeText(content));
}
/ "*" content:$(!"*" [a-z0-9 \t]i)+ "*"
{
const parsedContent = applyParser(content, 'inlineParser');
return createNode('italic', { }, parsedContent);
}
/ "_" content:$(!"_" [a-z0-9 \t]i)+ "_"
{
const parsedContent = applyParser(content, 'inlineParser');
return createNode('italic', { }, parsedContent);
}
// inline: strike
strike
= "~~" content:(!("~" / LF) i:inline { return i; })+ "~~"
{
return createNode('strike', { }, mergeText(content));
}
// inline: inlineCode
inlineCode
= "`" content:$(!"`" c:CHAR { return c; })+ "`"
{
// inline: mathInline
mathInline
= "\\(" content:$(!"\\)" c:CHAR { return c; })+ "\\)"
{
// inline: mention
mention
= "@" name:mentionName host:("@" host:mentionHost { return host; })?
{
return createNode('mention', {
});
}
mentionName
= !"-" mentionNamePart+ // first char is not "-".
{
return text();
}
mentionNamePart
= "-" &mentionNamePart // last char is not "-".
/ [a-z0-9_]i
mentionHost
= ![.-] mentionHostPart+ // first char is neither "." nor "-".
{
return text();
}
mentionHostPart
= [.-] &mentionHostPart // last char is neither "." nor "-".
/ [a-z0-9_]i
// inline: hashtag
hashtag
= "#" content:hashtagContent
{
return createNode('hashtag', { hashtag: content });
}
hashtagContent
= (hashtagBracketPair / hashtagChar)+ { return text(); }
hashtagBracketPair
= "(" hashtagContent* ")"
/ "[" hashtagContent* "]"
/ "「" hashtagContent* "」"
hashtagChar
= ![ \t.,!?'"#:\/\[\]【】()「」] CHAR
// inline: URL
url
= "<" url:urlFormat ">"
{
return createNode('url', { url: url });
}
/ url:urlFormat
{
return createNode('url', { url: url });
}
urlFormat
= "http" "s"? "://" urlContent
{
return text();
}
urlContent
= urlContentPart+
urlContentPart
= urlBracketPair
/ [.,] &urlContentPart // last char is neither "." nor ",".
urlBracketPair
= "(" urlContentPart* ")"
/ "[" urlContentPart* "]"
{
return createNode('link', {
silent: (silent != null),
url: url
}, mergeText(label));
}
linkLabel
= (!"]" n:inline { return n; })+
linkUrl
= url { return text(); }
CHAR
= !LF . { return text(); }
LF
= "\r\n" / [\r\n]