Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/RefDocGen/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ private static async Task Run(IProgramConfiguration config)

Dictionary<DocumentationTemplate, ITemplateProcessor> templateProcessors = new()
{
[DocumentationTemplate.Default] = new DefaultTemplateProcessor(htmlRenderer, availableLanguages, config.StaticPagesDir, config.DocVersion)
[DocumentationTemplate.Default] = new DefaultTemplateProcessor(htmlRenderer, availableLanguages, config.StaticPagesDir, config.DocVersion, config.ForceCreate)
// #ADD_TEMPLATE: use the enum value together with the RazorTemplateProcessor with 8 type parameters, representing the templates
// additionally, pass the 'DocCommentHtmlConfiguration' or a custom configuration (if provided)
//
Expand All @@ -111,7 +111,8 @@ private static async Task Run(IProgramConfiguration config)
// htmlRenderer,
// availableLanguages,
// config.StaticPagesDir,
// config.DocVersion)
// config.DocVersion,
// config.ForceCreate)
//
// #ADD_TEMPLATE_PROCESSOR: use the enum value together with the custom template processor
//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,17 @@ internal class DefaultTemplateProcessor : RazorTemplateProcessor<
/// <param name="htmlRenderer">Renderer of the Razor components.</param>
/// <param name="staticPagesDirectory">Path to the directory containing the static pages created by user. <c>null</c> indicates that the directory is not specified.</param>
/// <param name="docVersion">Version of the documentation (e.g. 'v1.0'). Pass <c>null</c> if no specific version should be generated.</param>
/// <param name="forceCreate">If <see langword="true"/> and the <paramref name="docVersion"/> already exists, the existing version will be overwritten.</param>
/// <param name="availableLanguages">Configuration of languages available in the documentation.</param>
internal DefaultTemplateProcessor(HtmlRenderer htmlRenderer, ILanguageConfiguration[] availableLanguages,
string? staticPagesDirectory = null, string? docVersion = null)
string? staticPagesDirectory = null, string? docVersion = null, bool forceCreate = false)
: base(
htmlRenderer,
new DocCommentTransformer(new DocCommentHtmlConfiguration()),
availableLanguages,
staticPagesDirectory,
docVersion)
docVersion,
forceCreate)
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ internal class DocVersionManager
/// </summary>
/// <param name="baseOutputDirectory">Base output directory, containing the JSON versions file.</param>
/// <param name="currentVersion">Current version of the documentation being generated.</param>
public DocVersionManager(string baseOutputDirectory, string currentVersion)
/// <param name="forceCreate">
/// If <see langword="true"/> and a version with the same name already exists, the existing version will be overwritten.
/// If <see langword="false"/> and a duplicate version is found, a <see cref="DuplicateDocVersionNameException"/> is thrown.
/// </param>
public DocVersionManager(string baseOutputDirectory, string currentVersion, bool forceCreate = false)
{
this.baseOutputDirectory = baseOutputDirectory;
this.currentVersion = currentVersion;
Expand All @@ -60,7 +64,20 @@ public DocVersionManager(string baseOutputDirectory, string currentVersion)

if (versions.Any(v => v.Version == currentVersion))
{
throw new DuplicateDocVersionNameException(currentVersion); // there's already a version with the same name -> throw an exception
if (forceCreate)
{
_ = versions.RemoveAll(v => v.Version == currentVersion); // remove the existing version from the list

string existingVersionDir = Path.Join(baseOutputDirectory, currentVersion);
if (Directory.Exists(existingVersionDir))
{
Directory.Delete(existingVersionDir, true); // delete the existing version directory
}
}
else
{
throw new DuplicateDocVersionNameException(currentVersion); // there's already a version with the same name -> throw an exception
}
}
}
else
Expand Down
20 changes: 15 additions & 5 deletions src/RefDocGen/TemplateProcessors/Shared/RazorTemplateProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@ internal class RazorTemplateProcessor<
/// </summary>
private readonly string? docVersion;

/// <summary>
/// Indicates whether an existing documentation version with the same name should be overwritten.
/// </summary>
private readonly bool forceCreate;

/// <summary>
/// Set of paths of all generated pages in the current doc version, relative to <see cref="outputDirectory"/>.
/// </summary>
Expand Down Expand Up @@ -157,18 +162,21 @@ internal class RazorTemplateProcessor<
/// <param name="docCommentTransformer">Transformer of the XML doc comments into HTML.</param>
/// <param name="staticPagesDirectory">Path to the directory containing the static pages created by user. <c>null</c> indicates that the directory is not specified.</param>
/// <param name="docVersion">Version of the documentation (e.g. 'v1.0'). Pass <c>null</c> if no specific version should be generated.</param>
/// <param name="forceCreate">If <see langword="true"/> and the <paramref name="docVersion"/> already exists, the existing version will be overwritten.</param>
/// <param name="availableLanguages"><inheritdoc cref="availableLanguages"/></param>
internal RazorTemplateProcessor(
HtmlRenderer htmlRenderer,
IDocCommentTransformer docCommentTransformer,
IEnumerable<ILanguageConfiguration> availableLanguages,
string? staticPagesDirectory = null,
string? docVersion = null)
string? docVersion = null,
bool forceCreate = false)
{
this.htmlRenderer = htmlRenderer;
this.docCommentTransformer = docCommentTransformer;
this.staticPagesDirectory = staticPagesDirectory;
this.docVersion = docVersion;
this.forceCreate = forceCreate;
this.availableLanguages = availableLanguages;

defaultIndexPage = Path.Join(AppDomain.CurrentDomain.BaseDirectory, "TemplateProcessors", "Shared", "StaticData", "defaultIndexPage.html");
Expand All @@ -191,10 +199,10 @@ public void ProcessTemplates(ITypeRegistry typeRegistry, string outputDirectory,
{
string rootOutputDirectory = outputDirectory;

versionManager = new(rootOutputDirectory, docVersion, forceCreate);

this.outputDirectory = Path.Join(outputDirectory, docVersion); // set output directory
_ = Directory.CreateDirectory(this.outputDirectory);

versionManager = new(rootOutputDirectory, docVersion);
}
else
{
Expand Down Expand Up @@ -569,14 +577,16 @@ private void CreateVersionedDocIndexPage()
/// <param name="docCommentHtmlConfiguration">The configuration describing mapping of the inner XML tags into HTML.</param>
/// <param name="staticPagesDirectory">Path to the directory containing the static pages created by user. <c>null</c> indicates that the directory is not specified.</param>
/// <param name="docVersion">Version of the documentation (e.g. 'v1.0'). Pass <c>null</c> if no specific version should be generated.</param>
/// <param name="forceCreate">If <see langword="true"/> and the <paramref name="docVersion"/> already exists, the existing version will be overwritten.</param>
/// <param name="availableLanguages"><inheritdoc cref="availableLanguages"/></param>
/// <returns>An instance of <see cref="RazorTemplateProcessor{TObjectTypeTemplate, TDelegateTemplate, TEnumTemplate, TNamespaceTemplate, TAssemblyTemplate, TApiTemplate, TStaticPageTemplate, TSearchPageTemplate}"/> class.</returns>
internal static ITemplateProcessor With(
IDocCommentHtmlConfiguration docCommentHtmlConfiguration,
HtmlRenderer htmlRenderer,
IEnumerable<ILanguageConfiguration> availableLanguages,
string? staticPagesDirectory = null,
string? docVersion = null)
string? docVersion = null,
bool forceCreate = false)
{
return new RazorTemplateProcessor<
TObjectTypePageTemplate,
Expand All @@ -587,6 +597,6 @@ internal static ITemplateProcessor With(
TApiHomePageTemplate,
TStaticPageTemplate,
TSearchPageTemplate
>(htmlRenderer, new DocCommentTransformer(docCommentHtmlConfiguration), availableLanguages, staticPagesDirectory, docVersion);
>(htmlRenderer, new DocCommentTransformer(docCommentHtmlConfiguration), availableLanguages, staticPagesDirectory, docVersion, forceCreate);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using RefDocGen.TemplateProcessors.Shared.DocVersioning;
using RefDocGen.Tools.Exceptions;
using Shouldly;
using System.Text.Json;

namespace RefDocGen.UnitTests.TemplateProcessors.Shared;

/// <summary>
/// Class containing tests for <see cref="DocVersionManager"/> class.
/// </summary>
public class DocVersionManagerTests : IDisposable
{
/// <summary>
/// Temporary directory used as the base output directory for tests.
/// </summary>
private readonly string tempDirectory;

public DocVersionManagerTests()
{
tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
Directory.CreateDirectory(tempDirectory);
}

public void Dispose()
{
Directory.Delete(tempDirectory, true);
GC.SuppressFinalize(this);
}

[Fact]
public void Constructor_ThrowsDuplicateDocVersionNameException_WhenVersionAlreadyExistsAndForceCreateIsFalse()
{
var firstManager = new DocVersionManager(tempDirectory, "v1.0");
firstManager.SaveCurrentVersionData([]);

Should.Throw<DuplicateDocVersionNameException>(() => new DocVersionManager(tempDirectory, "v1.0", forceCreate: false));
}

[Fact]
public void Constructor_DoesNotThrow_WhenVersionAlreadyExistsAndForceCreateIsTrue()
{
var firstManager = new DocVersionManager(tempDirectory, "v1.0");
firstManager.SaveCurrentVersionData([]);

Should.NotThrow(() => new DocVersionManager(tempDirectory, "v1.0", forceCreate: true));
}

[Fact]
public void Constructor_DeletesExistingVersionDirectory_WhenForceCreateIsTrue()
{
string versionDir = Path.Join(tempDirectory, "v1.0");
Directory.CreateDirectory(versionDir);
File.WriteAllText(Path.Join(versionDir, "page.html"), "<html/>");

var firstManager = new DocVersionManager(tempDirectory, "v1.0");
firstManager.SaveCurrentVersionData(["page.html"]);

_ = new DocVersionManager(tempDirectory, "v1.0", forceCreate: true);

Directory.Exists(versionDir).ShouldBeFalse();
}

[Fact]
public void Constructor_RemovesExistingVersionFromVersionsList_WhenForceCreateIsTrue()
{
var firstManager = new DocVersionManager(tempDirectory, "v1.0");
firstManager.SaveCurrentVersionData([]);

var secondManager = new DocVersionManager(tempDirectory, "v1.0", forceCreate: true);
secondManager.SaveCurrentVersionData([]);

string json = File.ReadAllText(Path.Join(tempDirectory, "versions.json"));
var versions = JsonSerializer.Deserialize<List<JsonElement>>(json);

versions.ShouldNotBeNull();
versions.Count.ShouldBe(1); // only one entry, not two
versions[0].GetProperty("Version").GetString().ShouldBe("v1.0");
}
}