diff --git a/LICENSE.md b/LICENSE.md index 4eedaf8..c026327 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021 Bryan Wilhite +Copyright (c) 2023 Bryan Wilhite Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Songhay.Publications.Tests/Extensions/ISegmentExtensionsTests.cs b/Songhay.Publications.Tests/Extensions/ISegmentExtensionsTests.cs index bdd816e..74033d6 100644 --- a/Songhay.Publications.Tests/Extensions/ISegmentExtensionsTests.cs +++ b/Songhay.Publications.Tests/Extensions/ISegmentExtensionsTests.cs @@ -226,17 +226,17 @@ public void ToPublicationIndexEntryJObject_Test(FileInfo indexInfo) _testOutputHelper.WriteLine($"converting {nameof(Segment)} `{segment.SegmentName}`..."); - var jIndex = segment.ToPublicationIndexEntryJObject(useJavaScriptCase: true); - Assert.NotNull(jIndex); - _testOutputHelper.WriteLine($"{nameof(Segment)} `{segment.SegmentName}` parsed:"); - _testOutputHelper.WriteLine(jIndex.ToString()); - - var jDocuments = jIndex.GetJArray(nameof(Segment.Documents).ToLowerInvariant(), throwException: false); - Assert.Null(jDocuments); - - var jSegments = jIndex.GetJArray(nameof(Segment.Segments).ToLowerInvariant(), throwException: false); - Assert.NotNull(jSegments); - Assert.True(jSegments.Any()); + // var jIndex = segment.ToPublicationIndexEntryJObject(useJavaScriptCase: true); + // Assert.NotNull(jIndex); + // _testOutputHelper.WriteLine($"{nameof(Segment)} `{segment.SegmentName}` parsed:"); + // _testOutputHelper.WriteLine(jIndex.ToString()); + // + // var jDocuments = jIndex.GetJArray(nameof(Segment.Documents).ToLowerInvariant(), throwException: false); + // Assert.Null(jDocuments); + // + // var jSegments = jIndex.GetJArray(nameof(Segment.Segments).ToLowerInvariant(), throwException: false); + // Assert.NotNull(jSegments); + // Assert.True(jSegments.Any()); } readonly ITestOutputHelper _testOutputHelper; diff --git a/Songhay.Publications.Tests/Extensions/JObjectExtensionsTests.cs b/Songhay.Publications.Tests/Extensions/JObjectExtensionsTests.cs index 8f05070..d4d91dc 100644 --- a/Songhay.Publications.Tests/Extensions/JObjectExtensionsTests.cs +++ b/Songhay.Publications.Tests/Extensions/JObjectExtensionsTests.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json.Linq; +using System.Text.Json; using Songhay.Extensions; using Songhay.Models; using Songhay.Publications.Activities; @@ -8,9 +8,9 @@ namespace Songhay.Publications.Tests.Extensions; -public class JObjectExtensionsTests +public class JsonElementExtensionsTests { - public JObjectExtensionsTests(ITestOutputHelper helper) + public JsonElementExtensionsTests(ITestOutputHelper helper) { _testOutputHelper = helper; } @@ -32,7 +32,7 @@ public void GetAddEntryExtractArg_Test(string settingsFile, string presentationR Assert.True(presentationInfo.Exists); Assert.True(settingsInfo.Exists); - var jO = JObject.Parse(File.ReadAllText(settingsInfo.FullName)); + var jO = JsonDocument.Parse(File.ReadAllText(settingsInfo.FullName)).ToReferenceTypeValueOrThrow().RootElement; var entryPath = jO.GetAddEntryExtractArg(presentationInfo); Assert.True(File.Exists(entryPath)); @@ -58,7 +58,7 @@ public void GetCompressed11tyIndexArgs_Test(string settingsFile, string presenta Assert.True(presentationInfo.Exists); Assert.True(settingsInfo.Exists); - var jO = JObject.Parse(File.ReadAllText(settingsInfo.FullName)); + var jO = JsonDocument.Parse(File.ReadAllText(settingsInfo.FullName)).ToReferenceTypeValueOrThrow().RootElement; var (entryRootInfo, indexRootInfo, indexFileName) = jO.GetCompressed11TyIndexArgs(presentationInfo); Assert.True(entryRootInfo.Exists); @@ -88,7 +88,7 @@ public void GetExpandUrisArgs_Test(string settingsFile, string presentationRoot) Assert.True(presentationInfo.Exists); Assert.True(settingsInfo.Exists); - var jO = JObject.Parse(File.ReadAllText(settingsInfo.FullName)); + var jO = JsonDocument.Parse(File.ReadAllText(settingsInfo.FullName)).ToReferenceTypeValueOrThrow().RootElement; var (entryPath, collapsedHost) = jO.GetExpandUrisArgs(presentationInfo); Assert.True(File.Exists(entryPath)); @@ -115,7 +115,7 @@ public void GetFindChangeArgs_Test(string settingsFile, string presentationRoot) Assert.True(presentationInfo.Exists); Assert.True(settingsInfo.Exists); - var jO = JObject.Parse(File.ReadAllText(settingsInfo.FullName)); + var jO = JsonDocument.Parse(File.ReadAllText(settingsInfo.FullName)).ToReferenceTypeValueOrThrow().RootElement; var (input, pattern, replacement, useRegex, outputPath) = jO.GetFindChangeArgs(presentationInfo); Assert.False(string.IsNullOrEmpty(input)); @@ -124,7 +124,7 @@ public void GetFindChangeArgs_Test(string settingsFile, string presentationRoot) Assert.True(useRegex); Assert.False(string.IsNullOrEmpty(outputPath)); - var inputPath = jO.GetValue("inputPath"); + var inputPath = jO.GetProperty("inputPath").GetString(); _testOutputHelper.WriteLine($"{nameof(inputPath)}: {inputPath}"); _testOutputHelper.WriteLine($"{nameof(input)}: {input.Substring(0, 16)}..."); @@ -151,7 +151,7 @@ public void GetGenerateEntryArgs_Test(string settingsFile, string presentationRo Assert.True(presentationInfo.Exists); Assert.True(settingsInfo.Exists); - var jO = JObject.Parse(File.ReadAllText(settingsInfo.FullName)); + var jO = JsonDocument.Parse(File.ReadAllText(settingsInfo.FullName)).ToReferenceTypeValueOrThrow().RootElement; var (entryDraftsRootInfo, title) = jO.GetGenerateEntryArgs(presentationInfo); Assert.True(entryDraftsRootInfo.Exists); @@ -178,7 +178,7 @@ public void GetPublishEntryArgs_Test(string settingsFile, string presentationRoo Assert.True(presentationInfo.Exists); Assert.True(settingsInfo.Exists); - var jO = JObject.Parse(File.ReadAllText(settingsInfo.FullName)); + var jO = JsonDocument.Parse(File.ReadAllText(settingsInfo.FullName)).ToReferenceTypeValueOrThrow().RootElement; var (entryDraftsRootInfo, entryRootInfo, entryFileName) = jO.GetPublishEntryArgs(presentationInfo); diff --git a/Songhay.Publications.Tests/Extensions/MarkdownEntryExtensionsTests.cs b/Songhay.Publications.Tests/Extensions/MarkdownEntryExtensionsTests.cs index f72124c..88b1764 100644 --- a/Songhay.Publications.Tests/Extensions/MarkdownEntryExtensionsTests.cs +++ b/Songhay.Publications.Tests/Extensions/MarkdownEntryExtensionsTests.cs @@ -1,8 +1,7 @@ -using Newtonsoft.Json.Linq; +using System.Text.Json.Nodes; using Songhay.Publications.Extensions; using Songhay.Publications.Models; using Songhay.Tests; -using Songhay.Extensions; using Xunit; using Xunit.Abstractions; @@ -78,7 +77,7 @@ public void ToMarkdownEntry_Test(string clientId, FileInfo entryInfo) // assert Assert.NotNull(jFrontMatter); - Assert.Equal(clientId, jFrontMatter.GetValue("clientId")); + Assert.Equal(clientId, jFrontMatter["clientId"]?.GetValue()); } [Theory] @@ -130,10 +129,10 @@ public void With11tyExtract_Test(string? title, string? content, string? path, s .WithNew11TyFrontMatter(title, DateTime.Now, path, tag) .WithContentHeader() .WithEdit(i => i.Content = string.Concat(i.Content, content)).With11TyExtract(length); - var jO = JObject.Parse(entry.FrontMatter.GetValue("tag")); + var jO = JsonNode.Parse(entry.FrontMatter["tag"].GetValue()); Assert.NotNull(jO); - var extract = jO.GetValue("extract"); + var extract = jO["extract"].GetValue(); _testOutputHelper.WriteLine($"front matter (input-tag: `{tag ?? "[null]"}`):"); _testOutputHelper.WriteLine($"{entry.FrontMatter}"); @@ -153,10 +152,10 @@ public void With11tyExtract_FromFile_Test(int expectedLength, FileInfo entryInfo var entry = entryInfo.ToMarkdownEntry() .With11TyExtract(expectedLength); - var jO = JObject.Parse(entry.FrontMatter.GetValue("tag")); + var jO = JsonNode.Parse(entry.FrontMatter["tag"]?.GetValue()); Assert.NotNull(jO); - var extract = jO.GetValue("extract"); + var extract = jO["extract"]?.GetValue(); Assert.False(string.IsNullOrWhiteSpace(extract)); Assert.Equal(expectedLength + 1, extract.Length); @@ -177,7 +176,7 @@ public void WithNew11tyFrontMatterAndContentHeaderAndTouch_Test() entry.Touch(DateTime.Now); //assert - Assert.True(entry.FrontMatter.GetValue("modificationDate") > inceptDate); + Assert.True(entry.FrontMatter["modificationDate"]?.GetValue() > inceptDate); } readonly ITestOutputHelper _testOutputHelper; diff --git a/Songhay.Publications.Tests/MarkdownEntryUtilityTests.cs b/Songhay.Publications.Tests/MarkdownEntryUtilityTests.cs index 83eaff1..e2c432f 100644 --- a/Songhay.Publications.Tests/MarkdownEntryUtilityTests.cs +++ b/Songhay.Publications.Tests/MarkdownEntryUtilityTests.cs @@ -1,5 +1,4 @@ -using Songhay.Extensions; -using Songhay.Tests; +using Songhay.Tests; using Xunit; namespace Songhay.Publications.Tests; @@ -15,7 +14,7 @@ public void GenerateEntryFor11ty_Test(string entryRoot, string title) var entry = MarkdownEntryUtility.GenerateEntryFor11Ty(entryRoot, title); Assert.NotNull(entry); - Assert.True(File.Exists(ProgramFileUtility.GetCombinedPath(entryRoot, $"{entry.FrontMatter.GetValue("clientId")}.md"))); + Assert.True(File.Exists(ProgramFileUtility.GetCombinedPath(entryRoot, $"{entry.FrontMatter["clientId"]?.GetValue()}.md"))); } [DebuggerAttachedTheory] diff --git a/Songhay.Publications/Activities/MarkdownEntryActivity.cs b/Songhay.Publications/Activities/MarkdownEntryActivity.cs index c5b9bab..2fd1217 100644 --- a/Songhay.Publications/Activities/MarkdownEntryActivity.cs +++ b/Songhay.Publications/Activities/MarkdownEntryActivity.cs @@ -1,5 +1,5 @@ -using System.Text.RegularExpressions; -using Newtonsoft.Json.Linq; +using System.Text.Json; +using System.Text.RegularExpressions; namespace Songhay.Publications.Activities; @@ -33,7 +33,7 @@ public static void AddEntryExtract(string? entryPath) File.WriteAllText(entryInfo.FullName, $"{finalEdit}"); - var clientId = entry.FrontMatter.GetValue("clientId"); + var clientId = entry.FrontMatter["clientId"].ToReferenceTypeValueOrThrow().GetValue(); TraceSource?.WriteLine($"{nameof(MarkdownEntryActivity)}: Added entry extract: {clientId}"); } @@ -148,7 +148,7 @@ public static void GenerateEntry(DirectoryInfo entryDraftsRootInfo, string title throw new NullReferenceException($"The expected {nameof(entry)} is not here."); } - var clientId = entry.FrontMatter.GetValue("clientId"); + var clientId = entry.FrontMatter["clientId"].ToReferenceTypeValueOrThrow().GetValue(); TraceSource?.WriteLine($"{nameof(MarkdownEntryActivity)}: Generated entry: {clientId}"); } @@ -233,16 +233,16 @@ internal void PublishEntry() PublishEntry(entryDraftsRootInfo, entryRootInfo, entryFileName); } - internal (DirectoryInfo presentationInfo, JObject jSettings) GetContext(ProgramArgs? args) + internal (DirectoryInfo presentationInfo, JsonElement jSettings) GetContext(ProgramArgs? args) { var (presentationInfo, settingsInfo) = args.ToPresentationAndSettingsInfo(); TraceSource?.TraceVerbose($"applying settings..."); - var jSettings = JObject.Parse(File.ReadAllText(settingsInfo.FullName)); + var jSettings = JsonDocument.Parse(File.ReadAllText(settingsInfo.FullName)).ToReferenceTypeValueOrThrow().RootElement; return (presentationInfo, jSettings); } DirectoryInfo? _presentationInfo; - JObject? _jSettings; + JsonElement _jSettings; } diff --git a/Songhay.Publications/Activities/SearchIndexActivity.cs b/Songhay.Publications/Activities/SearchIndexActivity.cs index 482ec05..2bceae7 100644 --- a/Songhay.Publications/Activities/SearchIndexActivity.cs +++ b/Songhay.Publications/Activities/SearchIndexActivity.cs @@ -1,5 +1,6 @@ using System.IO.Compression; -using Newtonsoft.Json.Linq; +using System.Text.Json; +using System.Text.Json.Nodes; namespace Songhay.Publications.Activities; @@ -61,22 +62,22 @@ public static FileInfo[] GenerateSearchIndexFrom11TyEntries(DirectoryInfo entryR var frontMatterDocumentCollections = entryRootInfo .GetFiles("*.md", SearchOption.AllDirectories) .Select(fileInfo => fileInfo.ToMarkdownEntry().FrontMatter) - .Select(jO => JObject.FromObject(new + .Select(jO => new { - extract = JObject.Parse(jO.GetValue("tag", throwException: false) ?? @"{ ""extract"": ""[empty]"" }").GetValue("extract"), - clientId = jO.GetValue("clientId", throwException: false) ?? "[empty]", - inceptDate = jO.GetValue("date", throwException: false) ?? string.Empty, - modificationDate = jO.GetValue("modificationDate", throwException: false) ?? string.Empty, - title = jO.GetValue("title", throwException: false) ?? string.Empty - })) - .OrderByDescending(o => o.GetValue("clientId")) + extract = JsonNode.Parse(jO["tag"]?.GetValue() ?? @"{ ""extract"": ""[empty]"" }")?.AsObject()["extract"]?.GetValue(), + clientId = jO["clientId"]?.GetValue() ?? "[empty]", + inceptDate = jO["date"]?.GetValue() ?? string.Empty, + modificationDate = jO["modificationDate"]?.GetValue() ?? string.Empty, + title = jO["title"]?.GetValue() ?? string.Empty + }.ToJsonNode().ToReferenceTypeValueOrThrow()) + .OrderByDescending(o => o["clientId"]?.GetValue()) .Partition(partitionSize); var indices = new List(); var count = 0; foreach (var frontMatterDocuments in frontMatterDocumentCollections) { - var jA = new JArray(frontMatterDocuments); + var jA = new JsonArray(new JsonNodeOptions { PropertyNameCaseInsensitive = false },frontMatterDocuments.ToArray()); var path = indexRootInfo.ToCombinedPath(indexFileName.Replace(".json", $"-{count:00}.json")); indices.Add(new FileInfo(path)); @@ -135,16 +136,16 @@ internal void GenerateCompressed11TySearchIndex() } - internal (DirectoryInfo presentationInfo, JObject jSettings) GetContext(ProgramArgs? args) + internal (DirectoryInfo presentationInfo, JsonElement jSettings) GetContext(ProgramArgs? args) { var (presentationInfo, settingsInfo) = args.ToPresentationAndSettingsInfo(); TraceSource?.TraceVerbose($"applying settings..."); - var jSettings = JObject.Parse(File.ReadAllText(settingsInfo.FullName)); + var jSettings = JsonDocument.Parse(File.ReadAllText(settingsInfo.FullName)).ToReferenceTypeValueOrThrow().RootElement; return (presentationInfo, jSettings); } DirectoryInfo? _presentationInfo; - JObject? _jSettings; + JsonElement _jSettings; } diff --git a/Songhay.Publications/Extensions/IDocumentExtensions.cs b/Songhay.Publications/Extensions/IDocumentExtensions.cs index fd13e8b..d766fb6 100644 --- a/Songhay.Publications/Extensions/IDocumentExtensions.cs +++ b/Songhay.Publications/Extensions/IDocumentExtensions.cs @@ -1,8 +1,4 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using JsonSerializer = Newtonsoft.Json.JsonSerializer; - -namespace Songhay.Publications.Extensions; +namespace Songhay.Publications.Extensions; /// /// Extensions of @@ -153,28 +149,6 @@ public static string ToDisplayText(this IDocument? data, bool showIdOnly) return builder.ToString(); } - /// - /// Converts the to . - /// - /// The data. - /// when true use “camel” casing. - public static JObject? ToJObject(this IDocument? data, bool useJavaScriptCase) - { - if (data == null) return null; - - var settings = JsonSerializationUtility - .GetConventionalResolver(useJavaScriptCase) - .ToJsonSerializerSettings(); - - //TODO: consider making these optional: - settings.MissingMemberHandling = MissingMemberHandling.Ignore; - settings.NullValueHandling = NullValueHandling.Ignore; - - var jO = JObject.FromObject(data, JsonSerializer.Create(settings)); - - return jO; - } - /// /// Converts the into a menu display item model. /// diff --git a/Songhay.Publications/Extensions/IFragmentExtensions.cs b/Songhay.Publications/Extensions/IFragmentExtensions.cs index 8cb3b48..c744d76 100644 --- a/Songhay.Publications/Extensions/IFragmentExtensions.cs +++ b/Songhay.Publications/Extensions/IFragmentExtensions.cs @@ -1,8 +1,4 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using JsonSerializer = Newtonsoft.Json.JsonSerializer; - -namespace Songhay.Publications.Extensions; +namespace Songhay.Publications.Extensions; /// /// Extensions of @@ -119,28 +115,6 @@ public static string ToDisplayText(this IFragment? data, bool showIdOnly) return builder.ToString(); } - /// - /// Converts the to . - /// - /// The data. - /// when true use “camel” casing. - public static JObject? ToJObject(this IFragment? data, bool useJavaScriptCase) - { - if (data == null) return null; - - var settings = JsonSerializationUtility - .GetConventionalResolver(useJavaScriptCase) - .ToJsonSerializerSettings(); - - //TODO: consider making these optional: - settings.MissingMemberHandling = MissingMemberHandling.Ignore; - settings.NullValueHandling = NullValueHandling.Ignore; - - var jO = JObject.FromObject(data, JsonSerializer.Create(settings)); - - return jO; - } - /// /// Converts the into a menu display item model. /// diff --git a/Songhay.Publications/Extensions/ISegmentExtensions.cs b/Songhay.Publications/Extensions/ISegmentExtensions.cs index b70cb22..20a7991 100644 --- a/Songhay.Publications/Extensions/ISegmentExtensions.cs +++ b/Songhay.Publications/Extensions/ISegmentExtensions.cs @@ -1,9 +1,4 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using JsonSerializer = Newtonsoft.Json.JsonSerializer; - - -namespace Songhay.Publications.Extensions; +namespace Songhay.Publications.Extensions; /// /// Extensions of @@ -120,28 +115,6 @@ public static string ToDisplayText(this ISegment? data, bool showIdOnly) return builder.ToString(); } - /// - /// Converts the to . - /// - /// The data. - /// when true use “camel” casing. - public static JObject? ToJObject(this ISegment? data, bool useJavaScriptCase) - { - if (data == null) return null; - - var settings = JsonSerializationUtility - .GetConventionalResolver(useJavaScriptCase) - .ToJsonSerializerSettings(); - - //TODO: consider making these optional: - settings.MissingMemberHandling = MissingMemberHandling.Ignore; - settings.NullValueHandling = NullValueHandling.Ignore; - - var jO = JObject.FromObject(data, JsonSerializer.Create(settings)); - - return jO; - } - /// /// Converts the into a menu display item model. /// @@ -202,35 +175,6 @@ public static IIndexEntry ToPublicationIndexEntry(this ISegment? data) }; } - /// - /// Converts the to - /// in the shape of a Publications Index Entry. - /// - /// The data. - /// when true use “camel” casing. - public static JObject ToPublicationIndexEntryJObject(this ISegment? data, bool useJavaScriptCase) - { - var jSegment = data.ToJObject(useJavaScriptCase).ToReferenceTypeValueOrThrow(); - - if (data is not Segment segment) return jSegment; - - if (segment.Segments.Any()) - { - var jSegmentArray = new JArray(segment.Segments.Select(i => i.ToPublicationIndexEntryJObject(useJavaScriptCase))); - - jSegment[nameof(Segment.Segments).ToLowerInvariant()] = jSegmentArray; - } - - if (!segment.Documents.Any()) return jSegment; - { - var jDocumentArray = new JArray(segment.Documents.Select(i => i.ToJObject(useJavaScriptCase))); - - jSegment[nameof(Segment.Documents).ToLowerInvariant()] = jDocumentArray; - } - - return jSegment; - } - /// /// Converts the data to . /// diff --git a/Songhay.Publications/Extensions/JObjectExtensions._.cs b/Songhay.Publications/Extensions/JObjectExtensions._.cs deleted file mode 100644 index 719c362..0000000 --- a/Songhay.Publications/Extensions/JObjectExtensions._.cs +++ /dev/null @@ -1,139 +0,0 @@ -using Newtonsoft.Json.Linq; - -namespace Songhay.Publications.Extensions; - -/// -/// Extensions of -/// -public static partial class JObjectExtensions -{ - static JObjectExtensions() => TraceSource = TraceSources - .Instance - .GetTraceSourceFromConfiguredName() - .WithSourceLevels(); - - static readonly TraceSource? TraceSource; - - /// - /// Gets the publication command. - /// - /// The . - public static string? GetPublicationCommand(this JObject? jObject) => jObject.GetValue("command"); - - /// - /// Converts the to presentation . - /// - /// The . - public static Segment? ToPresentation(this JObject? jObject) - { - if (jObject == null) return null; - - var rootProperty = "presentation"; - - TraceSource?.TraceVerbose($"Converting {rootProperty} JSON to {nameof(Segment)} with descendants..."); - - var jPresentation = jObject.GetJObject(rootProperty); - var isPostedToServer = jPresentation.GetValue("is-posted-to-server"); - if (isPostedToServer) - { - var postedDate = jPresentation.GetValue("posted-date"); - TraceSource?.TraceVerbose($"This {rootProperty} was already posted on {postedDate}."); - return null; - } - - var jSegment = jPresentation.GetValue(nameof(Segment)); - var segment = jSegment.FromJObject(); - if (segment == null) - { - TraceSource?.TraceError($"The expected {nameof(Segment)} is not here."); - return null; - } - - var clientId = segment.ClientId; - if (string.IsNullOrEmpty(clientId)) - { - TraceSource?.TraceError("The expected Client ID is not here."); - return null; - } - - TraceSource?.TraceVerbose($"{nameof(Segment)}: {segment}"); - var validationResult = segment.ToValidationResult(); - if (!validationResult.IsValid) - { - TraceSource?.TraceError($"{nameof(Segment)} validation error(s)!"); - TraceSource?.TraceError(validationResult.Errors.First().ErrorMessage); - return null; - } - - var jDocuments = jSegment.GetJArray(nameof(segment.Documents), throwException: true); - if (!jDocuments.OfType().Any()) - { - TraceSource?.TraceError($"The expected JObject {nameof(Document)} enumeration is not here."); - return null; - } - - jDocuments.OfType().ForEachInEnumerable(i => - { - var document = i.FromJObject(); - if (document == null) - { - TraceSource?.TraceError($"The expected {nameof(Document)} is not here."); - return; - } - - if (document.ClientId != clientId) - { - TraceSource?.TraceError($"The expected {nameof(Document)} Client ID is not here."); - return; - } - - TraceSource?.TraceVerbose($"{nameof(Document)}: {document}"); - var validationResultForDocument = document.ToValidationResult(); - if (!validationResultForDocument.IsValid) - { - TraceSource?.TraceError($"{nameof(Document)} validation error(s)!"); - TraceSource?.TraceError(validationResultForDocument.Errors.First().ErrorMessage); - return; - } - - var jFragments = i.GetJArray(nameof(document.Fragments), throwException: false); - if ((jFragments == null) || !jFragments.OfType().Any()) - { - TraceSource?.TraceWarning($"The JObject {nameof(Fragment)} enumeration is not here."); - segment.Documents.Add(document); - return; - } - - jFragments.OfType().ForEachInEnumerable(j => - { - var fragment = j.FromJObject(); - if (fragment == null) - { - TraceSource?.TraceError($"The expected {nameof(Fragment)} is not here."); - return; - } - - if (fragment.ClientId != clientId) - { - TraceSource?.TraceError($"The expected {nameof(Fragment)} Client ID is not here."); - return; - } - - TraceSource?.TraceVerbose($"{nameof(Fragment)}: {fragment}"); - var validationResultForFragment = fragment.ToValidationResult(); - if (!validationResultForFragment.IsValid) - { - TraceSource?.TraceError($"{nameof(Fragment)} validation error(s)!"); - TraceSource?.TraceError(validationResultForFragment.Errors.First().ErrorMessage); - return; - } - - document.Fragments.Add(fragment); - }); - - segment.Documents.Add(document); - }); - - return segment; - } -} diff --git a/Songhay.Publications/Extensions/JObjectExtensions.args.cs b/Songhay.Publications/Extensions/JObjectExtensions.args.cs deleted file mode 100644 index 26ca313..0000000 --- a/Songhay.Publications/Extensions/JObjectExtensions.args.cs +++ /dev/null @@ -1,137 +0,0 @@ -using Newtonsoft.Json.Linq; - -namespace Songhay.Publications.Extensions; - -/// -/// Extensions of . -/// -public static partial class JObjectExtensions -{ - /// - /// Gets the arguments for Activity method. - /// - /// The . - /// The presentation information. - public static string GetAddEntryExtractArg(this JObject? jObject, DirectoryInfo? presentationInfo) - { - var entryPath = jObject.GetValue("entryPath"); - entryPath = presentationInfo.ToCombinedPath(entryPath); - - return entryPath; - } - - /// - /// Gets the arguments for Activity method. - /// - /// The . - /// The presentation information. - public static ( - DirectoryInfo entryRootInfo, - DirectoryInfo indexRootInfo, - string indexFileName - ) GetCompressed11TyIndexArgs(this JObject? jObject, DirectoryInfo? presentationInfo) - { - var indexRoot = jObject.GetValue("indexRoot"); - indexRoot = presentationInfo.ToCombinedPath(indexRoot); - var indexRootInfo = new DirectoryInfo(indexRoot); - if (!indexRootInfo.Exists) - throw new DirectoryNotFoundException($"The expected index root, {indexRoot}, is not here."); - - var indexFileName = jObject.GetValue("indexFileName"); - var entryRootInfo = presentationInfo - .FindDirectory("presentation") - .FindDirectory("entry") - .ToReferenceTypeValueOrThrow(); - - return (entryRootInfo, indexRootInfo, indexFileName); - } - - /// - /// Gets the arguments for Activity method. - /// - /// The . - /// The presentation information. - public static ( - string entryPath, - string collapsedHost - ) GetExpandUrisArgs(this JObject? jObject, DirectoryInfo? presentationInfo) - { - var collapsedHost = jObject.GetValue("collapsedHost"); - var entryPath = jObject.GetValue("entryPath"); - entryPath = presentationInfo.ToCombinedPath(entryPath); - - return (entryPath, collapsedHost); - } - - /// - /// Gets the arguments for Activity method. - /// - /// The . - /// The presentation information. - public static ( - string input, - string pattern, - string replacement, - bool useRegex, - string outputPath) - GetFindChangeArgs(this JObject? jObject, DirectoryInfo? presentationInfo) - { - var inputPath = jObject.GetValue("inputPath"); - inputPath = presentationInfo.ToCombinedPath(inputPath); - if (!File.Exists(inputPath)) - throw new FileNotFoundException($"The expected input file, `{inputPath}`, is not here."); - - var input = File.ReadAllText(inputPath); - - var pattern = jObject.GetValue("pattern"); - var replacement = jObject.GetValue("replacement"); - var useRegex = jObject.GetValue("useRegex"); - - var outputPath = jObject.GetValue("outputPath"); - outputPath = presentationInfo.ToCombinedPath(outputPath); - - return (input, pattern, replacement, useRegex, outputPath); - } - - /// - /// Gets the arguments for Activity method. - /// - /// The . - /// The presentation information. - public static ( - DirectoryInfo entryDraftsRootInfo, - string title - ) GetGenerateEntryArgs(this JObject? jObject, DirectoryInfo? presentationInfo) - { - var entryDraftsRootInfo = presentationInfo - .FindDirectory(MarkdownPresentationDirectories.DirectoryNamePresentationDrafts) - .ToReferenceTypeValueOrThrow(); - var title = jObject.GetValue("title"); - - return (entryDraftsRootInfo, title); - } - - /// - /// Gets the arguments for Activity method. - /// - /// The . - /// The presentation information. - public static ( - DirectoryInfo entryDraftsRootInfo, - DirectoryInfo entryRootInfo, - string entryFileName - ) GetPublishEntryArgs(this JObject? jObject, DirectoryInfo? presentationInfo) - { - var entryDraftsRootInfo = presentationInfo - .FindDirectory(MarkdownPresentationDirectories.DirectoryNamePresentationDrafts) - .ToReferenceTypeValueOrThrow(); - var entryRootInfo = presentationInfo - .FindDirectory(MarkdownPresentationDirectories.DirectoryNamePresentation) - .FindDirectory("entry") - .FindDirectory(DateTime.Now.Year.ToString()) - .ToReferenceTypeValueOrThrow(); - var entryFileName = jObject.GetValue("entryFileName"); - - return (entryDraftsRootInfo, entryRootInfo, entryFileName); - } -} diff --git a/Songhay.Publications/Extensions/JsonNodeExtensions.cs b/Songhay.Publications/Extensions/JsonNodeExtensions.cs new file mode 100644 index 0000000..4bfb9f5 --- /dev/null +++ b/Songhay.Publications/Extensions/JsonNodeExtensions.cs @@ -0,0 +1,39 @@ +using System.Text.Json; +using System.Text.Json.Nodes; + +namespace Songhay.Publications.Extensions; + +/// +/// Extensions of +/// +public static class JsonNodeExtensions +{ + /// + /// Returns false when the specified property name does not exist. + /// + /// the + /// the property name + /// + public static bool HasProperty(this JsonNode? node, string? propertyName) + { + if (node == null) return false; + if (string.IsNullOrWhiteSpace(propertyName)) return false; + + return node[propertyName] != null; + } + + /// + /// Converts the specified + /// to a . + /// + /// any + /// + public static JsonNode? ToJsonNode(this object? data) + { + if (data == null) return JsonNode.Parse("{}"); + + var json = JsonSerializer.Serialize(data); + + return JsonNode.Parse(json); + } +} diff --git a/Songhay.Publications/Extensions/MarkdownEntryExtensions.cs b/Songhay.Publications/Extensions/MarkdownEntryExtensions.cs index 2b0ba00..ef79bbe 100644 --- a/Songhay.Publications/Extensions/MarkdownEntryExtensions.cs +++ b/Songhay.Publications/Extensions/MarkdownEntryExtensions.cs @@ -1,6 +1,6 @@ +using System.Text.Json; +using System.Text.Json.Nodes; using System.Text.RegularExpressions; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; namespace Songhay.Publications.Extensions; @@ -21,7 +21,7 @@ static MarkdownEntryExtensions() => TraceSource = TraceSources /// /// The entry. public static MarkdownEntry DoNullCheck(this MarkdownEntry? entry) => - entry.DoNullCheckForFrontMatter().DoNullCheckForContent(); + entry.ToReferenceTypeValueOrThrow().DoNullCheckForContent(); /// /// Effectively validates . @@ -36,19 +36,6 @@ public static MarkdownEntry DoNullCheckForContent(this MarkdownEntry? entry) : entry; } - /// - /// Effectively validates . - /// - /// The entry. - public static MarkdownEntry DoNullCheckForFrontMatter(this MarkdownEntry? entry) - { - ArgumentNullException.ThrowIfNull(entry); - - return entry.FrontMatter == null - ? throw new NullReferenceException($"The expected {nameof(MarkdownEntry.FrontMatter)} is not here.") - : entry; - } - /// /// Converts the /// to an extract of the specified length @@ -80,7 +67,7 @@ public static string ToFinalEdit(this MarkdownEntry? entry) var finalEdit = string.Concat( "---json", MarkdownEntry.NewLine, - entry?.FrontMatter?.ToString().Trim(), + entry?.FrontMatter.ToString().Trim(), MarkdownEntry.NewLine, "---", MarkdownEntry.NewLine, @@ -121,12 +108,17 @@ public static MarkdownEntry ToMarkdownEntry(this FileInfo entry) .Skip(1) .Aggregate((a, i) => $"{a}{MarkdownEntry.NewLine}{i}"); - JObject frontMatter = JObject.FromObject(new { error = "front matter was not found", file = entry.FullName }); + var frontMatter = + new {error = "front matter was not found", file = entry.FullName} + .ToJsonNode() + .ToReferenceTypeValueOrThrow() + .AsObject(); + try { - frontMatter = JObject.Parse(json); + frontMatter = JsonNode.Parse(json).ToReferenceTypeValueOrThrow().AsObject(); } - catch (JsonReaderException ex) + catch (JsonException ex) { TraceSource?.TraceError(ex); } @@ -166,14 +158,11 @@ public static MarkdownEntry Touch(this MarkdownEntry? entry, DateTime date) { return entry.WithEdit(i => { - i.DoNullCheckForFrontMatter(); + i.ToReferenceTypeValueOrThrow(); const string propertyName = "modificationDate"; - if (!i.FrontMatter.HasProperty(propertyName)) - throw new FormatException($"The expected date property, `{propertyName}`, is not here."); - - i.FrontMatter![propertyName] = ProgramTypeUtility.ConvertDateTimeToUtc(date); + i.FrontMatter[propertyName] = ProgramTypeUtility.ConvertDateTimeToUtc(date); }); } @@ -192,12 +181,12 @@ string UpdateExtractAndReturnTag(string tag, string e) const string extractPropertyName = "extract"; var jO = tag.TrimStart().StartsWith("{") ? - JObject.Parse(tag) : - JObject.FromObject(new { legacy = tag }); + JsonNode.Parse(tag) : + new { legacy = tag }.ToJsonNode(); if (!jO.HasProperty(extractPropertyName)) { - jO.Add(extractPropertyName, null); + jO?.AsObject().Add(extractPropertyName, null); } jO[extractPropertyName] = e; @@ -205,13 +194,13 @@ string UpdateExtractAndReturnTag(string tag, string e) } const string tagPropertyName = "tag"; - var tagString = i.FrontMatter - .GetValue(tagPropertyName, throwException: false); + var tagString = i.FrontMatter[tagPropertyName].ToReferenceTypeValueOrThrow() + .GetValue(); var extract = i.ToExtract(length); - i.DoNullCheckForFrontMatter().FrontMatter![tagPropertyName] = string.IsNullOrWhiteSpace(tagString) ? - JObject.FromObject(new { extract }).ToString() + i.ToReferenceTypeValueOrThrow().FrontMatter[tagPropertyName] = string.IsNullOrWhiteSpace(tagString) ? + new { extract }.ToJsonNode()?.ToString() : UpdateExtractAndReturnTag(tagString, extract) ; @@ -234,18 +223,18 @@ string UpdateExtractAndReturnTag(string tag, string e) /// The header level. public static MarkdownEntry WithContentHeader(this MarkdownEntry? entry, int headerLevel) { - entry.DoNullCheckForFrontMatter(); + entry.ToReferenceTypeValueOrThrow(); const string propertyName = "title"; - if (!entry!.FrontMatter.HasProperty(propertyName)) + if (!entry.FrontMatter.HasProperty(propertyName)) throw new FormatException($"The expected date property, `{propertyName}`, is not here."); headerLevel = headerLevel == 0 ? 1 : Math.Abs(headerLevel); var markdownHeader = new string(Enumerable.Repeat('#', headerLevel > 6 ? 6 : headerLevel).ToArray()); return entry.WithEdit(i => - i.Content = $"{markdownHeader} {i.FrontMatter![propertyName]}{MarkdownEntry.NewLine}{MarkdownEntry.NewLine}"); + i.Content = $"{markdownHeader} {i.FrontMatter[propertyName]}{MarkdownEntry.NewLine}{MarkdownEntry.NewLine}"); } /// @@ -274,9 +263,9 @@ public static MarkdownEntry WithNew11TyFrontMatter(this MarkdownEntry? entry, st .ToReferenceTypeValueOrThrow() .WithNewFrontMatter(title, inceptDate, documentId: 0, fileName: "index.html", path: path, segmentId: 0, tag: tag) - .WithEdit(i => i.FrontMatter!["clientId"] = $"{inceptDate:yyyy-MM-dd}-{i.FrontMatter["clientId"]}") - .WithEdit(i => i.FrontMatter!["documentShortName"] = i.FrontMatter["clientId"]) - .WithEdit(i => i.FrontMatter!["path"] = $"{i.FrontMatter["path"]}{i.FrontMatter["clientId"]}"); + .WithEdit(i => i.FrontMatter["clientId"] = $"{inceptDate:yyyy-MM-dd}-{i.FrontMatter["clientId"]}") + .WithEdit(i => i.FrontMatter["documentShortName"] = i.FrontMatter["clientId"]) + .WithEdit(i => i.FrontMatter["path"] = $"{i.FrontMatter["path"]}{i.FrontMatter["clientId"]}"); /// /// Returns the with conventional frontmatter. @@ -314,7 +303,7 @@ public static MarkdownEntry WithNewFrontMatter(this MarkdownEntry? entry, string tag }; - entry.FrontMatter = JObject.FromObject(fm); + entry.FrontMatter = fm.ToJsonNode().ToReferenceTypeValueOrThrow().AsObject(); return entry; } diff --git a/Songhay.Publications/MarkdownEntryUtility.cs b/Songhay.Publications/MarkdownEntryUtility.cs index 5dee91c..5b24495 100644 --- a/Songhay.Publications/MarkdownEntryUtility.cs +++ b/Songhay.Publications/MarkdownEntryUtility.cs @@ -1,6 +1,4 @@ -using Newtonsoft.Json.Linq; - -namespace Songhay.Publications; +namespace Songhay.Publications; /// /// Shares routines for . @@ -15,7 +13,7 @@ public static class MarkdownEntryUtility /// see . public static MarkdownEntry GenerateEntryFor11Ty(string entryRoot, string title) { - var tag = JObject.FromObject(new { extract = string.Empty }).ToString(); + var tag = new { extract = string.Empty }.ToJsonNode()?.ToString(); return GenerateEntryFor11Ty(entryRoot, title, DateTime.Now, "./entry/", tag); } @@ -39,7 +37,7 @@ public static MarkdownEntry GenerateEntryFor11Ty(string? entryRoot, string? titl .WithNew11TyFrontMatter(title, inceptDate, path, tag) .WithContentHeader(); - File.WriteAllText($"{entryRoot}/{entry.FrontMatter?["clientId"]}.md", entry.ToFinalEdit()); + File.WriteAllText($"{entryRoot}/{entry.FrontMatter["clientId"]}.md", entry.ToFinalEdit()); return entry; } @@ -99,18 +97,19 @@ public static string PublishEntryFor11Ty(string entryRoot, string presentationRo throw new FileNotFoundException($"The expected file, `{fileName}`, under `{rootInfo.FullName}` is not here."); var draftEntry = draftInfo.ToMarkdownEntry(); - var inceptDate = draftEntry.FrontMatter.GetValue("date"); - var clientId = draftEntry.FrontMatter.GetValue("clientId"); - var path = draftEntry.FrontMatter.GetValue("path").Replace(clientId, string.Empty); + var inceptDate = draftEntry.FrontMatter["date"].ToReferenceTypeValueOrThrow().GetValue(); + var clientId = draftEntry.FrontMatter["clientId"].ToReferenceTypeValueOrThrow().GetValue(); + var path = draftEntry.FrontMatter["path"]?.GetValue().Replace(clientId, string.Empty); if ((publicationDate - inceptDate).Days >= 1) { - var title = draftEntry.FrontMatter.GetValue("title"); - var tag = draftEntry.FrontMatter.GetValue("tag", throwException: false); + var title = draftEntry.FrontMatter["title"]?.GetValue(); + var tag = draftEntry.FrontMatter["tag"]?.GetValue(); draftEntry.WithNew11TyFrontMatter(title, publicationDate, path, tag); } - var combinedPath = ProgramFileUtility.GetCombinedPath(presentationRoot, $"{draftEntry.FrontMatter.GetValue("clientId")}.md"); + var combinedPath = ProgramFileUtility.GetCombinedPath(presentationRoot, + $"{draftEntry.FrontMatter["clientId"].ToReferenceTypeValueOrThrow().GetValue()}.md"); File.WriteAllText(combinedPath, draftEntry.ToFinalEdit()); draftInfo.Delete(); diff --git a/Songhay.Publications/Models/MarkdownEntry.cs b/Songhay.Publications/Models/MarkdownEntry.cs index 018b210..fcdc4fc 100644 --- a/Songhay.Publications/Models/MarkdownEntry.cs +++ b/Songhay.Publications/Models/MarkdownEntry.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json.Linq; +using System.Text.Json.Nodes; namespace Songhay.Publications.Models; @@ -20,7 +20,7 @@ public class MarkdownEntry /// /// JSON front matter. /// - public JObject? FrontMatter { get; set; } + public JsonObject FrontMatter { get; set; } = new(); /// /// Text content. diff --git a/Songhay.Publications/Songhay.Publications.csproj b/Songhay.Publications/Songhay.Publications.csproj index 15b381b..64985f7 100644 --- a/Songhay.Publications/Songhay.Publications.csproj +++ b/Songhay.Publications/Songhay.Publications.csproj @@ -42,7 +42,6 @@ - diff --git a/Songhay.Publications/Songhay.Publications.xml b/Songhay.Publications/Songhay.Publications.xml index 3cf819f..09f7b57 100644 --- a/Songhay.Publications/Songhay.Publications.xml +++ b/Songhay.Publications/Songhay.Publications.xml @@ -434,13 +434,6 @@ The data. when true then display identifiers only - - - Converts the to . - - The data. - when true use “camel” casing. - Converts the into a menu display item model. @@ -512,13 +505,6 @@ The data. when true then display identifiers only - - - Converts the to . - - The data. - when true use “camel” casing. - Converts the into a menu display item model. @@ -638,13 +624,6 @@ The data. when true then display identifiers only - - - Converts the to . - - The data. - when true use “camel” casing. - Converts the into a menu display item model. @@ -670,14 +649,6 @@ The data. - - - Converts the to - in the shape of a Publications Index Entry. - - The data. - when true use “camel” casing. - Converts the data to . @@ -698,68 +669,6 @@ The data. The edit action. - - - Extensions of . - - - Extensions of - - - - - Gets the arguments for Activity method. - - The . - The presentation information. - - - - Gets the arguments for Activity method. - - The . - The presentation information. - - - - Gets the arguments for Activity method. - - The . - The presentation information. - - - - Gets the arguments for Activity method. - - The . - The presentation information. - - - - Gets the arguments for Activity method. - - The . - The presentation information. - - - - Gets the arguments for Activity method. - - The . - The presentation information. - - - - Gets the publication command. - - The . - - - - Converts the to presentation . - - The . - Extensions of . @@ -816,6 +725,27 @@ The . + + + Extensions of + + + + + Returns false when the specified property name does not exist. + + the + the property name + + + + + Converts the specified + to a . + + any + + Extensions of . @@ -833,12 +763,6 @@ The entry. - - - Effectively validates . - - The entry. - Converts the