From 4b998c2a3061a90f7b145ff207e49834cc38f31a Mon Sep 17 00:00:00 2001 From: Bruno Massa Date: Tue, 18 Jul 2023 09:05:14 -0300 Subject: [PATCH] feat: page Draft status --- .../CommandLineOptions/GenerateOptions.cs | 3 + .../CommandLineOptions/IGenerateOptions.cs | 9 ++- source/Models/FrontMatter.cs | 3 + source/Models/IFrontMatter.cs | 6 ++ source/Models/IPage.cs | 5 +- source/Models/ISite.cs | 9 +++ source/Models/Page.cs | 3 + source/Models/Site.cs | 24 ++++--- source/Program.cs | 13 ++-- test/Models/PageTests.cs | 63 +++++++++++++++++-- 10 files changed, 115 insertions(+), 23 deletions(-) diff --git a/source/Models/CommandLineOptions/GenerateOptions.cs b/source/Models/CommandLineOptions/GenerateOptions.cs index eb50030..8435eaf 100644 --- a/source/Models/CommandLineOptions/GenerateOptions.cs +++ b/source/Models/CommandLineOptions/GenerateOptions.cs @@ -8,6 +8,9 @@ internal class GenerateOptions : IGenerateOptions /// public string Source { get; init; } = "."; + /// + public bool Draft { get; init; } + /// public bool Future { get; init; } diff --git a/source/Models/CommandLineOptions/IGenerateOptions.cs b/source/Models/CommandLineOptions/IGenerateOptions.cs index 74e249a..72a9114 100644 --- a/source/Models/CommandLineOptions/IGenerateOptions.cs +++ b/source/Models/CommandLineOptions/IGenerateOptions.cs @@ -11,12 +11,17 @@ public interface IGenerateOptions string Source { get; } /// - /// Consider future content + /// Include draft content + /// + bool Draft { get; } + + /// + /// Include future content /// bool Future { get; } /// - /// Consider expired content + /// Include expired content /// bool Expired { get; } } \ No newline at end of file diff --git a/source/Models/FrontMatter.cs b/source/Models/FrontMatter.cs index 8ea9df4..9c5629b 100644 --- a/source/Models/FrontMatter.cs +++ b/source/Models/FrontMatter.cs @@ -22,6 +22,9 @@ internal class FrontMatter : IFrontMatter /// public string? URL { get; init; } + /// + public bool? Draft { get; init; } + /// public List? Aliases { get; init; } diff --git a/source/Models/IFrontMatter.cs b/source/Models/IFrontMatter.cs index a06b570..8da34d5 100644 --- a/source/Models/IFrontMatter.cs +++ b/source/Models/IFrontMatter.cs @@ -48,6 +48,12 @@ public interface IFrontMatter : IParams /// string? URL { get; } + /// + /// True for draft content. It will not be rendered unless + /// a option is set to true. + /// + bool? Draft { get; } + /// /// Date of the post. Will be used as the if it's not set. /// Unless the option is set to true, diff --git a/source/Models/IPage.cs b/source/Models/IPage.cs index 98ad810..1f739e5 100644 --- a/source/Models/IPage.cs +++ b/source/Models/IPage.cs @@ -112,10 +112,7 @@ public interface IPage : IFrontMatter /// /// Get all URLs related to this content. /// - public List Urls - { - get; - } + public List Urls { get; } /// /// Gets the Permalink path for the file. diff --git a/source/Models/ISite.cs b/source/Models/ISite.cs index be775bd..99a833e 100644 --- a/source/Models/ISite.cs +++ b/source/Models/ISite.cs @@ -114,6 +114,15 @@ public interface ISite : IParams /// public void PostProcessPage(in IPage page, IPage? parent = null, bool overwrite = false); + /// + /// Check if the page have the conditions to be published: valid date and not draft, + /// unless a command line option to force it. + /// + /// Page or front matter + /// options + /// + public bool IsValidPage(in IFrontMatter frontMatter, IGenerateOptions? options); + /// /// Check if the page have a publishing date from the past. /// diff --git a/source/Models/Page.cs b/source/Models/Page.cs index 70f360e..8f83c0c 100644 --- a/source/Models/Page.cs +++ b/source/Models/Page.cs @@ -27,6 +27,9 @@ internal class Page : IPage /// public string? URL => frontMatter.URL; + /// + public bool? Draft => frontMatter.Draft; + /// public List? Aliases => frontMatter.Aliases; diff --git a/source/Models/Site.cs b/source/Models/Site.cs index 95ce7f0..5601631 100644 --- a/source/Models/Site.cs +++ b/source/Models/Site.cs @@ -45,17 +45,17 @@ internal class Site : ISite /// /// Site description /// - public string? Description => settings.Description; + public string? Description => settings.Description; /// /// Copyright information /// - public string? Copyright => settings.Copyright; + public string? Copyright => settings.Copyright; /// /// The base URL that will be used to build internal links. /// - public string BaseURL => settings.BaseURL; + public string BaseURL => settings.BaseURL; /// /// The appearance of a URL is either ugly or pretty. @@ -415,12 +415,18 @@ internal class Site : ISite } } - /// - /// Check if the page have a publishing date from the past. - /// - /// Page or front matter - /// options - /// + /// + public bool IsValidPage(in IFrontMatter frontMatter, IGenerateOptions? options) + { + if (frontMatter is null) + { + throw new ArgumentNullException(nameof(frontMatter)); + } + return IsValidDate(frontMatter, options) + && (frontMatter.Draft is null || frontMatter.Draft == false || (options?.Draft ?? false)); + } + + /// public bool IsValidDate(in IFrontMatter frontMatter, IGenerateOptions? options) { if (frontMatter is null) diff --git a/source/Program.cs b/source/Program.cs index 59e04c3..2a118e3 100644 --- a/source/Program.cs +++ b/source/Program.cs @@ -52,6 +52,7 @@ internal class Program // Shared options between the commands var sourceOption = new Option(new[] { "--source", "-s" }, () => ".", "Source directory path"); + var draftOption = new Option(new[] { "--draft", "-d" }, "Include draft content"); var futureOption = new Option(new[] { "--future", "-f" }, "Include content with dates in the future"); var expiredOption = new Option(new[] { "--expired", "-e" }, "Include content with ExpiredDate dates from the past"); var verboseOption = new Option(new[] { "--verbose", "-v" }, "Verbose output"); @@ -62,12 +63,13 @@ internal class Program Command buildCommandHandler = new("build", "Builds the site") { sourceOption, + draftOption, buildOutputOption, futureOption, expiredOption, verboseOption }; - buildCommandHandler.SetHandler((source, output, future, expired, verbose) => + buildCommandHandler.SetHandler((source, output, draft, future, expired, verbose) => { logger = CreateLogger(verbose); @@ -75,28 +77,31 @@ internal class Program source: source, output: output) { + Draft = draft, Future = future, Expired = expired }; _ = new BuildCommand(buildOptions, logger); }, - sourceOption, buildOutputOption, futureOption, expiredOption, verboseOption); + sourceOption, buildOutputOption, draftOption, futureOption, expiredOption, verboseOption); // ServerCommand setup Command serveCommandHandler = new("serve", "Starts the server") { sourceOption, + draftOption, futureOption, expiredOption, verboseOption }; - serveCommandHandler.SetHandler(async (source, future, expired, verbose) => + serveCommandHandler.SetHandler(async (source, draft, future, expired, verbose) => { logger = CreateLogger(verbose); ServeOptions serverOptions = new() { Source = source, + Draft = draft, Future = future, Expired = expired }; @@ -105,7 +110,7 @@ internal class Program await serveCommand.RunServer(); await Task.Delay(-1); // Wait forever. }, - sourceOption, futureOption, expiredOption, verboseOption); + sourceOption, draftOption, futureOption, expiredOption, verboseOption); RootCommand rootCommand = new("SuCoS commands") { diff --git a/test/Models/PageTests.cs b/test/Models/PageTests.cs index cc77b7b..9e51d14 100644 --- a/test/Models/PageTests.cs +++ b/test/Models/PageTests.cs @@ -112,10 +112,10 @@ word03 word04 word05 6 7 eight [Theory] [InlineData(null, null, true)] - [InlineData(null, "2024-06-28", false)] - [InlineData("2022-06-28", null, true)] - [InlineData("2024-06-28", "2022-06-28", false)] - [InlineData("2022-06-28", "2024-06-28", true)] + [InlineData(null, "2024-01-01", false)] + [InlineData("2022-01-01", null, true)] + [InlineData("2024-01-01", "2022-01-01", false)] + [InlineData("2022-01-01", "2024-01-01", true)] public void IsDatePublishable_ShouldReturnCorrectValues(string? publishDate, string? date, bool expectedValue) { var page = new Page(new FrontMatter @@ -130,6 +130,61 @@ word03 word04 word05 6 7 eight Assert.Equal(expectedValue, site.IsDatePublishable(page)); } + [Theory] + // Draft as null + [InlineData(null, null, null, false, true)] + [InlineData(null, "2024-01-01", null, false, false)] + [InlineData("2022-01-01", null, null, false, true)] + [InlineData("2024-01-01", "2022-01-01", null, false, false)] + [InlineData("2022-01-01", "2024-01-01", null, false, true)] + // Draft as false + [InlineData(null, null, false, false, true)] + [InlineData(null, "2024-01-01", false, false, false)] + [InlineData("2022-01-01", null, false, false, true)] + [InlineData("2024-01-01", "2022-01-01", false, false, false)] + [InlineData("2022-01-01", "2024-01-01", false, false, true)] + // Draft as true + [InlineData(null, null, true, false, false)] + [InlineData(null, "2024-01-01", true, false, false)] + [InlineData("2022-01-01", null, true, false, false)] + [InlineData("2024-01-01", "2022-01-01", true, false, false)] + [InlineData("2022-01-01", "2024-01-01", true, false, false)] + // Draft as null, option -d + [InlineData(null, null, null, true, true)] + [InlineData(null, "2024-01-01", null, true, false)] + [InlineData("2022-01-01", null, null, true, true)] + [InlineData("2024-01-01", "2022-01-01", null, true, false)] + [InlineData("2022-01-01", "2024-01-01", null, true, true)] + // Draft as false, option -d + [InlineData(null, null, false, true, true)] + [InlineData(null, "2024-01-01", false, true, false)] + [InlineData("2022-01-01", null, false, true, true)] + [InlineData("2024-01-01", "2022-01-01", false, true, false)] + [InlineData("2022-01-01", "2024-01-01", false, true, true)] + // Draft as true, option -d + [InlineData(null, null, true, true, true)] + [InlineData(null, "2024-01-01", true, true, false)] + [InlineData("2022-01-01", null, true, true, true)] + [InlineData("2024-01-01", "2022-01-01", true, true, false)] + [InlineData("2022-01-01", "2024-01-01", true, true, true)] + public void IsValidPage_ShouldReturnCorrectValues(string? publishDate, string? date, bool? draft, bool draftOption, bool expectedValue) + { + var page = new Page(new FrontMatter + { + Title = titleCONST, + SourcePath = sourcePathCONST, + PublishDate = publishDate is null ? null : DateTime.Parse(publishDate, CultureInfo.InvariantCulture), + Date = date is null ? null : DateTime.Parse(date, CultureInfo.InvariantCulture), + Draft = draft + }, site); + + var options = new Mock(); + options.Setup(o => o.Draft).Returns(draftOption); + + // Assert + Assert.Equal(expectedValue, site.IsValidPage(page, options.Object)); + } + [Theory] [InlineData(false, false)] [InlineData(true, true)] -- GitLab