[parsing] Further improve mention parser logic, add more tests
This commit is contained in:
parent
fd5a524a8c
commit
3dc14f5bfe
2 changed files with 45 additions and 19 deletions
|
@ -134,24 +134,20 @@ module private MfmParser =
|
||||||
let aggregateTextInline nodes =
|
let aggregateTextInline nodes =
|
||||||
nodes |> aggregateText |> List.map (fun x -> x :?> MfmInlineNode)
|
nodes |> aggregateText |> List.map (fun x -> x :?> MfmInlineNode)
|
||||||
|
|
||||||
let domainFirstComponent =
|
|
||||||
many1Chars (satisfy isAsciiLetter <|> satisfy isDigit <|> anyOf "_-")
|
|
||||||
|
|
||||||
let domainComponent =
|
let domainComponent =
|
||||||
many1Chars (satisfy isAsciiLetter <|> satisfy isDigit <|> anyOf "._-")
|
many1Chars (
|
||||||
|
satisfy isAsciiLetterOrNumber
|
||||||
|
<|> pchar '_'
|
||||||
|
<|> attempt (
|
||||||
|
pchar '-'
|
||||||
|
.>> (previousCharSatisfies isAsciiLetterOrNumber
|
||||||
|
<|> nextCharSatisfies isAsciiLetterOrNumber)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
let domainStart = (satisfy isAsciiLetter <|> satisfy isDigit)
|
let domain =
|
||||||
|
domainComponent .>>. (many <| attempt (skipChar '.' >>. domainComponent))
|
||||||
let domainFull =
|
|>> fun (a, b) -> String.concat "." <| Seq.append [ a ] b
|
||||||
domainStart .>>. domainFirstComponent .>>. pchar '.' .>>. many1 domainComponent
|
|
||||||
|
|
||||||
let domainAggregate1 (a: char, b: string) = string a + b
|
|
||||||
let domainAggregate2 (a: char * string, b: char) = (domainAggregate1 a) + string b
|
|
||||||
|
|
||||||
let domainAggregate (x: (char * string) * char, y: string list) =
|
|
||||||
domainAggregate2 x + (String.concat "" y)
|
|
||||||
|
|
||||||
let domain = domainFull |>> domainAggregate
|
|
||||||
|
|
||||||
let acct (user: string, host: string option) =
|
let acct (user: string, host: string option) =
|
||||||
match host with
|
match host with
|
||||||
|
@ -230,7 +226,10 @@ module private MfmParser =
|
||||||
let mentionNode =
|
let mentionNode =
|
||||||
previousCharSatisfiesNot isNotWhitespace
|
previousCharSatisfiesNot isNotWhitespace
|
||||||
>>. skipString "@"
|
>>. skipString "@"
|
||||||
>>. many1Chars (satisfy isAsciiLetter <|> satisfy isDigit <|> anyOf "._-")
|
>>. many1Chars (
|
||||||
|
satisfy isAsciiLetterOrNumber
|
||||||
|
<|> attempt (anyOf "._-" .>> nextCharSatisfies isAsciiLetterOrNumber)
|
||||||
|
)
|
||||||
.>>. opt (skipChar '@' >>. domain)
|
.>>. opt (skipChar '@' >>. domain)
|
||||||
.>> (lookAhead
|
.>> (lookAhead
|
||||||
<| choice
|
<| choice
|
||||||
|
|
|
@ -66,10 +66,13 @@ public class MfmTests
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void TestMention()
|
public void TestMention()
|
||||||
{
|
{
|
||||||
const string input = "test @test test";
|
const string input = "test @test test @test@instance.tld";
|
||||||
List<MfmNode> expected =
|
List<MfmNode> expected =
|
||||||
[
|
[
|
||||||
new MfmTextNode("test "), new MfmMentionNode("test", "test", null), new MfmTextNode(" test")
|
new MfmTextNode("test "),
|
||||||
|
new MfmMentionNode("test", "test", null),
|
||||||
|
new MfmTextNode(" test "),
|
||||||
|
new MfmMentionNode("test@instance.tld", "test", "instance.tld")
|
||||||
];
|
];
|
||||||
var res = Mfm.parse(input);
|
var res = Mfm.parse(input);
|
||||||
|
|
||||||
|
@ -90,6 +93,30 @@ public class MfmTests
|
||||||
MfmSerializer.Serialize(res).Should().BeEquivalentTo(input);
|
MfmSerializer.Serialize(res).Should().BeEquivalentTo(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void TestMentionTrailingDot()
|
||||||
|
{
|
||||||
|
const string input = "@test@asdf.com.";
|
||||||
|
List<MfmNode> expected = [new MfmMentionNode("test@asdf.com", "test", "asdf.com"), new MfmTextNode(".")];
|
||||||
|
var res = Mfm.parse(input);
|
||||||
|
|
||||||
|
AssertionOptions.FormattingOptions.MaxDepth = 100;
|
||||||
|
res.ToList().Should().Equal(expected, MfmNodeEqual);
|
||||||
|
MfmSerializer.Serialize(res).Should().BeEquivalentTo(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void TestMentionTrailingDotLocal()
|
||||||
|
{
|
||||||
|
const string input = "@test.";
|
||||||
|
List<MfmNode> expected = [new MfmMentionNode("test", "test", null), new MfmTextNode(".")];
|
||||||
|
var res = Mfm.parse(input);
|
||||||
|
|
||||||
|
AssertionOptions.FormattingOptions.MaxDepth = 100;
|
||||||
|
res.ToList().Should().Equal(expected, MfmNodeEqual);
|
||||||
|
MfmSerializer.Serialize(res).Should().BeEquivalentTo(input);
|
||||||
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void TestCodeBlock()
|
public void TestCodeBlock()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue