feat(markdown): implemented expanding single link list items
This commit is contained in:
parent
16a888fe9e
commit
982e3b38c3
4 changed files with 226 additions and 0 deletions
103
src/MfGames.Nitride.Markdown/MakeSingleLinkListItems.cs
Normal file
103
src/MfGames.Nitride.Markdown/MakeSingleLinkListItems.cs
Normal file
|
@ -0,0 +1,103 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using MfGames.Gallium;
|
||||
using MfGames.Nitride.Contents;
|
||||
using MfGames.Nitride.Slugs;
|
||||
|
||||
namespace MfGames.Nitride.Markdown;
|
||||
|
||||
/// <summary>
|
||||
/// An operation that turns list items that starts with a link into a single
|
||||
/// link for the entire list item, even if there are additional links in the
|
||||
/// list.
|
||||
/// </summary>
|
||||
public class MakeSingleLinkListItems : IOperation
|
||||
{
|
||||
private readonly ISlugConverter slugs;
|
||||
|
||||
public MakeSingleLinkListItems(ISlugConverter slugs)
|
||||
{
|
||||
this.slugs = slugs;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<Entity> Run(IEnumerable<Entity> input)
|
||||
{
|
||||
return input
|
||||
.SelectManyEntity<IsMarkdown>(
|
||||
x => x
|
||||
.Select(this.MakeSingleLinkLists));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This turns all links that start with a link into a single link while
|
||||
/// removing all trailing links within the line. This is to simplify the
|
||||
/// rendering of the link on page.
|
||||
/// </summary>
|
||||
private Entity MakeSingleLinkLists(Entity entity)
|
||||
{
|
||||
string content = entity.GetText()!;
|
||||
|
||||
string output = Regex.Replace(
|
||||
content,
|
||||
@"- \[\[(?<label>[^\]]+?)\]\](?<post>[^\n]+)\n",
|
||||
match =>
|
||||
{
|
||||
string wiki = match.Groups["label"].ToString();
|
||||
string path = string.Format(
|
||||
"/{0}/",
|
||||
this.slugs.ToSlug(wiki.Split('|').First()));
|
||||
string label = wiki.Split('|').Last();
|
||||
string after = match.Groups["post"].ToString();
|
||||
string post = this.RemoveLinks(after);
|
||||
string value = $"- [{label}{post}]({path})\n";
|
||||
|
||||
return value;
|
||||
});
|
||||
|
||||
output = Regex.Replace(
|
||||
output,
|
||||
@"- \[(?<label>[^\]]+?)\]\((?<path>[^\)]+?)\)(?<post>[^\n]+)\n",
|
||||
match =>
|
||||
{
|
||||
string label = match.Groups["label"].ToString();
|
||||
string path = match.Groups["path"].ToString();
|
||||
string after = match.Groups["post"].ToString();
|
||||
string post = this.RemoveLinks(after);
|
||||
string value = $"- [{label}{post}]({path})\n";
|
||||
|
||||
return value;
|
||||
});
|
||||
|
||||
return entity.SetTextContent(output);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a normal link and replaces it with the text.
|
||||
/// </summary>
|
||||
private string RemoveLinks(string input)
|
||||
{
|
||||
string output = Regex.Replace(
|
||||
input,
|
||||
@"\[\[(?<label>[^\]]+)\]\]",
|
||||
match =>
|
||||
{
|
||||
string link1 = match.Groups["label"].ToString();
|
||||
string path1 = string.Format(
|
||||
"/{0}/",
|
||||
this.slugs.ToSlug(link1.Split('|').First()));
|
||||
string label1 = link1.Split('|').Last();
|
||||
|
||||
return label1;
|
||||
});
|
||||
|
||||
output = Regex.Replace(
|
||||
output,
|
||||
@"\[(?<label>[^\]]+)\]\([^)]+\)",
|
||||
match => match.Groups["label"].ToString());
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
|
@ -12,6 +12,7 @@
|
|||
<ItemGroup>
|
||||
<ProjectReference Include="..\MfGames.Nitride.Gemtext\MfGames.Nitride.Gemtext.csproj" />
|
||||
<ProjectReference Include="..\MfGames.Nitride.Html\MfGames.Nitride.Html.csproj" />
|
||||
<ProjectReference Include="..\MfGames.Nitride.Slugs\MfGames.Nitride.Slugs.csproj" />
|
||||
<ProjectReference Include="..\MfGames.Nitride\MfGames.Nitride.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using MfGames.Gallium;
|
||||
using MfGames.Nitride.Contents;
|
||||
using MfGames.Nitride.Markdown;
|
||||
using MfGames.Nitride.Tests;
|
||||
using MfGames.TestSetup;
|
||||
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace MfGames.Nitride.Slugs.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Tests the functionality of the WriteFiles().
|
||||
/// </summary>
|
||||
public class MakeSingleLinkListItemsTests : TestBase<MarkdownTestContext>
|
||||
{
|
||||
public MakeSingleLinkListItemsTests(ITestOutputHelper output)
|
||||
: base(output)
|
||||
{
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AlreadyFullMarkdownLink()
|
||||
{
|
||||
using MarkdownTestContext context = this.CreateContext();
|
||||
|
||||
List<Entity> input = new()
|
||||
{
|
||||
new Entity()
|
||||
.Set(IsMarkdown.Instance)
|
||||
.SetTextContent("- [Empty](link)"),
|
||||
};
|
||||
MakeSingleLinkListItems?
|
||||
op = context.Resolve<MakeSingleLinkListItems>();
|
||||
IEnumerable<Entity> output = op.Run(input);
|
||||
string content = output.First().GetText()!.Trim();
|
||||
|
||||
Assert.Equal("- [Empty](link)", content);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExtendSingleMarkdownLink()
|
||||
{
|
||||
using MarkdownTestContext context = this.CreateContext();
|
||||
|
||||
List<Entity> input = new()
|
||||
{
|
||||
new Entity()
|
||||
.Set(IsMarkdown.Instance)
|
||||
.SetTextContent("- [Empty](link) space"),
|
||||
};
|
||||
MakeSingleLinkListItems?
|
||||
op = context.Resolve<MakeSingleLinkListItems>();
|
||||
IEnumerable<Entity> output = op.Run(input);
|
||||
string content = output.First().GetText()!.Trim();
|
||||
|
||||
Assert.Equal("- [Empty space](link)", content);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NoLinksNoChange()
|
||||
{
|
||||
using MarkdownTestContext context = this.CreateContext();
|
||||
|
||||
List<Entity> input = new()
|
||||
{
|
||||
new Entity()
|
||||
.Set(IsMarkdown.Instance)
|
||||
.SetTextContent("- Empty"),
|
||||
};
|
||||
MakeSingleLinkListItems?
|
||||
op = context.Resolve<MakeSingleLinkListItems>();
|
||||
IEnumerable<Entity> output = op.Run(input);
|
||||
string content = output.First().GetText()!.Trim();
|
||||
|
||||
Assert.Equal("- Empty", content);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RemoveSecondMarkdownLink()
|
||||
{
|
||||
using MarkdownTestContext context = this.CreateContext();
|
||||
|
||||
List<Entity> input = new()
|
||||
{
|
||||
new Entity()
|
||||
.Set(IsMarkdown.Instance)
|
||||
.SetTextContent("- [Empty](link) [space](link2)"),
|
||||
};
|
||||
MakeSingleLinkListItems?
|
||||
op = context.Resolve<MakeSingleLinkListItems>();
|
||||
IEnumerable<Entity> output = op.Run(input);
|
||||
string content = output.First().GetText()!.Trim();
|
||||
|
||||
Assert.Equal("- [Empty space](link)", content);
|
||||
}
|
||||
}
|
22
tests/MfGames.Nitride.Markdown.Tests/MarkdownTestContext.cs
Normal file
22
tests/MfGames.Nitride.Markdown.Tests/MarkdownTestContext.cs
Normal file
|
@ -0,0 +1,22 @@
|
|||
using Autofac;
|
||||
|
||||
using MfGames.Nitride.Markdown;
|
||||
using MfGames.Nitride.Tests;
|
||||
|
||||
namespace MfGames.Nitride.Slugs.Tests;
|
||||
|
||||
public class MarkdownTestContext : NitrideTestContext
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void ConfigureContainer(ContainerBuilder builder)
|
||||
{
|
||||
base.ConfigureContainer(builder);
|
||||
builder.RegisterModule<NitrideSlugsModule>();
|
||||
builder.RegisterModule<NitrideMarkdownModule>();
|
||||
|
||||
builder
|
||||
.RegisterType<SimpleSlugConverter>()
|
||||
.As<ISlugConverter>()
|
||||
.SingleInstance();
|
||||
}
|
||||
}
|
Reference in a new issue