Compare commits

...

10 commits
v1.2.1 ... main

51 changed files with 743 additions and 182 deletions

View file

@ -10,8 +10,7 @@ pipeline:
commands:
- nix develop --command scripts/build.sh
when:
event: [push, pull_request, tag]
tag: v*
event: [push, pull_request]
test:
image: registry.gitlab.com/dmoonfire/nix-flake-docker:latest
@ -19,11 +18,6 @@ pipeline:
- nix develop --command scripts/test.sh
when:
event: [push, pull_request]
#paths:
# - ./**/*test-result.xml
# - ./coverage/Cobertura.xml
# - ./coverage/Summary.*
# - ./**/*.nupkg
release-main:
image: registry.gitlab.com/dmoonfire/nix-flake-docker:latest

View file

@ -1,54 +1,86 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26124.0
MinimumVisualStudioVersion = 15.0.26124.0
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{954BA984-D50E-4D1C-880F-EAE678EF6945}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MfGames.Markdown.Gemtext", "src\MfGames.Markdown.Gemtext\MfGames.Markdown.Gemtext.csproj", "{2A1DE43D-544D-4CE0-ACC8-D15497BBCECA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MfGames.Markdown.Gemtext.Tests", "src\MfGames.Markdown.Gemtext.Tests\MfGames.Markdown.Gemtext.Tests.csproj", "{D2703B25-9AF7-49FF-93A4-CB124560F2A9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2A1DE43D-544D-4CE0-ACC8-D15497BBCECA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2A1DE43D-544D-4CE0-ACC8-D15497BBCECA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2A1DE43D-544D-4CE0-ACC8-D15497BBCECA}.Debug|x64.ActiveCfg = Debug|Any CPU
{2A1DE43D-544D-4CE0-ACC8-D15497BBCECA}.Debug|x64.Build.0 = Debug|Any CPU
{2A1DE43D-544D-4CE0-ACC8-D15497BBCECA}.Debug|x86.ActiveCfg = Debug|Any CPU
{2A1DE43D-544D-4CE0-ACC8-D15497BBCECA}.Debug|x86.Build.0 = Debug|Any CPU
{2A1DE43D-544D-4CE0-ACC8-D15497BBCECA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2A1DE43D-544D-4CE0-ACC8-D15497BBCECA}.Release|Any CPU.Build.0 = Release|Any CPU
{2A1DE43D-544D-4CE0-ACC8-D15497BBCECA}.Release|x64.ActiveCfg = Release|Any CPU
{2A1DE43D-544D-4CE0-ACC8-D15497BBCECA}.Release|x64.Build.0 = Release|Any CPU
{2A1DE43D-544D-4CE0-ACC8-D15497BBCECA}.Release|x86.ActiveCfg = Release|Any CPU
{2A1DE43D-544D-4CE0-ACC8-D15497BBCECA}.Release|x86.Build.0 = Release|Any CPU
{D2703B25-9AF7-49FF-93A4-CB124560F2A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D2703B25-9AF7-49FF-93A4-CB124560F2A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D2703B25-9AF7-49FF-93A4-CB124560F2A9}.Debug|x64.ActiveCfg = Debug|Any CPU
{D2703B25-9AF7-49FF-93A4-CB124560F2A9}.Debug|x64.Build.0 = Debug|Any CPU
{D2703B25-9AF7-49FF-93A4-CB124560F2A9}.Debug|x86.ActiveCfg = Debug|Any CPU
{D2703B25-9AF7-49FF-93A4-CB124560F2A9}.Debug|x86.Build.0 = Debug|Any CPU
{D2703B25-9AF7-49FF-93A4-CB124560F2A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D2703B25-9AF7-49FF-93A4-CB124560F2A9}.Release|Any CPU.Build.0 = Release|Any CPU
{D2703B25-9AF7-49FF-93A4-CB124560F2A9}.Release|x64.ActiveCfg = Release|Any CPU
{D2703B25-9AF7-49FF-93A4-CB124560F2A9}.Release|x64.Build.0 = Release|Any CPU
{D2703B25-9AF7-49FF-93A4-CB124560F2A9}.Release|x86.ActiveCfg = Release|Any CPU
{D2703B25-9AF7-49FF-93A4-CB124560F2A9}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{2A1DE43D-544D-4CE0-ACC8-D15497BBCECA} = {954BA984-D50E-4D1C-880F-EAE678EF6945}
{D2703B25-9AF7-49FF-93A4-CB124560F2A9} = {954BA984-D50E-4D1C-880F-EAE678EF6945}
EndGlobalSection
EndGlobal
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26124.0
MinimumVisualStudioVersion = 15.0.26124.0
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{954BA984-D50E-4D1C-880F-EAE678EF6945}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MfGames.Markdown.Gemtext", "src\MfGames.Markdown.Gemtext\MfGames.Markdown.Gemtext.csproj", "{2A1DE43D-544D-4CE0-ACC8-D15497BBCECA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MfGames.Markdown.Gemtext.Tests", "tests\MfGames.Markdown.Gemtext.Tests\MfGames.Markdown.Gemtext.Tests.csproj", "{D2703B25-9AF7-49FF-93A4-CB124560F2A9}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{B4837F83-8560-4AC9-B1E3-6B8C0545A65B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MfGames.Markdown", "src\MfGames.Markdown\MfGames.Markdown.csproj", "{482E332F-9E72-4F02-B528-9CF04AE05E82}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MfGames.Markdown.Tests", "tests\MfGames.Markdown.Tests\MfGames.Markdown.Tests.csproj", "{3E2AD98D-D1A1-48DF-B94F-A470982DAC9B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2A1DE43D-544D-4CE0-ACC8-D15497BBCECA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2A1DE43D-544D-4CE0-ACC8-D15497BBCECA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2A1DE43D-544D-4CE0-ACC8-D15497BBCECA}.Debug|x64.ActiveCfg = Debug|Any CPU
{2A1DE43D-544D-4CE0-ACC8-D15497BBCECA}.Debug|x64.Build.0 = Debug|Any CPU
{2A1DE43D-544D-4CE0-ACC8-D15497BBCECA}.Debug|x86.ActiveCfg = Debug|Any CPU
{2A1DE43D-544D-4CE0-ACC8-D15497BBCECA}.Debug|x86.Build.0 = Debug|Any CPU
{2A1DE43D-544D-4CE0-ACC8-D15497BBCECA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2A1DE43D-544D-4CE0-ACC8-D15497BBCECA}.Release|Any CPU.Build.0 = Release|Any CPU
{2A1DE43D-544D-4CE0-ACC8-D15497BBCECA}.Release|x64.ActiveCfg = Release|Any CPU
{2A1DE43D-544D-4CE0-ACC8-D15497BBCECA}.Release|x64.Build.0 = Release|Any CPU
{2A1DE43D-544D-4CE0-ACC8-D15497BBCECA}.Release|x86.ActiveCfg = Release|Any CPU
{2A1DE43D-544D-4CE0-ACC8-D15497BBCECA}.Release|x86.Build.0 = Release|Any CPU
{D2703B25-9AF7-49FF-93A4-CB124560F2A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D2703B25-9AF7-49FF-93A4-CB124560F2A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D2703B25-9AF7-49FF-93A4-CB124560F2A9}.Debug|x64.ActiveCfg = Debug|Any CPU
{D2703B25-9AF7-49FF-93A4-CB124560F2A9}.Debug|x64.Build.0 = Debug|Any CPU
{D2703B25-9AF7-49FF-93A4-CB124560F2A9}.Debug|x86.ActiveCfg = Debug|Any CPU
{D2703B25-9AF7-49FF-93A4-CB124560F2A9}.Debug|x86.Build.0 = Debug|Any CPU
{D2703B25-9AF7-49FF-93A4-CB124560F2A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D2703B25-9AF7-49FF-93A4-CB124560F2A9}.Release|Any CPU.Build.0 = Release|Any CPU
{D2703B25-9AF7-49FF-93A4-CB124560F2A9}.Release|x64.ActiveCfg = Release|Any CPU
{D2703B25-9AF7-49FF-93A4-CB124560F2A9}.Release|x64.Build.0 = Release|Any CPU
{D2703B25-9AF7-49FF-93A4-CB124560F2A9}.Release|x86.ActiveCfg = Release|Any CPU
{D2703B25-9AF7-49FF-93A4-CB124560F2A9}.Release|x86.Build.0 = Release|Any CPU
{482E332F-9E72-4F02-B528-9CF04AE05E82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{482E332F-9E72-4F02-B528-9CF04AE05E82}.Debug|Any CPU.Build.0 = Debug|Any CPU
{482E332F-9E72-4F02-B528-9CF04AE05E82}.Debug|x64.ActiveCfg = Debug|Any CPU
{482E332F-9E72-4F02-B528-9CF04AE05E82}.Debug|x64.Build.0 = Debug|Any CPU
{482E332F-9E72-4F02-B528-9CF04AE05E82}.Debug|x86.ActiveCfg = Debug|Any CPU
{482E332F-9E72-4F02-B528-9CF04AE05E82}.Debug|x86.Build.0 = Debug|Any CPU
{482E332F-9E72-4F02-B528-9CF04AE05E82}.Release|Any CPU.ActiveCfg = Release|Any CPU
{482E332F-9E72-4F02-B528-9CF04AE05E82}.Release|Any CPU.Build.0 = Release|Any CPU
{482E332F-9E72-4F02-B528-9CF04AE05E82}.Release|x64.ActiveCfg = Release|Any CPU
{482E332F-9E72-4F02-B528-9CF04AE05E82}.Release|x64.Build.0 = Release|Any CPU
{482E332F-9E72-4F02-B528-9CF04AE05E82}.Release|x86.ActiveCfg = Release|Any CPU
{482E332F-9E72-4F02-B528-9CF04AE05E82}.Release|x86.Build.0 = Release|Any CPU
{3E2AD98D-D1A1-48DF-B94F-A470982DAC9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3E2AD98D-D1A1-48DF-B94F-A470982DAC9B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3E2AD98D-D1A1-48DF-B94F-A470982DAC9B}.Debug|x64.ActiveCfg = Debug|Any CPU
{3E2AD98D-D1A1-48DF-B94F-A470982DAC9B}.Debug|x64.Build.0 = Debug|Any CPU
{3E2AD98D-D1A1-48DF-B94F-A470982DAC9B}.Debug|x86.ActiveCfg = Debug|Any CPU
{3E2AD98D-D1A1-48DF-B94F-A470982DAC9B}.Debug|x86.Build.0 = Debug|Any CPU
{3E2AD98D-D1A1-48DF-B94F-A470982DAC9B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3E2AD98D-D1A1-48DF-B94F-A470982DAC9B}.Release|Any CPU.Build.0 = Release|Any CPU
{3E2AD98D-D1A1-48DF-B94F-A470982DAC9B}.Release|x64.ActiveCfg = Release|Any CPU
{3E2AD98D-D1A1-48DF-B94F-A470982DAC9B}.Release|x64.Build.0 = Release|Any CPU
{3E2AD98D-D1A1-48DF-B94F-A470982DAC9B}.Release|x86.ActiveCfg = Release|Any CPU
{3E2AD98D-D1A1-48DF-B94F-A470982DAC9B}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{2A1DE43D-544D-4CE0-ACC8-D15497BBCECA} = {954BA984-D50E-4D1C-880F-EAE678EF6945}
{D2703B25-9AF7-49FF-93A4-CB124560F2A9} = {B4837F83-8560-4AC9-B1E3-6B8C0545A65B}
{482E332F-9E72-4F02-B528-9CF04AE05E82} = {954BA984-D50E-4D1C-880F-EAE678EF6945}
{3E2AD98D-D1A1-48DF-B94F-A470982DAC9B} = {B4837F83-8560-4AC9-B1E3-6B8C0545A65B}
EndGlobalSection
EndGlobal

View file

@ -1,4 +1,38 @@
MfGames.Markdown.Gemtext CIL
============================
# MfGames.Markdown CIL
An extension for [Markdig](https://github.com/xoofx/markdig) that converts Markdown into Gemtext.
This is a set of libraries for working with Markdown in C#. Most of the code are extensions in [MarkDig](https://github.com/xoofx/markdig), an extensible library for converting Markdown.
The library includes the following:
- An extension for converting wiki links, such as `[[MfGames]]` into a link based on the title. This is for both HTML and Gemtext.
- A output library for using MarkDig to generate Gemtext for Gemini pods.
The documentation is rather light at the moment, but the tests can show various ways of using the libraries.
## Usage
These library are not on nuget.org (for various reasons). To use them, set up your NuGet.config to pull them from their repository.
```
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
<add key="mfgames.com" value="https://src.mfgames.com/api/packages/mfgames-cil/nuget/index.json" protocolVersion="3" />
</packageSources>
<packageSourceMapping>
<packageSource key="nuget.org">
<package pattern="*" />
</packageSource>
<packageSource key="mfgames.com">
<package pattern="MfGames.*" />
</packageSource>
</packageSourceMapping>
</configuration>
```
The two libraries are:
- MfGames.Markdown
- MfGames.Markdown.Gemtext

View file

@ -1,7 +1,12 @@
#!/usr/bin/env sh
# Set up logging.
log() { echo "🛠️ $(basename $0): $@"; }
# Move into the top level.
cd $(dirname $0)/..
./scripts/setup.sh || exit 1
echo "$(basename $0): building project"
log "building project"
dotnet build

View file

@ -1,3 +0,0 @@
npm install --ci
dotnet restore
dotnet build

View file

@ -1,5 +0,0 @@
npm install --ci
dotnet restore
dotnet build
npm install --ci
npx semantic-release

View file

@ -1,9 +0,0 @@
npm install --ci
npx commitlint-gitlab-ci -x @commitlint/config-conventional
dotnet restore
dotnet build
dotnet test --test-adapter-path:. --logger:"junit;LogFilePath=../artifacts/{assembly}-test-result.xml;MethodFormat=Default;FailureBodyFormat=Verbose" --collect:"XPlat Code Coverage"
dotnet new tool-manifest
dotnet tool install dotnet-reportgenerator-globaltool
dotnet tool run reportgenerator -reports:src/*/TestResults/*/coverage.cobertura.xml -targetdir:./coverage "-reporttypes:Cobertura;TextSummary"
grep "Line coverage" coverage/Summary.txt

View file

@ -1,39 +1,43 @@
#!/usr/bin/env sh
# Set up logging.
log() { echo "️🚢 $(basename $0): $@"; }
# Move into the root folder and make sure we're set up.
cd $(dirname $0)/..
./scripts/setup.sh || exit 1
# Verify the input.
if [ "x$GITEA_TOKEN" = "x" ]
then
echo "the environment variable GITEA_TOKEN is not defined"
log "the environment variable GITEA_TOKEN is not defined"
exit 1
fi
# Clean up everything from the previous runs.
echo "$(basename $0): cleaning project"
log "cleaning project"
dotnet clean
# Version the file based on the Git repository.
echo "$(basename $0): setting project version"
log "setting project version"
(cd src && dotnet dotnet-gitversion /updateprojectfiles)
SEMVER="v$(dotnet gitversion /output json | jq -r .SemVer)"
if [ "x$SEMVER" = "x" ]
then
echo "$(basename $0): cannot figure out the semantic version"
log "cannot figure out the semantic version"
exit 1
fi
# Build to pick up the new version.
echo "$(basename $0): building project $SEMVER"
log "building project $SEMVER"
dotnet build || exit 1
# Create and publish the NuGet packages.
echo "$(basename $0): creating NuGet packages"
log "creating NuGet packages"
dotnet pack -p:IncludeSymbols=true -p:SymbolPackageFormat=snupkg || exit 1
echo "$(basename $0): publishing NuGet package"
log "publishing NuGet package"
dotnet nuget remove source mfgames.com >& /dev/null
dotnet nuget add source --name mfgames.com --username dmoonfire --password $GITEA_TOKEN https://src.mfgames.com/api/packages/mfgames-cil/nuget/index.json --store-password-in-clear-text || exit 1
dotnet nuget push --skip-duplicate --source mfgames.com src/*/bin/Debug/*.nupkg || exit 1
@ -41,11 +45,11 @@ dotnet nuget push --skip-duplicate --source mfgames.com src/*/bin/Debug/*.nupkg
# Tag and push, but only if we don't have a tag.
if ! git tag | grep $SEMVER >& /dev/null
then
echo "$(basename $0): tagging and pushing"
log "tagging and pushing"
git remote add publish https://dmoonfire:$GITEA_TOKEN@src.mfgames.com/mfgames-cil/$(basename $(git config --get remote.origin.url))
git tag $SEMVER
git push publish $SEMVER || exit 1
git remote remove publish
else
echo "$(basename $0): not tagging, already exists"
log "not tagging, already exists"
fi

View file

@ -1,5 +1,8 @@
#!/usr/bin/env sh
# Set up logging.
log() { echo "📦️ $(basename $0): $@"; }
# Normalize our environment.
cd $(dirname $0)/..
@ -8,7 +11,7 @@ for e in dotnet lefthook prettier nixfmt
do
if ! which $e >& /dev/null
then
echo "Cannot find '$e' in the path"
log "Cannot find '$e' in the path"
exit 1
fi
done
@ -16,12 +19,12 @@ done
# Make sure we have lefthook is installed.
if [ ! -f .git/hooks/pre-commit ]
then
echo "$(basename $0): installing lefthook"
log "installing lefthook"
lefthook install
fi
# Make sure our tools are installed.
echo "$(basename $0): install .NET tools"
log "install .NET tools"
dotnet tool restore
# Everything is good.

View file

@ -1,12 +1,12 @@
#!/usr/bin/env sh
# Set up logging.
log() { echo "️🧪 $(basename $0): $@"; }
# Move into the root folder and make sure we're set up.
cd $(dirname $0)/..
./scripts/setup.sh || exit 1
if [ -f ./tests/*/*.csproj ]
then
./scripts/setup.sh || exit 1
dotnet test --test-adapter-path:. --logger:"junit;LogFilePath=../artifacts/{assembly}-test-result.xml;MethodFormat=Default;FailureBodyFormat=Verbose" --collect:"XPlat Code Coverage"
dotnet tool run reportgenerator -reports:tests/*/TestResults/*/coverage.cobertura.xml -targetdir:./coverage "-reporttypes:Cobertura;TextSummary"
grep "Line coverage" coverage/Summary.txt
fi
dotnet test --test-adapter-path:. --logger:"junit;LogFilePath=../artifacts/{assembly}-test-result.xml;MethodFormat=Default;FailureBodyFormat=Verbose" --collect:"XPlat Code Coverage"
dotnet tool run reportgenerator -reports:tests/*/TestResults/*/coverage.cobertura.xml -targetdir:./coverage "-reporttypes:Cobertura;TextSummary"
grep "Line coverage" coverage/Summary.txt

View file

@ -1,26 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>MfGames.Markdown.Gemini.Tests</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0"/>
<PackageReference Include="JunitXml.TestLogger" Version="2.1.81" />
<PackageReference Include="xunit" Version="2.4.1"/>
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.0.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MfGames.Markdown.Gemtext\MfGames.Markdown.Gemtext.csproj"/>
</ItemGroup>
</Project>

View file

@ -2,6 +2,7 @@ using Markdig;
using Markdig.Extensions.SmartyPants;
using Markdig.Parsers.Inlines;
using Markdig.Renderers;
using MfGames.Markdown.Gemtext.Renderers;
using MfGames.Markdown.Gemtext.Renderers.Gemtext.Inlines;
@ -44,7 +45,7 @@ namespace MfGames.Markdown.Gemtext.Extensions
}
if (!gemtextRenderer.ObjectRenderers
.Contains<GemtextSmartyPantRenderer>())
.Contains<GemtextSmartyPantRenderer>())
{
gemtextRenderer.ObjectRenderers.Add(
new GemtextSmartyPantRenderer(this.Options));

View file

@ -1,5 +1,6 @@
using Markdig;
using Markdig.Renderers;
using MfGames.Markdown.Gemtext.Renderers;
namespace MfGames.Markdown.Gemtext.Extensions

View file

@ -1,5 +1,6 @@
using Markdig;
using Markdig.Renderers;
using MfGames.Markdown.Gemtext.Renderers;
using MfGames.Markdown.Gemtext.Renderers.Gemtext.Blocks;
@ -26,7 +27,8 @@ namespace MfGames.Markdown.Gemtext.Extensions
return;
}
var heading = gemtext.ObjectRenderers.Find<HeadingRenderer>();
HeadingRenderer? heading =
gemtext.ObjectRenderers.Find<HeadingRenderer>();
if (heading != null)
{

View file

@ -1,5 +1,6 @@
using Markdig;
using Markdig.Renderers;
using MfGames.Markdown.Gemtext.Renderers;
namespace MfGames.Markdown.Gemtext.Extensions

View file

@ -1,5 +1,6 @@
using Markdig;
using Markdig.Renderers;
using MfGames.Markdown.Gemtext.Renderers;
namespace MfGames.Markdown.Gemtext.Extensions

View file

@ -1,8 +1,10 @@
using System;
using System.IO;
using Markdig;
using Markdig.Parsers;
using Markdig.Syntax;
using MfGames.Markdown.Gemtext.Renderers;
namespace MfGames.Markdown.Gemtext

View file

@ -1,25 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Authors>Dylan Moonfire</Authors>
<Company>Moonfire Games</Company>
<RepositoryUrl>https://gitlab.com/mfgames-cil/mfgames-markdown-gemtext-cil</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
<PackageTags>ecs</PackageTags>
<PackageProjectUrl>https://gitlab.com/mfgames-cil/mfgames-markdown-gemtext-cil</PackageProjectUrl>
<PackageLicense>MIT</PackageLicense>
<Description>A Markdown extension to render Markdown in Gemtext.</Description>
</PropertyGroup>
<PropertyGroup>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Authors>Dylan Moonfire</Authors>
<Company>Moonfire Games</Company>
<RepositoryUrl>https://gitlab.com/mfgames-cil/mfgames-markdown-cil</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
<PackageProjectUrl>https://gitlab.com/mfgames-cil/mfgames-markdown-cil</PackageProjectUrl>
<PackageLicense>MIT</PackageLicense>
<Description>A MarkDig extension to render Markdown in Gemtext.</Description>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ConsoleTableExt" Version="3.1.9" />
<PackageReference Include="Markdig" Version="0.25.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="ConsoleTableExt" Version="3.2.0"/>
<PackageReference Include="Markdig" Version="0.30.3"/>
</ItemGroup>
</Project>

View file

@ -16,7 +16,7 @@ namespace MfGames.Markdown.Gemtext.Renderers.Gemtext.Blocks
renderer.EnsureTwoLines();
// Go through each list item and write them out.
foreach (var item in listBlock)
foreach (Block? item in listBlock)
{
// If the list only contains a link, then we just render the
// link instead.

View file

@ -1,4 +1,5 @@
using Markdig.Syntax;
using MfGames.Markdown.Gemtext.Renderers.Gemtext.Inlines;
namespace MfGames.Markdown.Gemtext.Renderers.Gemtext.Blocks

View file

@ -1,4 +1,5 @@
using Markdig.Syntax;
using MfGames.Markdown.Gemtext.Renderers.Gemtext.Inlines;
namespace MfGames.Markdown.Gemtext.Renderers.Gemtext.Blocks

View file

@ -1,5 +1,6 @@
using System;
using System.Net;
using Markdig.Extensions.SmartyPants;
namespace MfGames.Markdown.Gemtext.Renderers.Gemtext.Inlines

View file

@ -1,4 +1,5 @@
using System.IO;
using Markdig.Syntax.Inlines;
namespace MfGames.Markdown.Gemtext.Renderers.Gemtext.Inlines
@ -25,7 +26,7 @@ namespace MfGames.Markdown.Gemtext.Renderers.Gemtext.Inlines
// write out each link which is already formatted.
renderer.WriteLine();
foreach (var link in renderer.GatheredLinks)
foreach (string? link in renderer.GatheredLinks)
{
renderer.WriteLine();
renderer.Write(link);

View file

@ -1,4 +1,5 @@
using System.Linq;
using Markdig.Syntax;
using Markdig.Syntax.Inlines;

View file

@ -1,9 +1,11 @@
using System;
using System.Collections.Generic;
using System.IO;
using Markdig.Helpers;
using Markdig.Renderers;
using Markdig.Syntax;
using MfGames.Markdown.Gemtext.Renderers.Gemtext.Blocks;
using MfGames.Markdown.Gemtext.Renderers.Gemtext.Inlines;

View file

@ -0,0 +1,11 @@
using Markdig.Syntax.Inlines;
namespace MfGames.Markdown.Extensions;
public class WikiLink : LinkInline
{
public WikiLink()
{
this.IsClosed = false;
}
}

View file

@ -0,0 +1,47 @@
using Markdig;
using Markdig.Parsers.Inlines;
using Markdig.Renderers;
namespace MfGames.Markdown.Extensions;
/// <summary>
/// Translate `[[Bob]]` into `/bob/`.
/// </summary>
public class WikiLinkExtension : IMarkdownExtension
{
public WikiLinkExtension()
: this(null)
{
}
public WikiLinkExtension(WikiLinkOptions? options)
{
this.Options = options ?? new WikiLinkOptions();
}
public WikiLinkOptions Options { get; set; }
/// <inheritdoc />
public void Setup(MarkdownPipelineBuilder pipeline)
{
WikiLinkInlineParser? parser = pipeline.InlineParsers
.FindExact<WikiLinkInlineParser>();
if (parser != null)
{
return;
}
parser = new WikiLinkInlineParser(this.Options);
pipeline.InlineParsers.InsertBefore<LinkInlineParser>(parser);
}
/// <inheritdoc />
public void Setup(
MarkdownPipeline pipeline,
IMarkdownRenderer renderer)
{
// No setup needed here because we're using LinkInline which does the
// bulk of the work.
}
}

View file

@ -0,0 +1,112 @@
using System.Linq;
using Markdig.Helpers;
using Markdig.Parsers;
using Markdig.Syntax.Inlines;
namespace MfGames.Markdown.Extensions;
public class WikiLinkInlineParser : InlineParser
{
private readonly WikiLinkOptions options;
public WikiLinkInlineParser(WikiLinkOptions options)
{
this.options = options;
this.OpeningCharacters = new[] { '[' };
}
/// <inheritdoc />
public override bool Match(
InlineProcessor processor,
ref StringSlice slice)
{
// We are looking for the `[[` opening for the tag and that the first
// one isn't escaped.
if (IsNotDelimiter(slice, '['))
{
return false;
}
// We need to loop over the entire link, including the `[[` and `]]`
// while keeping track since we'll swallow additional characters beyond
// the link.
int linkStart = slice.Start;
int linkEnd = slice.Start;
slice.Start += 2;
// Our content starts after the double '[['.
int contentStart = slice.Start;
// We need to find the end of the link (the `]]`).
while (IsNotDelimiter(slice, ']'))
{
slice.NextChar();
linkEnd = slice.Start;
}
// Pull out the components before we adjust for the ']]' for the end.
int contentEnd = linkEnd;
// Finish skipping over the `]]`.
slice.NextChar();
slice.NextChar();
// Format the label and the URL.
string content = slice.Text.Substring(
contentStart,
contentEnd - contentStart);
string[] contentParts = content.Split('|', 2);
string label = contentParts.Last();
string url = this.options.GetUrl(contentParts.First());
// Add in any trailing components. This merges the `'s` from
// `[[Dale]]'s` into the label.
while (this.options.IsTrailingLink(slice.CurrentChar))
{
label += slice.CurrentChar;
slice.NextChar();
linkEnd++;
}
// Create the link that we're replacing.
WikiLink link = new()
{
Span =
{
Start = processor.GetSourcePosition(
linkStart,
out int line,
out int column),
},
Line = line,
Column = column,
Url = url,
IsClosed = true,
};
link.AppendChild(
new LiteralInline()
{
Line = line,
Column = column,
Content = new StringSlice(label),
IsClosed = true,
});
// Replace the inline and then indicate we have a match.
processor.Inline = link;
return true;
}
private static bool IsNotDelimiter(
StringSlice slice,
char delimiter)
{
return slice.CurrentChar != delimiter
|| slice.PeekChar() != delimiter
|| slice.PeekCharExtra(-1) == '\\';
}
}

View file

@ -0,0 +1,31 @@
using System;
using Markdig.Helpers;
namespace MfGames.Markdown.Extensions;
public class WikiLinkOptions
{
public WikiLinkOptions()
{
this.GetUrl = a => a;
this.IsTrailingLink = a => a.IsAlpha() || a == '\'';
}
/// <summary>
/// The callback to determine the link from the given wiki link. This does
/// not include trailing additions or use the label (e.g., `(ab|cd)` would
/// get `ab` as the parameters of this function.
/// </summary>
public Func<string, string> GetUrl { get; set; }
/// <summary>
/// <para>
/// A callback to determine if the text after the link should be merged
/// with the link label. This allows links such as [[Dale]]'s to be turned
/// into "Dale's" but pointing to "Dale" as a page.
/// </para>
/// <para>The default is to include any character or the apostrophe.</para>
/// </summary>
public Func<char, bool> IsTrailingLink { get; set; }
}

View file

@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Authors>Dylan Moonfire</Authors>
<Company>Moonfire Games</Company>
<RepositoryUrl>https://gitlab.com/mfgames-cil/mfgames-markdown-cil</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
<PackageProjectUrl>https://gitlab.com/mfgames-cil/mfgames-markdown-cil</PackageProjectUrl>
<PackageLicense>MIT</PackageLicense>
<Description>Various extensions for MarkDig and classes for working with Markdown.</Description>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Markdig" Version="0.30.3"/>
</ItemGroup>
</Project>

View file

@ -1,10 +1,11 @@
using Markdig;
using MfGames.Markdown.Gemtext;
using MfGames.Markdown.Gemtext.Extensions;
using MfGames.Markdown.Gemtext.Renderers;
using Xunit;
namespace MfGames.Markdown.Gemini.Tests
namespace MfGames.Markdown.Gemtext.Tests
{
public class CodeInlineTests
{

View file

@ -1,7 +1,6 @@
using MfGames.Markdown.Gemtext;
using Xunit;
namespace MfGames.Markdown.Gemini.Tests
namespace MfGames.Markdown.Gemtext.Tests
{
public class HeaderTests
{

View file

@ -1,7 +1,6 @@
using MfGames.Markdown.Gemtext;
using Xunit;
namespace MfGames.Markdown.Gemini.Tests
namespace MfGames.Markdown.Gemtext.Tests
{
public class ImageLinkTests
{

View file

@ -1,9 +1,10 @@
using Markdig;
using MfGames.Markdown.Gemtext;
using Markdig;
using MfGames.Markdown.Gemtext.Extensions;
using Xunit;
namespace MfGames.Markdown.Gemini.Tests
namespace MfGames.Markdown.Gemtext.Tests
{
public class IncreaseHeaderDepthsAfterFirstTests
{

View file

@ -1,7 +1,6 @@
using MfGames.Markdown.Gemtext;
using Xunit;
namespace MfGames.Markdown.Gemini.Tests
namespace MfGames.Markdown.Gemtext.Tests
{
public class LinkTests
{

View file

@ -1,7 +1,6 @@
using MfGames.Markdown.Gemtext;
using Xunit;
namespace MfGames.Markdown.Gemini.Tests
namespace MfGames.Markdown.Gemtext.Tests
{
public class ListTests
{

View file

@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MfGames.TestSetup" Version="1.0.6"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1"/>
<PackageReference Include="JunitXml.TestLogger" Version="3.0.114"/>
<PackageReference Include="xunit" Version="2.4.2"/>
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\MfGames.Markdown.Gemtext\MfGames.Markdown.Gemtext.csproj"/>
<ProjectReference Include="..\..\src\MfGames.Markdown\MfGames.Markdown.csproj"/>
</ItemGroup>
</Project>

View file

@ -1,10 +1,11 @@
using Markdig;
using MfGames.Markdown.Gemtext;
using MfGames.Markdown.Gemtext.Extensions;
using MfGames.Markdown.Gemtext.Renderers;
using Xunit;
namespace MfGames.Markdown.Gemini.Tests
namespace MfGames.Markdown.Gemtext.Tests
{
/// <summary>
/// Tests the various functionality of the ParagraphLinkHandling and

View file

@ -1,7 +1,6 @@
using MfGames.Markdown.Gemtext;
using Xunit;
namespace MfGames.Markdown.Gemini.Tests
namespace MfGames.Markdown.Gemtext.Tests
{
public class PlainTextTests
{

View file

@ -1,7 +1,6 @@
using MfGames.Markdown.Gemtext;
using Xunit;
namespace MfGames.Markdown.Gemini.Tests.PythonInspired
namespace MfGames.Markdown.Gemtext.Tests.PythonInspired
{
/// <summary>
/// https://github.com/makeworld-the-better-one/md2gemini/blob/master/tests/test_base_url.py

View file

@ -1,7 +1,6 @@
using MfGames.Markdown.Gemtext;
using Xunit;
namespace MfGames.Markdown.Gemini.Tests.PythonInspired
namespace MfGames.Markdown.Gemtext.Tests.PythonInspired
{
/// <summary>
/// https://github.com/makeworld-the-better-one/md2gemini/blob/master/tests/test_codeblock.py

View file

@ -1,7 +1,6 @@
using MfGames.Markdown.Gemtext;
using Xunit;
namespace MfGames.Markdown.Gemini.Tests.PythonInspired
namespace MfGames.Markdown.Gemtext.Tests.PythonInspired
{
/// <summary>
/// https://github.com/makeworld-the-better-one/md2gemini/blob/master/tests/test_list.py

View file

@ -1,9 +1,10 @@
using Markdig;
using MfGames.Markdown.Gemtext;
using MfGames.Markdown.Gemtext.Extensions;
using Xunit;
namespace MfGames.Markdown.Gemini.Tests.PythonInspired
namespace MfGames.Markdown.Gemtext.Tests.PythonInspired
{
/// <summary>
/// Runs through various plain input tests.

View file

@ -1,12 +1,11 @@
using Markdig;
using MfGames.Markdown.Gemtext;
using MfGames.Markdown.Gemtext.Extensions;
using MfGames.Markdown.Gemtext.Renderers;
using Xunit;
namespace MfGames.Markdown.Gemini.Tests.PythonInspired
namespace MfGames.Markdown.Gemtext.Tests.PythonInspired
{
/// <summary>
/// https://github.com/makeworld-the-better-one/md2gemini/blob/master/tests/test_strip_html.py

View file

@ -1,10 +1,11 @@
using Markdig;
using Markdig.Extensions.SmartyPants;
using MfGames.Markdown.Gemtext;
using MfGames.Markdown.Gemtext.Extensions;
using Xunit;
namespace MfGames.Markdown.Gemini.Tests
namespace MfGames.Markdown.Gemtext.Tests
{
public class QuoteTests
{

View file

@ -2,12 +2,11 @@ using ConsoleTableExt;
using Markdig;
using MfGames.Markdown.Gemtext;
using MfGames.Markdown.Gemtext.Extensions;
using Xunit;
namespace MfGames.Markdown.Gemini.Tests
namespace MfGames.Markdown.Gemtext.Tests
{
public class TableTests
{

View file

@ -0,0 +1,56 @@
using Markdig;
using MfGames.Markdown.Extensions;
using MfGames.Markdown.Gemtext.Extensions;
using MfGames.Markdown.Gemtext.Renderers;
using MfGames.TestSetup;
using Xunit;
using Xunit.Abstractions;
namespace MfGames.Markdown.Gemtext.Tests;
/// <summary>
/// Tests the functionality of the WriteFiles().
/// </summary>
public class WikiLinkTest : TestBase<TestContext>
{
public WikiLinkTest(ITestOutputHelper output)
: base(output)
{
}
[Fact]
public void PossessiveLabeledWikiLinkGemtext()
{
MarkdownPipeline pipeline = CreatePipeline();
string result = MarkdownGemtext
.ToGemtext(
"[[Test|Label]]'s",
pipeline)
.Replace("%5E", "^");
Assert.Equal("=> ^test$ Label's", result);
}
private static MarkdownPipeline CreatePipeline()
{
// Convert all titles to slugs.
WikiLinkOptions options = new()
{
GetUrl = (title) => string.Format(
"^{0}$",
title.ToLowerInvariant().Replace(" ", "-")),
};
// Create the pipeline and return the results.
MarkdownPipelineBuilder builder = new MarkdownPipelineBuilder()
.Use(new WikiLinkExtension(options))
.Use(new SetBlockLinkHandling(BlockLinkHandling.DocumentEnd));
// Build the pipeline and return it.
MarkdownPipeline pipeline = builder.Build();
return pipeline;
}
}

View file

@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Markdig" Version="0.30.3"/>
<PackageReference Include="MfGames.TestSetup" Version="1.0.6"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1"/>
<PackageReference Include="JunitXml.TestLogger" Version="3.0.114"/>
<PackageReference Include="xunit" Version="2.4.2"/>
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\MfGames.Markdown\MfGames.Markdown.csproj"/>
</ItemGroup>
</Project>

View file

@ -0,0 +1,188 @@
using Markdig;
using MfGames.Markdown.Extensions;
using MfGames.TestSetup;
using Xunit;
using Xunit.Abstractions;
namespace MfGames.Markdown.Tests;
/// <summary>
/// Tests the functionality of the WriteFiles().
/// </summary>
public class WikiLinkTest : TestBase<TestContext>
{
public WikiLinkTest(ITestOutputHelper output)
: base(output)
{
}
[Fact]
public void BareStringHtml()
{
MarkdownPipeline pipeline = CreatePipeline();
string result = Markdig.Markdown.ToHtml(
"This is text.",
pipeline);
Assert.Equal("<p>This is text.</p>\n", result);
}
[Fact]
public void BlankStringHtml()
{
MarkdownPipeline pipeline = CreatePipeline();
string result = Markdig.Markdown.ToHtml(
"",
pipeline);
Assert.Equal("", result);
}
[Fact]
public void LabeledWikiLinkHtml()
{
MarkdownPipeline pipeline = CreatePipeline();
string result = Markdig.Markdown
.ToHtml(
"[[Test|Label]]",
pipeline)
.Replace("%5E", "^");
Assert.Equal("<p><a href=\"^test$\">Label</a></p>\n", result);
}
[Fact]
public void PossessiveLabeledWikiLinkHtml()
{
MarkdownPipeline pipeline = CreatePipeline();
string result = Markdig.Markdown
.ToHtml(
"[[Test|Label]]'s",
pipeline)
.Replace("%5E", "^");
Assert.Equal("<p><a href=\"^test$\">Label's</a></p>\n", result);
}
[Fact]
public void PossessiveWikiLinkHtml()
{
MarkdownPipeline pipeline = CreatePipeline();
string result = Markdig.Markdown
.ToHtml(
"[[Test]]'s",
pipeline)
.Replace("%5E", "^");
Assert.Equal("<p><a href=\"^test$\">Test's</a></p>\n", result);
}
[Fact]
public void PunctuationLabeledWikiLinkHtml()
{
MarkdownPipeline pipeline = CreatePipeline();
string result = Markdig.Markdown
.ToHtml(
"[[Test|Label]].",
pipeline)
.Replace("%5E", "^");
Assert.Equal("<p><a href=\"^test$\">Label</a>.</p>\n", result);
}
[Fact]
public void PunctuationWikiLinkHtml()
{
MarkdownPipeline pipeline = CreatePipeline();
string result = Markdig.Markdown
.ToHtml(
"[[Test]].",
pipeline)
.Replace("%5E", "^");
Assert.Equal("<p><a href=\"^test$\">Test</a>.</p>\n", result);
}
[Fact]
public void SentenceWikiLinkHtml()
{
MarkdownPipeline pipeline = CreatePipeline();
string result = Markdig.Markdown
.ToHtml(
"This is a [[test]] of this system.",
pipeline)
.Replace("%5E", "^");
Assert.Equal(
"<p>This is a <a href=\"^test$\">test</a> of this system.</p>\n",
result);
}
[Fact]
public void SimpleWikiLinkHtml()
{
MarkdownPipeline pipeline = CreatePipeline();
string result = Markdig.Markdown
.ToHtml(
"[[Test]]",
pipeline)
.Replace("%5E", "^");
Assert.Equal("<p><a href=\"^test$\">Test</a></p>\n", result);
}
[Fact]
public void StandardLinkHtml()
{
MarkdownPipeline pipeline = CreatePipeline();
string result = Markdig.Markdown.ToHtml(
"[Test](https://test/)",
pipeline);
Assert.Equal("<p><a href=\"https://test/\">Test</a></p>\n", result);
}
[Fact]
public void TrailingLabeledWikiLinkHtml()
{
MarkdownPipeline pipeline = CreatePipeline();
string result = Markdig.Markdown
.ToHtml(
"[[Test|Label]]s",
pipeline)
.Replace("%5E", "^");
Assert.Equal("<p><a href=\"^test$\">Labels</a></p>\n", result);
}
[Fact]
public void TrailingWikiLinkHtml()
{
MarkdownPipeline pipeline = CreatePipeline();
string result = Markdig.Markdown
.ToHtml(
"[[Test]]s",
pipeline)
.Replace("%5E", "^");
Assert.Equal("<p><a href=\"^test$\">Tests</a></p>\n", result);
}
private static MarkdownPipeline CreatePipeline()
{
WikiLinkOptions options = new()
{
GetUrl = (title) => string.Format(
"^{0}$",
title.ToLowerInvariant().Replace(" ", "-")),
};
MarkdownPipelineBuilder? builder = new MarkdownPipelineBuilder()
.Use(new WikiLinkExtension(options));
MarkdownPipeline? pipeline = builder.Build();
return pipeline;
}
}