diff --git a/.gitignore b/.gitignore index 49748b0d..a6a1c95e 100644 --- a/.gitignore +++ b/.gitignore @@ -405,7 +405,8 @@ Docs/pages/.docusaurus/ Docs/pages/build/ # Aggregated content (fetched at build time by ./build.sh Pages from sibling repositories) -Docs/pages/docs/abstractions -Docs/pages/docs/awexpect -Docs/pages/docs/mockolate -Docs/pages/docs/extensions +Docs/pages/docs/Abstractions +Docs/pages/docs/aweXpect +Docs/pages/docs/Mockolate +Docs/pages/docs/Extensions +Docs/pages/docs/Chronology diff --git a/Docs/pages/README.md b/Docs/pages/README.md index 4a62d926..986c8b7a 100644 --- a/Docs/pages/README.md +++ b/Docs/pages/README.md @@ -31,7 +31,7 @@ Two workflows publish the docs: - **`.github/workflows/build.yml`** (`name: Build`) - the main CI workflow runs on every push to `main` and on release tags. Its `build-pages` job (`needs: [ pack ]`) builds and deploys the docs after tests, static analysis and packaging have all succeeded. This is the normal channel for in-repo doc changes. - **`.github/workflows/pages.yml`** (`name: Pages`) - triggered by `repository_dispatch` events of type `extension-documentation-updated-event`. Extension repos use this to ask the site to rebuild after their own docs change, without going through the full CI build. -Both workflows run the same deploy steps: setup .NET → `./build.sh Pages` (downloads the `Docs/pages/` folder of every extension repo listed in `Pipeline/Build.Pages.cs` into `Docs/pages/docs/extensions/project//`) → npm install → docusaurus build → publish to the `gh-pages` branch via [`peaceiris/actions-gh-pages`](https://github.com/peaceiris/actions-gh-pages). +Both workflows run the same deploy steps: setup .NET → `./build.sh Pages` (downloads the `Docs/pages/` folder of every extension repo listed in `Pipeline/Build.Pages.cs` into `Docs/pages/docs/Extensions/project//`) → npm install → docusaurus build → publish to the `gh-pages` branch via [`peaceiris/actions-gh-pages`](https://github.com/peaceiris/actions-gh-pages). In repository settings, GitHub Pages source must be set to **Deploy from a branch** → `gh-pages` / `(root)`. @@ -43,7 +43,7 @@ The custom domain `docs.testably.org` is configured via the `static/CNAME` file. ```csharp { "Testably.Abstractions.MyExtension", "MyExtension" } ``` - The key is the GitHub repository name under the `Testably` org; the value is the directory under `Docs/pages/docs/extensions/project/`. + The key is the GitHub repository name under the `Testably` org; the value is the directory under `Docs/pages/docs/Extensions/project/`. 2. In the extension repo, place documentation pages under `Docs/pages/` and an optional `README.md` (the section from the first `##` header onwards is substituted into any local file beginning with `00-` that contains the `{README}` placeholder). 3. From the extension repo's CI, dispatch the `extension-documentation-updated-event` event to this repo so it rebuilds. diff --git a/Docs/pages/docusaurus.config.ts b/Docs/pages/docusaurus.config.ts index bf8553c6..239114e8 100644 --- a/Docs/pages/docusaurus.config.ts +++ b/Docs/pages/docusaurus.config.ts @@ -87,15 +87,15 @@ const config: Config = { }, { type: 'docSidebar', - sidebarId: 'extensionsSidebar', + sidebarId: 'chronologySidebar', position: 'right', - label: 'Extensions', + label: 'Chronology', }, { type: 'docSidebar', - sidebarId: 'chronologySidebar', + sidebarId: 'extensionsSidebar', position: 'right', - label: 'Chronology', + label: 'Extensions', }, ], }, diff --git a/Docs/pages/sidebars.ts b/Docs/pages/sidebars.ts index ca651517..62952179 100644 --- a/Docs/pages/sidebars.ts +++ b/Docs/pages/sidebars.ts @@ -1,11 +1,11 @@ import type {SidebarsConfig} from '@docusaurus/plugin-content-docs'; const sidebars: SidebarsConfig = { - abstractionsSidebar: [{type: 'autogenerated', dirName: 'abstractions'}], - awexpectSidebar: [{type: 'autogenerated', dirName: 'awexpect'}], - mockolateSidebar: [{type: 'autogenerated', dirName: 'mockolate'}], - extensionsSidebar: [{type: 'autogenerated', dirName: 'extensions'}], - chronologySidebar: [{type: 'autogenerated', dirName: 'chronology'}], + abstractionsSidebar: [{type: 'autogenerated', dirName: 'Abstractions'}], + awexpectSidebar: [{type: 'autogenerated', dirName: 'aweXpect'}], + mockolateSidebar: [{type: 'autogenerated', dirName: 'Mockolate'}], + extensionsSidebar: [{type: 'autogenerated', dirName: 'Extensions'}], + chronologySidebar: [{type: 'autogenerated', dirName: 'Chronology'}], }; export default sidebars; diff --git a/Docs/pages/src/clientModules/sectionTheme.ts b/Docs/pages/src/clientModules/sectionTheme.ts index a2e5f2a8..ec586bfa 100644 --- a/Docs/pages/src/clientModules/sectionTheme.ts +++ b/Docs/pages/src/clientModules/sectionTheme.ts @@ -9,11 +9,11 @@ * the bracket beige defined in `:root`. */ -const SECTION_PATTERN = /^\/(abstractions|awexpect|mockolate|extensions)(?:\/|$)/; +const SECTION_PATTERN = /^\/(abstractions|awexpect|mockolate|extensions)(?:\/|$)/i; function getSection(pathname: string): string | null { const match = pathname.match(SECTION_PATTERN); - return match ? match[1] : null; + return match ? match[1].toLowerCase() : null; } function applySection(): void { diff --git a/Docs/pages/src/css/custom.css b/Docs/pages/src/css/custom.css index 768824d5..671f688b 100644 --- a/Docs/pages/src/css/custom.css +++ b/Docs/pages/src/css/custom.css @@ -9,7 +9,7 @@ * - Mockolate: chocolate / tan. */ -/* ───── Default (landing page, /extensions/*) ───── +/* ───── Default (landing page, /Extensions/*) ───── * Light mode: darker warm neutral (the bracket beige #c8c0b4 has poor * contrast against the white page background). * Dark mode: the bracket beige itself, which reads well on dark. diff --git a/Docs/pages/src/pages/index.tsx b/Docs/pages/src/pages/index.tsx index 5a795328..8c727374 100644 --- a/Docs/pages/src/pages/index.tsx +++ b/Docs/pages/src/pages/index.tsx @@ -20,7 +20,7 @@ type Library = { const libraries: Library[] = [ { label: 'Testably.Abstractions', - href: '/abstractions/', + href: '/Abstractions/', tagline: 'Mock the unmockable.', description: 'IFileSystem, ITimeSystem and IRandomSystem abstractions with feature-complete in-memory mocks for deterministic, cross-platform unit tests.', @@ -29,7 +29,7 @@ const libraries: Library[] = [ }, { label: 'aweXpect', - href: '/awexpect/', + href: '/aweXpect/', tagline: 'Fluent expectations for .NET.', description: 'A modern, async-first assertion library with a natural-language API. Plays well with xUnit, NUnit, MSTest and TUnit.', @@ -38,7 +38,7 @@ const libraries: Library[] = [ }, { label: 'Mockolate', - href: '/mockolate/', + href: '/Mockolate/', tagline: 'AOT-friendly mocking via source generators.', description: 'Strongly-typed, source-generator-based mocking for .NET. No runtime proxies, no reflection, native-AOT compatible.', @@ -110,7 +110,7 @@ function LibraryCards() {

Looking for add-ons? See the{' '} - Extensions section. + Extensions section.

diff --git a/Docs/pages/src/theme/Logo/index.tsx b/Docs/pages/src/theme/Logo/index.tsx index 698540eb..62e098d7 100644 --- a/Docs/pages/src/theme/Logo/index.tsx +++ b/Docs/pages/src/theme/Logo/index.tsx @@ -32,11 +32,11 @@ const DEFAULT_LOGO = { dark: 'img/testably-dark.svg', }; -const SECTION_PATTERN = /^\/(abstractions|awexpect|mockolate)(?:\/|$)/; +const SECTION_PATTERN = /^\/(abstractions|awexpect|mockolate)(?:\/|$)/i; function pickLogo(pathname: string) { const match = pathname.match(SECTION_PATTERN); - return match ? SECTION_LOGOS[match[1]] : DEFAULT_LOGO; + return match ? SECTION_LOGOS[match[1].toLowerCase()] : DEFAULT_LOGO; } export default function Logo(props: Props): ReactNode { diff --git a/Pipeline/Build.Pages.cs b/Pipeline/Build.Pages.cs index 4f8a2cc6..e9199afe 100644 --- a/Pipeline/Build.Pages.cs +++ b/Pipeline/Build.Pages.cs @@ -59,23 +59,23 @@ record ReadmeSubstitution( /// The slices that compose the testably.org documentation portal. Order matters: /// later sources may overlay files written by earlier ones (e.g. each extension /// overwrites the placeholder 00-index.md seeded by the bundled - /// aweXpect/extensions slice). + /// aweXpect/Extensions slice). /// static readonly DocsSource[] AggregatedSources = [ - new("Testably", "Testably.Abstractions", "Docs/pages/docs", "abstractions"), - new("Testably", "aweXpect", "Docs/pages", "awexpect", + new("Testably", "Testably.Abstractions", "Docs/pages/docs", "Abstractions"), + new("Testably", "aweXpect", "Docs/pages", "aweXpect", ExtraReadmes: [ new("Testably", "aweXpect.Migration", "09-migration.md"), ]), - new("Testably", "aweXpect.Json", "Docs/pages", "extensions/aweXpect.Json", InlineReadme: true), - new("Testably", "aweXpect.Mockolate", "Docs/pages", "extensions/aweXpect.Mockolate", InlineReadme: true), - new("Testably", "aweXpect.Reflection", "Docs/pages", "extensions/aweXpect.Reflection", InlineReadme: true), - new("Testably", "aweXpect.Testably", "Docs/pages", "extensions/aweXpect.Testably", InlineReadme: true), - new("Testably", "aweXpect.Web", "Docs/pages", "extensions/aweXpect.Web", InlineReadme: true), - new("Testably", "aweXpect.Chronology", "Docs/pages", "chronology", InlineReadme: true), - new("Testably", "Mockolate", "Docs/pages", "mockolate", + new("Testably", "aweXpect.Json", "Docs/pages", "Extensions/aweXpect.Json", InlineReadme: true), + new("Testably", "aweXpect.Mockolate", "Docs/pages", "Extensions/aweXpect.Mockolate", InlineReadme: true), + new("Testably", "aweXpect.Reflection", "Docs/pages", "Extensions/aweXpect.Reflection", InlineReadme: true), + new("Testably", "aweXpect.Testably", "Docs/pages", "Extensions/aweXpect.Testably", InlineReadme: true), + new("Testably", "aweXpect.Web", "Docs/pages", "Extensions/aweXpect.Web", InlineReadme: true), + new("Testably", "aweXpect.Chronology", "Docs/pages", "Chronology", InlineReadme: true), + new("Testably", "Mockolate", "Docs/pages", "Mockolate", ExtraReadmes: [ new("Testably", "Mockolate.Migration", "11-migration.md"),