diff --git a/source/Models/CommandLineOptions/GenerateOptions.cs b/source/Models/CommandLineOptions/GenerateOptions.cs
index eb50030a3990e1de1159383fd59a872de56c63cb..8435eafc4d260e4d34e10954bc6cfd5b4d79e5b4 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 74e249af077fe7832cd8203f30c7730dd41bfa14..72a911465389312a9d9b9619c081cc0739444edf 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 8ea9df48bf66a24c26d6b0a09ec24c87779dcd81..9c5629b95d5c7b235ddfbf8b601af9c119b5ce63 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 a06b57016e48a4ab3230a5935f480a0395d4ac57..8da34d5244c95dbd2760f2814dd3ef116f020282 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 98ad8105e845e62e5b17f366bb570a7084385f21..1f739e5be43d6dd9ed2fa61ca4bc51b574d372cd 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 be775bd75448eebffb9725a321e31c26589ee0a4..99a833e8df241cf72514e457bbed3642473a24c8 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 70f360ee2dea312c4871ea552ef331dc52320ccf..8f83c0c1bfda44c5cf72eac8934563e4718f99ba 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 95ce7f09661048b4cefb783057b0be9f0c00db31..560163139aa85d7d0463c28e4f647af5ac7fb47c 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 59e04c31fd2292e43db16e54ae69500bbd40e806..2a118e39bab66b647f0e40472d568ae5afa54c9a 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 cc77b7b74d6ed5d11a63f1c05594bb58e6a450a7..9e51d147213ac175053570ad8c87463449554fdf 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)]