namespace DocFx.Plugin.LastModified.Processors;
using Docfx.Common;
using Docfx.Plugins;
using HtmlAgilityPack;
///
/// An abstract processor for adding last modified date to articles, contains common methods.
///
public abstract class AbstractProcessor : IProcessor
{
///
/// Determines whether this processor supports the given type.
///
/// The type of manifest item.
/// True if this processor supports the given type, false otherwise.
public abstract bool Supports(string type);
///
/// Processes the given manifest item.
///
/// The that contains the manifest item.
/// The to process.
/// The output folder.
public abstract void Process(Manifest manifest, ManifestItem manifestItem, string outputFolder);
///
/// Attempts to process the given manifest item.
///
/// The that contains the manifest item.
/// The to process.
/// The output folder.
/// True if the manifest item was processed, false otherwise.
public bool TryProcess(Manifest manifest, ManifestItem manifestItem, string outputFolder)
{
if (!Supports(manifestItem.Type))
{
Logger.LogVerbose($"Skipping {manifestItem.Type}...");
return false;
}
Logger.LogDiagnostic($"Processing {manifestItem.Type}...");
Process(manifest, manifestItem, outputFolder);
return true;
}
///
/// Builds the last modified info for the given file path.
///
/// The file path.
/// The for the given file path.
protected abstract LastModifiedInfo GetLastModifiedInfo(string filePath);
///
/// Modifies the given document with the given last modified info.
///
/// The file path to the document.
/// The to use.
protected virtual void ModifyDocument(string filePath, LastModifiedInfo lastModifiedInfo)
{
var htmlDocument = new HtmlDocument();
htmlDocument.Load(filePath);
var articleNode = htmlDocument.DocumentNode.SelectSingleNode("//article");
if (articleNode == null)
{
Logger.LogWarning($"No article node found in {filePath}.");
return;
}
var separatorNode = htmlDocument.CreateElement("hr");
articleNode.AppendChild(separatorNode);
var lastModifiedNode = htmlDocument.CreateElement("div");
lastModifiedNode.SetAttributeValue("class", "last-modified");
articleNode.AppendChild(lastModifiedNode);
var paragraphNode = htmlDocument.CreateElement("p");
paragraphNode.InnerHtml = $"This page was last modified at {lastModifiedInfo.LastModified} (UTC).";
lastModifiedNode.AppendChild(paragraphNode);
if (string.IsNullOrEmpty(lastModifiedInfo.CommitHeader))
{
htmlDocument.Save(filePath);
return;
}
var collapsibleNode = htmlDocument.CreateElement("details");
lastModifiedNode.AppendChild(collapsibleNode);
var reasonHeaderNode = htmlDocument.CreateElement("summary");
reasonHeaderNode.SetAttributeValue("style", "display: list-item;");
reasonHeaderNode.InnerHtml = "Commit Message";
collapsibleNode.AppendChild(reasonHeaderNode);
var reasonContainerNode = htmlDocument.CreateElement("div");
collapsibleNode.AppendChild(reasonContainerNode);
var preCodeBlockNode = htmlDocument.CreateElement("pre");
var codeBlockNode = htmlDocument.CreateElement("code");
codeBlockNode.InnerHtml = lastModifiedInfo.CommitHeader;
preCodeBlockNode.AppendChild(codeBlockNode);
reasonContainerNode.AppendChild(preCodeBlockNode);
if (!string.IsNullOrEmpty(lastModifiedInfo.CommitBody))
{
preCodeBlockNode = htmlDocument.CreateElement("pre");
codeBlockNode = htmlDocument.CreateElement("code");
codeBlockNode.InnerHtml = lastModifiedInfo.CommitBody;
preCodeBlockNode.AppendChild(codeBlockNode);
reasonContainerNode.AppendChild(preCodeBlockNode);
}
htmlDocument.Save(filePath);
}
}