[backend/mfm] Implement more mfm node types in MfmParser
Only FnNode, MfmSearchNode & MfmQuoteNode are missing now.
This commit is contained in:
parent
4a1cf59e23
commit
03872a1ce1
1 changed files with 97 additions and 2 deletions
|
@ -17,10 +17,19 @@ public static class MfmParser {
|
||||||
new AltUrlNodeParser(),
|
new AltUrlNodeParser(),
|
||||||
new LinkNodeParser(),
|
new LinkNodeParser(),
|
||||||
new SilentLinkNodeParser(),
|
new SilentLinkNodeParser(),
|
||||||
new InlineCodeNodeParser()
|
new InlineCodeNodeParser(),
|
||||||
|
new EmojiCodeNodeParser(),
|
||||||
|
new MathInlineNodeParser(),
|
||||||
|
new MathBlockNodeParser(),
|
||||||
|
new CodeBlockParser()
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/// <remarks>
|
||||||
|
/// This intentionally doesn't implement the node type UnicodeEmojiNode, both for performance and because it's not
|
||||||
|
/// needed for backend processing
|
||||||
|
/// </remarks>
|
||||||
public static IEnumerable<MfmNode> Parse(string buffer, int position = 0, int nestLimit = 20) {
|
public static IEnumerable<MfmNode> Parse(string buffer, int position = 0, int nestLimit = 20) {
|
||||||
|
if (nestLimit <= 0) return [];
|
||||||
var nodes = new List<MfmNode>();
|
var nodes = new List<MfmNode>();
|
||||||
while (position < buffer.Length) {
|
while (position < buffer.Length) {
|
||||||
var parser = Parsers.FirstOrDefault(p => p.IsValid(buffer, position));
|
var parser = Parsers.FirstOrDefault(p => p.IsValid(buffer, position));
|
||||||
|
@ -396,5 +405,91 @@ internal class SilentLinkNodeParser : INodeParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: still missing: FnNode, MathInlineNode, EmojiCodeNode, UnicodeEmojiNode, MfmMathBlockNode, MfmCodeBlockNode, MfmSearchNode, MfmQuoteNode
|
internal class EmojiCodeNodeParser : INodeParser {
|
||||||
|
private const string Char = ":";
|
||||||
|
private static readonly Regex Full = new("^[a-z0-9_+-]+$");
|
||||||
|
|
||||||
|
public bool IsValid(string buffer, int position) {
|
||||||
|
if (!buffer[position..].StartsWith(Char))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var (start, end, _) = NodeParserAbstractions.HandlePosition(Char, buffer, position);
|
||||||
|
return end != buffer.Length && Full.IsMatch(buffer[start..end]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public (MfmNode node, int chars) Parse(string buffer, int position, int nestLimit) {
|
||||||
|
var (start, end, chars) = NodeParserAbstractions.HandlePosition(Char, buffer, position);
|
||||||
|
|
||||||
|
var node = new MfmEmojiCodeNode {
|
||||||
|
Name = buffer[start..end]
|
||||||
|
};
|
||||||
|
|
||||||
|
return (node, chars);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class MathInlineNodeParser : INodeParser {
|
||||||
|
private const string Pre = @"\(";
|
||||||
|
private const string Post = @"\)";
|
||||||
|
|
||||||
|
public bool IsValid(string buffer, int position) {
|
||||||
|
return buffer[position..].StartsWith(Pre);
|
||||||
|
}
|
||||||
|
|
||||||
|
public (MfmNode node, int chars) Parse(string buffer, int position, int nestLimit) {
|
||||||
|
var (start, end, chars) = NodeParserAbstractions.HandlePosition(Pre, Post, buffer, position);
|
||||||
|
|
||||||
|
var node = new MfmMathInlineNode {
|
||||||
|
Formula = buffer[start..end]
|
||||||
|
};
|
||||||
|
|
||||||
|
return (node, chars);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class MathBlockNodeParser : INodeParser {
|
||||||
|
private const string Pre = @"\[";
|
||||||
|
private const string Post = @"\]";
|
||||||
|
|
||||||
|
public bool IsValid(string buffer, int position) {
|
||||||
|
return buffer[position..].StartsWith(Pre);
|
||||||
|
}
|
||||||
|
|
||||||
|
public (MfmNode node, int chars) Parse(string buffer, int position, int nestLimit) {
|
||||||
|
var (start, end, chars) = NodeParserAbstractions.HandlePosition(Pre, Post, buffer, position);
|
||||||
|
|
||||||
|
var node = new MfmMathBlockNode {
|
||||||
|
Formula = buffer[start..end]
|
||||||
|
};
|
||||||
|
|
||||||
|
return (node, chars);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class CodeBlockParser : INodeParser {
|
||||||
|
private const string Char = "```";
|
||||||
|
|
||||||
|
public bool IsValid(string buffer, int position) {
|
||||||
|
if (!buffer[position..].StartsWith(Char)) return false;
|
||||||
|
|
||||||
|
var (start, end, _) = NodeParserAbstractions.HandlePosition(Char, buffer, position);
|
||||||
|
return buffer[start..end].EndsWith('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
public (MfmNode node, int chars) Parse(string buffer, int position, int nestLimit) {
|
||||||
|
var (start, end, chars) = NodeParserAbstractions.HandlePosition(Char, buffer, position);
|
||||||
|
var split = buffer[start..end].Split('\n');
|
||||||
|
var lang = split[0].Length > 0 ? split[0] : null;
|
||||||
|
var code = string.Join('\n', split[1..^1]);
|
||||||
|
|
||||||
|
var node = new MfmCodeBlockNode {
|
||||||
|
Code = code,
|
||||||
|
Language = lang
|
||||||
|
};
|
||||||
|
|
||||||
|
return (node, chars);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: still missing: FnNode, MfmSearchNode, MfmQuoteNode
|
||||||
//TODO: "*italic **bold** *" doesn't work yet
|
//TODO: "*italic **bold** *" doesn't work yet
|
Loading…
Add table
Reference in a new issue