From 769cf4a2b998c4a5ece630b45c9a1c2eefbaa037 Mon Sep 17 00:00:00 2001 From: Rafael Vuijk Date: Mon, 26 Oct 2026 23:57:49 +0000 Subject: [PATCH] The docs' pages with a '#' in their names are served and linked The compiler names a constructor #ctor and writes the dots in the name of an explicitly implemented interface member as '#', and Yadg.NET names a member's page after it: Erff/#ctor.html, Setting`1/AngouriMath#Convenience#ISettingState#CurrentState.html. Two things broke 117 links to them. GitHub Pages runs the gh-pages branch through Jekyll, which leaves out every file whose name starts with '#', so not one of the 115 constructors' pages on the site was published. The generator now writes a .nojekyll. No page here has front matter and nothing is in Sass or markdown, so Jekyll only ever copied the files, apart from the ones it dropped. And Yadg.NET wrote the '#' into each link as it was, where it begins the fragment, so the browser asked for Erff/ and for Setting`1/AngouriMath. Links to a member's page and cross-references now write it as %23; the sitemap already did. A link check of a local build goes from 244 broken links to 121, and none of the 121 is either of these. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura --- src/NaiveStaticGenerator/Program.cs | 9 +++++ src/Yadg.NET.patch | 53 +++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/src/NaiveStaticGenerator/Program.cs b/src/NaiveStaticGenerator/Program.cs index 5546d1c96..c365e967c 100644 --- a/src/NaiveStaticGenerator/Program.cs +++ b/src/NaiveStaticGenerator/Program.cs @@ -37,6 +37,7 @@ CopyImgFolderToFinalWebsite(); CopyCName(); CopyRobots(); +TurnOffJekyll(); GenerateSitemap(); GenerateLlmsTxt(); @@ -286,6 +287,14 @@ void CopyRobots() File.Copy(RootP._("robots.txt"), FinalOutputP._("robots.txt"), true); } +// GitHub Pages runs a branch through Jekyll unless it holds a .nojekyll, and Jekyll leaves out +// every file whose name starts with '#', '_' or '.'. The pages here are finished HTML with no +// front matter, so Jekyll had nothing to do but drop them: each constructor's page, #ctor.html. +void TurnOffJekyll() +{ + File.WriteAllText(FinalOutputP._(".nojekyll"), ""); +} + // Every page of the website, for search engines, which robots.txt points to. A page that is a // folder's index.html is served at the folder, so it is listed as the folder. void GenerateSitemap() diff --git a/src/Yadg.NET.patch b/src/Yadg.NET.patch index 89f4c5172..8b3fe849e 100644 --- a/src/Yadg.NET.patch +++ b/src/Yadg.NET.patch @@ -1,3 +1,56 @@ +diff --git a/Yadg.NET/WebsiteBuilder.cs b/Yadg.NET/WebsiteBuilder.cs +index 3e808a7..9c5666d 100644 +--- a/Yadg.NET/WebsiteBuilder.cs ++++ b/Yadg.NET/WebsiteBuilder.cs +@@ -21,7 +21,16 @@ namespace YadgNet + public WebsiteBuilder(IPageSave saver) + => this.saver = saver; + ++ // The compiler names a constructor #ctor, and writes the dots in the name of an ++ // explicitly implemented interface member as '#'. In a link that character begins the ++ // fragment, so the browser asked for the path before it; it is written %23. ++ internal static string InLink(string name) ++ => name.Replace("#", "%23"); ++ + internal static string? GetLinkWithinAsmByName(string cref) ++ => LinkWithinAsmByName(cref) is { } link ? InLink(link) : null; ++ ++ private static string? LinkWithinAsmByName(string cref) + => (cref[..2], cref[2..]) switch + { + (_, var containsSystem) when NameParser.GetMethodName(cref).Contains("System") +diff --git a/Yadg.NET/WebsiteBuilder/MemberListBuilder.cs b/Yadg.NET/WebsiteBuilder/MemberListBuilder.cs +index 5024e8f..1924ab8 100644 +--- a/Yadg.NET/WebsiteBuilder/MemberListBuilder.cs ++++ b/Yadg.NET/WebsiteBuilder/MemberListBuilder.cs +@@ -42,23 +42,23 @@ namespace YadgNet + ? + + p( +- a($"./{cls.Name}/{method.Name}.html", h3(SplitWrapWordsMethod(method.Name + method.Overloads.First().Parameters))) + "Method" ++ a($"./{cls.Name}/{WebsiteBuilder.InLink(method.Name)}.html", h3(SplitWrapWordsMethod(method.Name + method.Overloads.First().Parameters))) + "Method" + ) + + : + + p( +- a($"./{cls.Name}/{method.Name}.html", h3(method.Name)) + "Method and its overloads" ++ a($"./{cls.Name}/{WebsiteBuilder.InLink(method.Name)}.html", h3(method.Name)) + "Method and its overloads" + ) + ) + , + DocProperty property => + p( +- a($"./{cls.Name}/{property.Name}.html", h3(property.Name)) + "Property" ++ a($"./{cls.Name}/{WebsiteBuilder.InLink(property.Name)}.html", h3(property.Name)) + "Property" + ), + DocField field => + p( +- a($"./{cls.Name}/{field.Name}.html", h3(field.Name)) + "Field" ++ a($"./{cls.Name}/{WebsiteBuilder.InLink(field.Name)}.html", h3(field.Name)) + "Field" + ), + _ => throw new Exception() + } diff --git a/Yadg.NET/WebsiteBuilder/MemberPageBuilder.cs b/Yadg.NET/WebsiteBuilder/MemberPageBuilder.cs index 3caa5da..36ed5fe 100644 --- a/Yadg.NET/WebsiteBuilder/MemberPageBuilder.cs