Skip to content
Merged
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
13 changes: 12 additions & 1 deletion .github/scripts/validate-csharp-docs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,22 @@ for file in \
index.html \
api/Platform.Interfaces.html \
api/Platform.Interfaces.IFactory-1.html \
Platform.Interfaces.Documentation.pdf \
xrefmap.yml; do
if [[ ! -s "$site/$file" ]]; then
echo "Documentation site is missing $site/$file." >&2
exit 1
fi
done

echo "Validated DocFX home page, API pages, and cross-reference map."
if [[ $(head -c 5 "$site/Platform.Interfaces.Documentation.pdf") != '%PDF-' ]]; then
echo "Documentation PDF is invalid: $site/Platform.Interfaces.Documentation.pdf." >&2
exit 1
fi

if ! grep -Fq 'Platform.Interfaces.Documentation.pdf' "$site/index.html"; then
echo "Documentation home page is missing its PDF link: $site/index.html." >&2
exit 1
fi

echo "Validated DocFX home page, API pages, documentation PDF, and cross-reference map."
22 changes: 20 additions & 2 deletions .github/scripts/validate-csharp-docs.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@ import test from "node:test";

const validator = new URL("./validate-csharp-docs.sh", import.meta.url).pathname;

const withSite = (files, check) => {
const withSite = (files, check, contents = {}) => {
const site = mkdtempSync(join(tmpdir(), "csharp-docs-"));
try {
for (const file of files) {
const path = join(site, file);
mkdirSync(join(path, ".."), { recursive: true });
writeFileSync(path, "generated content");
const content = file === "index.html"
? '<a href="Platform.Interfaces.Documentation.pdf">Documentation PDF</a>'
: file.endsWith(".pdf") ? "%PDF-1.7\n" : "generated content";
writeFileSync(path, contents[file] ?? content);
}
check(spawnSync("bash", [validator, site], { encoding: "utf8" }));
} finally {
Expand All @@ -28,6 +31,7 @@ const requiredFiles = [
"api/Platform.Interfaces.html",
"api/Platform.Interfaces.IFactory-1.html",
"xrefmap.yml",
"Platform.Interfaces.Documentation.pdf",
];

test("accepts a complete DocFX site", () => {
Expand All @@ -44,3 +48,17 @@ for (const missingFile of requiredFiles) {
});
});
}

test("rejects an invalid documentation PDF", () => {
withSite(requiredFiles, ({ status, stderr }) => {
assert.notEqual(status, 0);
assert.match(stderr, /Documentation PDF is invalid/);
}, { "Platform.Interfaces.Documentation.pdf": "not a PDF" });
});

test("rejects a site with no documentation PDF link", () => {
withSite(requiredFiles, ({ status, stderr }) => {
assert.notEqual(status, 0);
assert.match(stderr, /home page is missing its PDF link/);
}, { "index.html": "generated content" });
});
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,9 @@ ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog

# Generated DocFX site
csharp/_site/

# NVidia Nsight GPU debugger configuration file
*.nvuser

Expand All @@ -343,4 +346,4 @@ ASALocalRun/
*.[0-9].rule.txt
*.[0-9][0-9].rule.txt
*.[0-9][0-9][0-9].rule.txt
*.[0-9][0-9][0-9][0-9].rule.txt
*.[0-9][0-9][0-9][0-9].rule.txt
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ NuGet package: [Platform.Interfaces](https://www.nuget.org/packages/Platform.Int

[PDF file](https://linksplatform.github.io/Interfaces/csharp/Platform.Interfaces.pdf) with code for e-readers.

[API documentation PDF](https://linksplatform.github.io/Interfaces/csharp/Platform.Interfaces.Documentation.pdf) generated by DocFX.

## Dependent libraries
* [Platform.Collections](https://github.com/linksplatform/Collections)
* [Platform.Setters](https://github.com/linksplatform/Setters)
Expand Down
4 changes: 2 additions & 2 deletions csharp/Platform.Interfaces/Platform.Interfaces.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<Description>LinksPlatform's Platform.Interfaces Class Library</Description>
<Copyright>Konstantin Diachenko</Copyright>
<AssemblyTitle>Platform.Interfaces</AssemblyTitle>
<VersionPrefix>0.5.2</VersionPrefix>
<VersionPrefix>0.5.3</VersionPrefix>
<Authors>Konstantin Diachenko</Authors>
<TargetFramework>net8</TargetFramework>
<AssemblyName>Platform.Interfaces</AssemblyName>
Expand All @@ -23,7 +23,7 @@
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<DebugType>embedded</DebugType>
<LangVersion>latest</LangVersion>
<PackageReleaseNotes>Fix package publishing while preserving embedded symbols, eliminate C# workflow warnings, and validate NuGet artifacts before release.</PackageReleaseNotes>
<PackageReleaseNotes>Fix package publishing while preserving embedded symbols, eliminate C# workflow warnings, validate NuGet artifacts before release, and add downloadable DocFX API documentation in PDF format.</PackageReleaseNotes>
<Nullable>enable</Nullable>
</PropertyGroup>

Expand Down
4 changes: 4 additions & 0 deletions csharp/docfx.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,16 @@
"globalMetadata": {
"_appTitle": "LinksPlatform's Platform.Interfaces Library",
"_enableSearch": true,
"pdf": true,
"pdfFileName": "Platform.Interfaces.Documentation.pdf",
"pdfTocPage": true,
"_gitContribute": {
"branch": "main"
},
"_gitUrlPattern": "github"
},
"markdownEngineName": "markdig",
"template": ["default", "modern"],
"dest": "_site"
}
}
Binary file added docs/screenshots/docfx-pdf-home.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions experiments/inspect-docfx-pdf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""Inspect a generated DocFX PDF with: pip install pypdf."""

import sys

from pypdf import PdfReader


reader = PdfReader(sys.argv[1])
text = "\n".join(page.extract_text() or "" for page in reader.pages)

print(f"Pages: {len(reader.pages)}")
for topic in ("Interfaces", "Platform.Interfaces", "IFactory", "IProvider"):
print(f"{topic}: {topic in text}")

if len(reader.pages) < 2 or any(topic not in text for topic in ("IFactory", "IProvider")):
raise SystemExit("The PDF is missing expected API content.")
Loading