From 976361f4466739580632d2c478596f8502650169 Mon Sep 17 00:00:00 2001
From: Tim <47110241+timunie@users.noreply.github.com>
Date: Sun, 19 Oct 2025 20:13:22 +0200
Subject: [PATCH 1/8] Updates
- update HelpFileBuilder
- Fix some errors and warnings after update
- improve ReadMe
---
README.md | 8 +-
.../ApiDocumentation.shfbproj | 4 +-
.../AvaloniaAttributesPlugIn.csproj | 4 +-
.../DocusaurusExportPlugin.csproj | 4 +-
.../DocusaurusMarkdownPresentationStyle.cs | 2 +-
.../DocusaurusMarkdownTransformation.cs | 90 ++++++++++---------
.../Elements/MdxListElement.cs | 1 -
.../DocusaurusPresentationStyle.csproj | 4 +-
8 files changed, 62 insertions(+), 55 deletions(-)
diff --git a/README.md b/README.md
index 49285b3..42e9d20 100644
--- a/README.md
+++ b/README.md
@@ -21,12 +21,10 @@ It is important to mind the build order.
> ```
## Generate the API docs for newer Avalonia version
-Use the `set-version.ps1` script to update the version.
+Use the `update-submodule.ps1` script to update the version to the latest stable. if you need any other branch version, you need to link the branch name for the submodule by hand.
-```ps1
-# -version: specify the Avalonia version to document. If this parameter is not set, `AvaloniaVersion.txt` will be used instead.
-.\set-version.ps1 11.2.0
-```
+> [!NOTE]
+> The file `./ext/Avalonia/build/SharedVersion.props` stores the current version info.
> [!WARNING]
> Remember to commit all updates made to the submodule.
diff --git a/src/ApiDocumentation/ApiDocumentation.shfbproj b/src/ApiDocumentation/ApiDocumentation.shfbproj
index 0e75d8a..d5574e6 100644
--- a/src/ApiDocumentation/ApiDocumentation.shfbproj
+++ b/src/ApiDocumentation/ApiDocumentation.shfbproj
@@ -135,8 +135,8 @@
-
-
+
+
diff --git a/src/AvaloniaAttributesPlugin/AvaloniaAttributesPlugIn.csproj b/src/AvaloniaAttributesPlugin/AvaloniaAttributesPlugIn.csproj
index df0d3d2..927e6e7 100644
--- a/src/AvaloniaAttributesPlugin/AvaloniaAttributesPlugIn.csproj
+++ b/src/AvaloniaAttributesPlugin/AvaloniaAttributesPlugIn.csproj
@@ -62,8 +62,8 @@
-
-
+
+
diff --git a/src/DocusaurusExportPlugin/DocusaurusExportPlugin.csproj b/src/DocusaurusExportPlugin/DocusaurusExportPlugin.csproj
index 528233c..fcd7875 100644
--- a/src/DocusaurusExportPlugin/DocusaurusExportPlugin.csproj
+++ b/src/DocusaurusExportPlugin/DocusaurusExportPlugin.csproj
@@ -63,8 +63,8 @@
-
-
+
+
diff --git a/src/DocusaurusPresentationStyle/DocusaurusMarkdown/DocusaurusMarkdownPresentationStyle.cs b/src/DocusaurusPresentationStyle/DocusaurusMarkdown/DocusaurusMarkdownPresentationStyle.cs
index 9fac58c..1388476 100644
--- a/src/DocusaurusPresentationStyle/DocusaurusMarkdown/DocusaurusMarkdownPresentationStyle.cs
+++ b/src/DocusaurusPresentationStyle/DocusaurusMarkdown/DocusaurusMarkdownPresentationStyle.cs
@@ -18,12 +18,12 @@
// 02/27/2025 TU Adjusted the code to support the MDX-format
//===============================================================================================================
-using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Sandcastle.Core;
using Sandcastle.Core.PresentationStyle;
+using Sandcastle.Core.Project;
namespace DocusaurusPresentationStyle.DocusaurusMarkdown
{
diff --git a/src/DocusaurusPresentationStyle/DocusaurusMarkdown/DocusaurusMarkdownTransformation.cs b/src/DocusaurusPresentationStyle/DocusaurusMarkdown/DocusaurusMarkdownTransformation.cs
index 430f2fe..130e76d 100644
--- a/src/DocusaurusPresentationStyle/DocusaurusMarkdown/DocusaurusMarkdownTransformation.cs
+++ b/src/DocusaurusPresentationStyle/DocusaurusMarkdown/DocusaurusMarkdownTransformation.cs
@@ -20,16 +20,15 @@
using System;
using System.Collections.Generic;
-using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Xml.Linq;
using DocusaurusPresentationStyle.DocusaurusMarkdown.Elements;
-using Sandcastle.Core;
using Sandcastle.Core.PresentationStyle.Transformation;
using Sandcastle.Core.PresentationStyle.Transformation.Elements;
using Sandcastle.Core.PresentationStyle.Transformation.Elements.Html;
using Sandcastle.Core.PresentationStyle.Transformation.Elements.Markdown;
+using Sandcastle.Core.Project;
using Sandcastle.Core.Reflection;
using CodeElement = DocusaurusPresentationStyle.DocusaurusMarkdown.Elements.CodeElement;
using MarkdownGlossaryElement = Sandcastle.Core.PresentationStyle.Transformation.Elements.Markdown.GlossaryElement;
@@ -44,9 +43,9 @@ public class DocusaurusMarkdownTransformation : TopicTransformationCore
{
//=====================================================================
- private XDocument? pageTemplate;
+ private XDocument? _pageTemplate;
- private static readonly HashSet spacePreservedElements = new HashSet(
+ private static readonly HashSet SpacePreservedElements = new HashSet(
new[] { "code", "pre", "snippet" }, StringComparer.OrdinalIgnoreCase);
//=====================================================================
@@ -471,10 +470,10 @@ protected override void CreateNoticeDefinitions()
///
protected override XDocument RenderTopic()
{
- if(pageTemplate == null)
- pageTemplate = LoadTemplateFile(this.TopicTemplatePath, null);
+ if(_pageTemplate == null)
+ _pageTemplate = LoadTemplateFile(this.TopicTemplatePath, null);
- var document = new XDocument(pageTemplate);
+ var document = new XDocument(_pageTemplate);
this.CurrentElement = document.Root;
@@ -527,7 +526,7 @@ public override void RenderTextNode(XElement? content, XText? textNode)
// list of elements that should preserve space, just add the text as-is. Otherwise,normalize the
// whitespace.
if(text.Length == 0 || (content.Name != "document" && content.Attribute(Element.XmlSpace) != null) ||
- spacePreservedElements.Contains(textNode.Parent?.Name.LocalName ?? string.Empty) ||
+ SpacePreservedElements.Contains(textNode.Parent?.Name.LocalName ?? string.Empty) ||
((textNode.Parent?.Name.LocalName == "div" || textNode.Parent?.Name.LocalName == "span") &&
textNode.Ancestors("syntax").Any()))
{
@@ -650,7 +649,7 @@ private static void RenderNotices(TopicTransformationCore transformation)
if(element != null)
{
if(n.UseValueForText)
- noticeText = element.Value?.NormalizeWhiteSpace();
+ noticeText = element.Value.NormalizeWhiteSpace();
if(String.IsNullOrWhiteSpace(noticeText))
noticeText = n.NoticeMessage;
@@ -670,7 +669,7 @@ private static void RenderNotices(TopicTransformationCore transformation)
if(attr != null)
{
if(n.UseValueForText)
- noticeText = attr.Element("argument")?.Element("value")?.Value?.NormalizeWhiteSpace();
+ noticeText = attr.Element("argument")?.Element("value")?.Value.NormalizeWhiteSpace();
if(String.IsNullOrWhiteSpace(noticeText))
noticeText = n.NoticeMessage;
@@ -692,7 +691,7 @@ private static void RenderNotices(TopicTransformationCore transformation)
message.Add("\n");
// If the notice text starts with '@', it's a content item
- if(noticeText[0] == '@')
+ if(noticeText is {Length: > 0} && noticeText[0] == '@')
message.Add(new XElement("include", new XAttribute("item", noticeText.Substring(1))));
else
message.Add(noticeText);
@@ -751,7 +750,7 @@ private static void RenderNoticeTags(TopicTransformationCore transformation, XEl
var tag = new XElement("Tag", new XAttribute("type", n.TagStyleClasses ?? "is-warning"));
// If the notice text starts with '@', it's a content item
- if(noticeText[0] == '@')
+ if(noticeText is {Length: > 0} && noticeText[0] == '@')
tag.Add(new XElement("include", new XAttribute("item", noticeText.Substring(1))));
else
tag.Add(noticeText);
@@ -909,7 +908,7 @@ private static void RenderApiNamespaceAndAssemblyInformation(TopicTransformation
}
var containers = transformation.ReferenceNode.Element("containers");
- var libraries = containers?.Elements("library");
+ var libraries = containers?.Elements("library").ToArray() ?? [];
content.Add("**",
new XElement("include", new XAttribute("item", "boilerplate_requirementsNamespace")), "** ",
@@ -919,13 +918,13 @@ private static void RenderApiNamespaceAndAssemblyInformation(TopicTransformation
int separatorSize = 1;
bool first = true;
- if(libraries?.Count() > 1)
+ if(libraries is {Length: > 1})
{
content.Add("**",
new XElement("include", new XAttribute("item", "boilerplate_requirementsAssemblies")), "**");
separatorSize = 2;
}
- else
+ else
{
content.Add("**",
new XElement("include", new XAttribute("item", "boilerplate_requirementsAssemblyLabel")), "**");
@@ -963,21 +962,26 @@ private static void RenderApiNamespaceAndAssemblyInformation(TopicTransformation
// Show XAML XML namespaces for APIs that support XAML. All topics that have auto-generated XAML
// syntax get an "XMLNS for XAML" line in the Requirements section. Topics with boilerplate XAML
// syntax, e.g. "Not applicable", do NOT get this line.
- var xamlCode = transformation.SyntaxNode.Elements("div").Where(d => d.Attribute("codeLanguage")?.Value.Equals(
- "XAML", StringComparison.Ordinal) ?? false);
+ var xamlCode = transformation.SyntaxNode
+ .Elements("div")
+ .Where(d => d.Attribute("codeLanguage")?.Value.Equals("XAML", StringComparison.Ordinal) ?? false)
+ .ToArray();
- if(xamlCode.Any())
+ if(xamlCode.Length != 0)
{
- var xamlXmlNS = xamlCode.Elements("div").Where(d => d.Attribute("class")?.Value == "xamlXmlnsUri");
+ var xamlXmlNs = xamlCode
+ .Elements("div")
+ .Where(d => d.Attribute("class")?.Value == "xamlXmlnsUri")
+ .ToArray();
content.Add(" \n", "**",
new XElement("include", new XAttribute("item", "boilerplate_xamlXmlnsRequirements")), "** ");
- if(xamlXmlNS.Any())
+ if(xamlXmlNs.Length != 0)
{
first = true;
- foreach(var d in xamlXmlNS)
+ foreach(var d in xamlXmlNs)
{
if(!first)
content.Add(", ");
@@ -1048,10 +1052,10 @@ private static void RenderApiRootList(TopicTransformationCore transformation)
var elements = transformation.ReferenceNode.Element("elements")?.Elements("element").OrderBy(
e => e.Element("apidata")?.Attribute("name")?.Value).ToList();
- if((elements?.Count ?? 0) == 0)
+ if(elements is null or { Count: 0 })
return;
- var (title, _) = transformation.CreateSection(elements?[0].GenerateUniqueId(), true, "title_namespaces", null);
+ var (title, _) = transformation.CreateSection(elements[0].GenerateUniqueId(), true, "title_namespaces", null);
transformation.CurrentElement.Add(title);
@@ -1095,10 +1099,10 @@ private static void RenderApiNamespaceGroupList(TopicTransformationCore transfor
return name.Substring(name.IndexOf(':') + 1);
}).ToList();
- if((elements?.Count ?? 0) == 0)
+ if(elements is null or {Count : 0})
return;
- var (title, _) = transformation.CreateSection(elements?[0].GenerateUniqueId(), true,
+ var (title, _) = transformation.CreateSection(elements[0].GenerateUniqueId(), true,
"tableTitle_namespace", null);
transformation.CurrentElement.Add(title);
@@ -1226,7 +1230,7 @@ private static void RenderApiEnumerationMembersList(TopicTransformationCore tran
{
EnumValueFormat enumFormat = thisTransform.FlagsEnumValueFormat;
int groupSize = thisTransform.IncludeIntegerEnumSeparators ? 3 : 0, minWidth = 0;
- bool signedValues = enumValues.Any(v => v.Length > 0 && v[0] == '-');
+ bool signedValues = enumValues.Any(v => v?.Length > 0 && v[0] == '-');
if(enumFormat != EnumValueFormat.IntegerValue &&
thisTransform.ReferenceNode.AttributeOfType("T:System.FlagsAttribute") != null)
@@ -1335,17 +1339,20 @@ private static void RenderApiTypeMemberLists(TopicTransformationCore transformat
{
var allMembers = transformation.ReferenceNode.Element("elements")?.Elements("element").ToList();
- if((allMembers?.Count ?? 0) == 0)
+ if(allMembers is null or {Count: 0})
return;
- var overloads = allMembers?.Where(e => e.Attribute("api")!.Value.StartsWith("Overload:",
+ var overloads = allMembers.Where(e => e.Attribute("api")!.Value.StartsWith("Overload:",
StringComparison.Ordinal)).ToList();
// Remove overload topics and add their members to the full member list
foreach(var overload in overloads)
{
- allMembers.Remove(overload);
- allMembers.AddRange(overload.Elements("element"));
+ if (overload != null)
+ {
+ allMembers.Remove(overload);
+ allMembers.AddRange(overload.Elements("element"));
+ }
}
var memberGroups = new Dictionary>
@@ -1369,7 +1376,7 @@ private static void RenderApiTypeMemberLists(TopicTransformationCore transformat
// Group the members by section type
foreach(var m in allMembers)
{
- XElement? apiData = m.Element("apidata"), memberData = m.Element("memberdata"),
+ XElement? apiData = m.Element("apidata"),
procedureData = m.Element("proceduredata");
// Some members such as inherited interface members on a derived interface, contain no
@@ -1476,7 +1483,6 @@ private static void RenderApiTypeMemberLists(TopicTransformationCore transformat
e.Element("memberdata")?.Attribute("overload") == null &&
!(e.Parent?.Attribute("api")?.Value ?? String.Empty).StartsWith(
"Overload:", StringComparison.Ordinal)) ? "false" : "true";
- bool isExtensionMethod = e.AttributeOfType("T:System.Runtime.CompilerServices.ExtensionAttribute") != null;
var summaryCell = new XElement("td");
@@ -1577,9 +1583,11 @@ private static void RenderApiTypeMemberLists(TopicTransformationCore transformat
private static void RenderApiSectionTable(TopicTransformationCore transformation, string sectionTitleItem,
IEnumerable sectionElements)
{
- if(sectionElements.Any())
+ var sections = sectionElements as XElement[] ?? sectionElements.ToArray();
+
+ if(sections.Length != 0)
{
- var (title, _) = transformation.CreateSection(sectionElements.First().GenerateUniqueId(), true,
+ var (title, _) = transformation.CreateSection(sections.First().GenerateUniqueId(), true,
sectionTitleItem, null);
transformation.CurrentElement.Add(title);
@@ -1588,7 +1596,7 @@ private static void RenderApiSectionTable(TopicTransformationCore transformation
transformation.CurrentElement.Add(table);
- foreach(var se in sectionElements)
+ foreach(var se in sections)
{
var descCell = new XElement("td");
@@ -1669,10 +1677,12 @@ private static void RenderApiRevisionHistorySection(TopicTransformationCore tran
if(revisionHistory == null || revisionHistory.Attribute("visible")?.Value == "false")
return;
- var revisions = revisionHistory.Elements("revision").Where(
- h => h.Attribute("visible")?.Value != "false");
+ var revisions = revisionHistory
+ .Elements("revision")
+ .Where(h => h.Attribute("visible")?.Value != "false")
+ .ToArray();
- if(revisions.Any())
+ if(revisions.Length != 0)
{
var (title, _) = transformation.CreateSection(revisionHistory.GenerateUniqueId(), true,
"title_revisionHistory", null);
@@ -1849,9 +1859,9 @@ private static void RenderApiAutoGeneratedSeeAlsoLinks(TopicTransformationCore t
}
// Add a link to the namespace topic
- string namespaceId = transformation.ReferenceNode.Element("containers")?.Element("namespace")?.Attribute("api")?.Value;
+ var namespaceId = transformation.ReferenceNode.Element("containers")?.Element("namespace")?.Attribute("api")?.Value;
- if(!String.IsNullOrWhiteSpace(namespaceId))
+ if(!string.IsNullOrWhiteSpace(namespaceId))
{
subsection.Add(new XElement("referenceLink",
new XAttribute("target", namespaceId),
diff --git a/src/DocusaurusPresentationStyle/DocusaurusMarkdown/Elements/MdxListElement.cs b/src/DocusaurusPresentationStyle/DocusaurusMarkdown/Elements/MdxListElement.cs
index 3320c4f..fe71d51 100644
--- a/src/DocusaurusPresentationStyle/DocusaurusMarkdown/Elements/MdxListElement.cs
+++ b/src/DocusaurusPresentationStyle/DocusaurusMarkdown/Elements/MdxListElement.cs
@@ -79,7 +79,6 @@ public override void Render(TopicTransformationCore? transformation, XElement? e
default:
throw new ArgumentException($"Invalid element type {element.Attribute("type")?.Value}");
- break;
}
}
}
\ No newline at end of file
diff --git a/src/DocusaurusPresentationStyle/DocusaurusPresentationStyle.csproj b/src/DocusaurusPresentationStyle/DocusaurusPresentationStyle.csproj
index 63d548b..7046869 100644
--- a/src/DocusaurusPresentationStyle/DocusaurusPresentationStyle.csproj
+++ b/src/DocusaurusPresentationStyle/DocusaurusPresentationStyle.csproj
@@ -62,8 +62,8 @@
-
-
+
+
From d53d14b75707c508b8024e660de5df402607d1de Mon Sep 17 00:00:00 2001
From: Tim <47110241+timunie@users.noreply.github.com>
Date: Sun, 19 Oct 2025 20:40:35 +0200
Subject: [PATCH 2/8] update shfb tools path
---
build.ps1 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/build.ps1 b/build.ps1
index edb0b0f..661810e 100644
--- a/build.ps1
+++ b/build.ps1
@@ -20,7 +20,7 @@ New-item ./website/AvaloniaVersion.txt -ItemType File -Value $version -Force
Write-Host "Avalonia version is $version"
# set SHFBRoot
-$env:SHFBRoot = ".\src\packages\ewsoftware.shfb\2025.3.22\tools\"
+$env:SHFBRoot = ".\src\packages\ewsoftware.shfb\2025.9.30\tools\"
# Define a list of dotNET projects to build
$projectsToBuild = @(
From 90c87f21296bdda24e526257d91cfcc03da9d2b1 Mon Sep 17 00:00:00 2001
From: Tim <47110241+timunie@users.noreply.github.com>
Date: Tue, 21 Oct 2025 11:14:54 +0200
Subject: [PATCH 3/8] Follow SHFB migration guide
After update there were some breaking changes. Files were updated accordingly (see: https://ewsoftware.github.io/SHFB/html/bc933f8f-e792-45bf-afec-62aa2c46aa3b.htm)
---
README.md | 9 +++++++++
.../AvaloniaAttributesPlugIn.cs | 8 ++++----
.../AvaloniaAttributesPlugIn.csproj | 1 -
.../DocusaurusContentGenerator.cs | 6 +++---
...ortPluginPlugIn.cs => DocusaurusExportPlugIn.cs} | 13 ++++++-------
.../DocusaurusExportPlugin.csproj | 2 +-
.../Sidebar/SidebarGenerator.cs | 2 +-
.../Sidebar/SidebarSection.cs | 3 +++
8 files changed, 27 insertions(+), 17 deletions(-)
rename src/DocusaurusExportPlugin/{DocusaurusExportPluginPlugIn.cs => DocusaurusExportPlugIn.cs} (93%)
diff --git a/README.md b/README.md
index 42e9d20..6e5dece 100644
--- a/README.md
+++ b/README.md
@@ -20,6 +20,15 @@ It is important to mind the build order.
> .\build.ps1 -preview
> ```
+## Updating the Sandcastle tools
+
+> [WARNING] if you update the SHFB-nuget packages you also need to update the tools path in `build.ps1`
+> ```ps1
+> # set SHFBRoot
+> $env:SHFBRoot = ".\src\packages\ewsoftware.shfb\2025.9.30\tools\"
+> ```
+
+
## Generate the API docs for newer Avalonia version
Use the `update-submodule.ps1` script to update the version to the latest stable. if you need any other branch version, you need to link the branch name for the submodule by hand.
diff --git a/src/AvaloniaAttributesPlugin/AvaloniaAttributesPlugIn.cs b/src/AvaloniaAttributesPlugin/AvaloniaAttributesPlugIn.cs
index 27c55a0..b3236bf 100644
--- a/src/AvaloniaAttributesPlugin/AvaloniaAttributesPlugIn.cs
+++ b/src/AvaloniaAttributesPlugin/AvaloniaAttributesPlugIn.cs
@@ -1,5 +1,3 @@
-using SandcastleBuilder.Utils.BuildComponent;
-using SandcastleBuilder.Utils.BuildEngine;
using System;
using System.Collections.Generic;
using System.IO;
@@ -7,6 +5,8 @@
using System.Text.RegularExpressions;
using System.Xml.Linq;
using System.Xml.XPath;
+using Sandcastle.Core.BuildEngine;
+using Sandcastle.Core.PlugIn;
namespace AvaloniaAttributes
{
@@ -36,7 +36,7 @@ public sealed class AvaloniaAttributesPlugIn : IPlugIn
private List? _executionPoints;
- private BuildProcess? _builder;
+ private IBuildProcess? _builder;
//=====================================================================
@@ -61,7 +61,7 @@ public IEnumerable ExecutionPoints
///
/// A reference to the current build process
/// The configuration data that the plug-in should use to initialize itself
- public void Initialize(BuildProcess buildProcess, XElement configuration)
+ public void Initialize(IBuildProcess buildProcess, XElement configuration)
{
_builder = buildProcess;
diff --git a/src/AvaloniaAttributesPlugin/AvaloniaAttributesPlugIn.csproj b/src/AvaloniaAttributesPlugin/AvaloniaAttributesPlugIn.csproj
index 927e6e7..3b34970 100644
--- a/src/AvaloniaAttributesPlugin/AvaloniaAttributesPlugIn.csproj
+++ b/src/AvaloniaAttributesPlugin/AvaloniaAttributesPlugIn.csproj
@@ -64,7 +64,6 @@
-