feat: implemented a JSON project as a variant of YAML

This commit is contained in:
D. Moonfire 2023-01-15 13:57:43 -06:00
parent c5c9b8bf9c
commit 0a36d70fb0
16 changed files with 395 additions and 32 deletions

View file

@ -47,6 +47,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MfGames.Nitride.Temporal.Te
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MfGames.Nitride.Markdown.Tests", "tests\MfGames.Nitride.Markdown.Tests\MfGames.Nitride.Markdown.Tests.csproj", "{2AAE2B69-A93D-4045-B7E6-A32ED08D0D65}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MfGames.Nitride.Markdown.Tests", "tests\MfGames.Nitride.Markdown.Tests\MfGames.Nitride.Markdown.Tests.csproj", "{2AAE2B69-A93D-4045-B7E6-A32ED08D0D65}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MfGames.Nitride.Json", "src\MfGames.Nitride.Json\MfGames.Nitride.Json.csproj", "{9A0D2BEE-859A-4E74-8CA7-5E0FB7C2B113}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MfGames.Nitride.Json.Tests", "tests\MfGames.Nitride.Json.Tests\MfGames.Nitride.Json.Tests.csproj", "{7CCC3A82-D5FE-4D54-9751-5E7985DE1F26}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -288,6 +292,30 @@ Global
{2AAE2B69-A93D-4045-B7E6-A32ED08D0D65}.Release|x64.Build.0 = Release|Any CPU {2AAE2B69-A93D-4045-B7E6-A32ED08D0D65}.Release|x64.Build.0 = Release|Any CPU
{2AAE2B69-A93D-4045-B7E6-A32ED08D0D65}.Release|x86.ActiveCfg = Release|Any CPU {2AAE2B69-A93D-4045-B7E6-A32ED08D0D65}.Release|x86.ActiveCfg = Release|Any CPU
{2AAE2B69-A93D-4045-B7E6-A32ED08D0D65}.Release|x86.Build.0 = Release|Any CPU {2AAE2B69-A93D-4045-B7E6-A32ED08D0D65}.Release|x86.Build.0 = Release|Any CPU
{9A0D2BEE-859A-4E74-8CA7-5E0FB7C2B113}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9A0D2BEE-859A-4E74-8CA7-5E0FB7C2B113}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9A0D2BEE-859A-4E74-8CA7-5E0FB7C2B113}.Debug|x64.ActiveCfg = Debug|Any CPU
{9A0D2BEE-859A-4E74-8CA7-5E0FB7C2B113}.Debug|x64.Build.0 = Debug|Any CPU
{9A0D2BEE-859A-4E74-8CA7-5E0FB7C2B113}.Debug|x86.ActiveCfg = Debug|Any CPU
{9A0D2BEE-859A-4E74-8CA7-5E0FB7C2B113}.Debug|x86.Build.0 = Debug|Any CPU
{9A0D2BEE-859A-4E74-8CA7-5E0FB7C2B113}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9A0D2BEE-859A-4E74-8CA7-5E0FB7C2B113}.Release|Any CPU.Build.0 = Release|Any CPU
{9A0D2BEE-859A-4E74-8CA7-5E0FB7C2B113}.Release|x64.ActiveCfg = Release|Any CPU
{9A0D2BEE-859A-4E74-8CA7-5E0FB7C2B113}.Release|x64.Build.0 = Release|Any CPU
{9A0D2BEE-859A-4E74-8CA7-5E0FB7C2B113}.Release|x86.ActiveCfg = Release|Any CPU
{9A0D2BEE-859A-4E74-8CA7-5E0FB7C2B113}.Release|x86.Build.0 = Release|Any CPU
{7CCC3A82-D5FE-4D54-9751-5E7985DE1F26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7CCC3A82-D5FE-4D54-9751-5E7985DE1F26}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7CCC3A82-D5FE-4D54-9751-5E7985DE1F26}.Debug|x64.ActiveCfg = Debug|Any CPU
{7CCC3A82-D5FE-4D54-9751-5E7985DE1F26}.Debug|x64.Build.0 = Debug|Any CPU
{7CCC3A82-D5FE-4D54-9751-5E7985DE1F26}.Debug|x86.ActiveCfg = Debug|Any CPU
{7CCC3A82-D5FE-4D54-9751-5E7985DE1F26}.Debug|x86.Build.0 = Debug|Any CPU
{7CCC3A82-D5FE-4D54-9751-5E7985DE1F26}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7CCC3A82-D5FE-4D54-9751-5E7985DE1F26}.Release|Any CPU.Build.0 = Release|Any CPU
{7CCC3A82-D5FE-4D54-9751-5E7985DE1F26}.Release|x64.ActiveCfg = Release|Any CPU
{7CCC3A82-D5FE-4D54-9751-5E7985DE1F26}.Release|x64.Build.0 = Release|Any CPU
{7CCC3A82-D5FE-4D54-9751-5E7985DE1F26}.Release|x86.ActiveCfg = Release|Any CPU
{7CCC3A82-D5FE-4D54-9751-5E7985DE1F26}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(NestedProjects) = preSolution GlobalSection(NestedProjects) = preSolution
{D480943C-764D-4A8A-B546-642ED10586BB} = {570184FD-ECE4-4EC8-86E1-C1265E17D647} {D480943C-764D-4A8A-B546-642ED10586BB} = {570184FD-ECE4-4EC8-86E1-C1265E17D647}
@ -309,5 +337,7 @@ Global
{C49E07D0-CD32-4332-90FA-07494195CAC4} = {251D9C68-34EB-439D-B167-688BCC47DA17} {C49E07D0-CD32-4332-90FA-07494195CAC4} = {251D9C68-34EB-439D-B167-688BCC47DA17}
{0B74A4DE-4F92-44EE-8273-E5A15EAB4266} = {251D9C68-34EB-439D-B167-688BCC47DA17} {0B74A4DE-4F92-44EE-8273-E5A15EAB4266} = {251D9C68-34EB-439D-B167-688BCC47DA17}
{2AAE2B69-A93D-4045-B7E6-A32ED08D0D65} = {251D9C68-34EB-439D-B167-688BCC47DA17} {2AAE2B69-A93D-4045-B7E6-A32ED08D0D65} = {251D9C68-34EB-439D-B167-688BCC47DA17}
{9A0D2BEE-859A-4E74-8CA7-5E0FB7C2B113} = {570184FD-ECE4-4EC8-86E1-C1265E17D647}
{7CCC3A82-D5FE-4D54-9751-5E7985DE1F26} = {251D9C68-34EB-439D-B167-688BCC47DA17}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View file

@ -0,0 +1,9 @@
namespace MfGames.Nitride.Json;
/// <summary>
/// A marker class that indicates that the entity is JSON.
/// </summary>
public record IsJson
{
public static IsJson Instance { get; } = new();
}

View file

@ -0,0 +1,16 @@
using MfGames.Gallium;
namespace MfGames.Nitride.Json;
public static class IsJsonExtensions
{
public static Entity RemoveIsJson(this Entity entity)
{
return entity.Remove<IsJson>();
}
public static Entity SetIsJson(this Entity entity)
{
return entity.Set(IsJson.Instance);
}
}

View file

@ -0,0 +1,33 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<Description>An extension to Nitride static site generator to parse JSON content.</Description>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\MfGames.Nitride\MfGames.Nitride.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MfGames.Gallium" Version="0.3.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
</ItemGroup>
<!-- Include the source generator -->
<PropertyGroup>
<EmitCompilerGeneratedFiles>True</EmitCompilerGeneratedFiles>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\MfGames.Nitride.Generators\MfGames.Nitride.Generators.csproj">
<OutputItemType>Analyzer</OutputItemType>
<ReferenceOutputAssembly>False</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
</Project>

View file

@ -0,0 +1,12 @@
using Autofac;
namespace MfGames.Nitride.Json;
public static class NitrideJsonBuilderExtensions
{
public static NitrideBuilder UseJson(this NitrideBuilder builder)
{
return builder.ConfigureContainer(
x => x.RegisterModule<NitrideJsonModule>());
}
}

View file

@ -0,0 +1,77 @@
using System;
using MfGames.Gallium;
using MfGames.Nitride.Contents;
using Newtonsoft.Json;
namespace MfGames.Nitride.Json;
public static class NitrideJsonEntityExtensions
{
/// <summary>
/// Parses the entity text as a JSON file and returns the results.
/// </summary>
public static TType? GetTextContentJson<TType>(
this Entity entity,
Action<JsonSerializerSettings> configure)
{
JsonSerializerSettings settings = new();
configure.Invoke(settings);
return entity.GetTextContentJson<TType>(settings);
}
/// <summary>
/// Parses the entity text as a JSON file and returns the results.
/// </summary>
public static TType? GetTextContentJson<TType>(
this Entity entity,
JsonSerializerSettings? settings = null)
{
string? text = entity.GetTextContentString();
return text != null
? JsonConvert.DeserializeObject<TType>(text, settings)
: default;
}
/// <summary>
/// Sets the text content to the serialized value. If this is null, then
/// the text content is removed. This uses the default serializer which
/// may be configured.
/// </summary>
/// <returns>The same entity for chaining methods.</returns>
public static Entity SetTextContentJson<TType>(
this Entity entity,
TType? value,
Action<JsonSerializerSettings> configure)
{
JsonSerializerSettings settings = new();
configure.Invoke(settings);
return SetTextContentJson(entity, value, settings);
}
/// <summary>
/// Sets the text content to the serialized value using the serializer
/// provided. If the value is null, then the text content is removed.
/// </summary>
/// <returns>The same entity for chaining methods.</returns>
public static Entity SetTextContentJson<TType>(
this Entity entity,
TType? value,
JsonSerializerSettings? settings = null)
{
if (value == null)
{
return entity.Remove<ITextContent>();
}
string json = JsonConvert.SerializeObject(value, settings);
return entity.SetTextContent(json);
}
}

View file

@ -0,0 +1,13 @@
using Autofac;
namespace MfGames.Nitride.Json;
public class NitrideJsonModule : Module
{
/// <inheritdoc />
protected override void Load(ContainerBuilder builder)
{
builder.RegisterOperators(this);
builder.RegisterValidators(this);
}
}

View file

@ -1,7 +1,7 @@
namespace MfGames.Nitride.Yaml; namespace MfGames.Nitride.Yaml;
/// <summary> /// <summary>
/// A marker class that indicates that the has a YAML model. /// A marker class that indicates that entity has a YAML model.
/// </summary> /// </summary>
public record HasYamlModel public record HasYamlModel
{ {

View file

@ -10,9 +10,10 @@ namespace MfGames.Nitride.Yaml;
public static class NitrideYamlEntityExtensions public static class NitrideYamlEntityExtensions
{ {
/// <summary> /// <summary>
/// Parses the entity text as a YAML file and returns the results. /// Parses the entity text as a YAML file and returns the results. This
/// uses the default serializer, which may be configured.
/// </summary> /// </summary>
public static TType? GetYaml<TType>( public static TType? GetTextContentYaml<TType>(
this Entity entity, this Entity entity,
Action<DeserializerBuilder>? configure = null) Action<DeserializerBuilder>? configure = null)
{ {
@ -22,13 +23,14 @@ public static class NitrideYamlEntityExtensions
IDeserializer deserializer = builder.Build(); IDeserializer deserializer = builder.Build();
return entity.GetYaml<TType>(deserializer); return entity.GetTextContentYaml<TType>(deserializer);
} }
/// <summary> /// <summary>
/// Parses the entity text as a YAML file and returns the results. /// Parses the entity text as a YAML file using the given serializer and
/// returns the results.
/// </summary> /// </summary>
public static TType? GetYaml<TType>( public static TType? GetTextContentYaml<TType>(
this Entity entity, this Entity entity,
IDeserializer deserializer) IDeserializer deserializer)
{ {
@ -38,4 +40,44 @@ public static class NitrideYamlEntityExtensions
? deserializer.Deserialize<TType>(text) ? deserializer.Deserialize<TType>(text)
: default; : default;
} }
/// <summary>
/// Sets the text content to the serialized value. If this is null, then
/// the text content is removed. This uses the default serializer which
/// may be configured.
/// </summary>
/// <returns>The same entity for chaining methods.</returns>
public static Entity SetTextContentYaml<TType>(
this Entity entity,
TType? value,
Action<SerializerBuilder>? configure = null)
{
SerializerBuilder builder = new();
configure?.Invoke(builder);
ISerializer serializer = builder.Build();
return SetTextContentYaml(entity, value, serializer);
}
/// <summary>
/// Sets the text content to the serialized value using the serializer
/// provided. If the value is null, then the text content is removed.
/// </summary>
/// <returns>The same entity for chaining methods.</returns>
public static Entity SetTextContentYaml<TType>(
this Entity entity,
TType? value,
ISerializer serializer)
{
if (value == null)
{
return entity.Remove<ITextContent>();
}
string yaml = serializer.Serialize(value);
return entity.SetTextContent(yaml);
}
} }

View file

@ -15,7 +15,7 @@
<PackageReference Include="MfGames.Gallium" Version="0.3.0" /> <PackageReference Include="MfGames.Gallium" Version="0.3.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" />
<PackageReference Include="JunitXml.TestLogger" Version="3.0.114" /> <PackageReference Include="JunitXml.TestLogger" Version="3.0.114" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1"/> <PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
<PackageReference Include="xunit" Version="2.4.2" /> <PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5"> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>

View file

@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MfGames.Gallium" Version="0.3.0" />
<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="..\MfGames.Nitride.Tests\MfGames.Nitride.Tests.csproj" />
<ProjectReference Include="..\..\src\MfGames.Nitride.Json\MfGames.Nitride.Json.csproj" />
<ProjectReference Include="..\..\src\MfGames.Nitride\MfGames.Nitride.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,51 @@
using MfGames.Gallium;
using MfGames.Nitride.Tests;
using Xunit;
using Xunit.Abstractions;
namespace MfGames.Nitride.Json.Tests;
public class TextContentJsonTests : NitrideTestBase
{
public TextContentJsonTests(ITestOutputHelper output)
: base(output)
{
}
[Fact]
public void NoTextContent()
{
Entity entity = new();
TestContent? output = entity.GetTextContentJson<TestContent>();
Assert.Null(output);
}
[Fact]
public void SetAndGetContent()
{
Entity entity = new Entity()
.SetTextContentJson(new TestContent { Value = "t1" });
TestContent? output = entity.GetTextContentJson<TestContent>();
Assert.NotNull(output);
Assert.Equal("t1", output.Value);
}
[Fact]
public void SetNullRemovesContent()
{
Entity entity = new Entity()
.SetTextContentJson(new TestContent { Value = "t1" })
.SetTextContentJson<TestContent>(null);
TestContent? output = entity.GetTextContentJson<TestContent>();
Assert.Null(output);
}
private class TestContent
{
public string? Value { get; set; }
}
}

View file

@ -15,7 +15,7 @@
<PackageReference Include="MfGames.Gallium" Version="0.3.0" /> <PackageReference Include="MfGames.Gallium" Version="0.3.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.1" />
<PackageReference Include="JunitXml.TestLogger" Version="3.0.114" /> <PackageReference Include="JunitXml.TestLogger" Version="3.0.114" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1"/> <PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
<PackageReference Include="xunit" Version="2.4.2" /> <PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5"> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>

View file

@ -10,9 +10,9 @@ using Xunit.Abstractions;
namespace MfGames.Nitride.Yaml.Tests; namespace MfGames.Nitride.Yaml.Tests;
public class ParseYamlHeaderTest : NitrideTestBase public class ParseYamlHeaderTests : NitrideTestBase
{ {
public ParseYamlHeaderTest(ITestOutputHelper output) public ParseYamlHeaderTests(ITestOutputHelper output)
: base(output) : base(output)
{ {
} }

View file

@ -0,0 +1,51 @@
using MfGames.Gallium;
using MfGames.Nitride.Tests;
using Xunit;
using Xunit.Abstractions;
namespace MfGames.Nitride.Yaml.Tests;
public class TextContentYamlTests : NitrideTestBase
{
public TextContentYamlTests(ITestOutputHelper output)
: base(output)
{
}
[Fact]
public void NoTextContent()
{
Entity entity = new();
TestContent? output = entity.GetTextContentYaml<TestContent>();
Assert.Null(output);
}
[Fact]
public void SetAndGetContent()
{
Entity entity = new Entity()
.SetTextContentYaml(new TestContent { Value = "t1" });
TestContent? output = entity.GetTextContentYaml<TestContent>();
Assert.NotNull(output);
Assert.Equal("t1", output.Value);
}
[Fact]
public void SetNullRemovesContent()
{
Entity entity = new Entity()
.SetTextContentYaml(new TestContent { Value = "t1" })
.SetTextContentYaml<TestContent>(null);
TestContent? output = entity.GetTextContentYaml<TestContent>();
Assert.Null(output);
}
private class TestContent
{
public string? Value { get; set; }
}
}