Generate a landing page linking to each package's documentation (#3076)

This commit is contained in:
Jesse Braham 2025-01-31 10:06:00 +01:00 committed by GitHub
parent 9a28bdfdbd
commit c74d614785
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 206 additions and 41 deletions

View File

@ -5,7 +5,7 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>esp-rs docs</title>
<title>esp-rs Documentation</title>
<link rel="icon" href="esp-rs.svg" />
<link href="https://fonts.googleapis.com/css2?family=Fira+Sans:wght@400;500&display=swap" rel="stylesheet" />
@ -93,19 +93,17 @@
<div class="content">
<div class="logo">
<img src="esp-rs.svg" alt="esp-rs logo" />
<div>{{ metadata[0].package }} Documentation</div>
<div>esp-rs Documentation</div>
</div>
<h2>{{ metadata[0].package }}</h2>
<h2>Packages</h2>
{%- for meta in metadata %}
<div class="crate">
<span class="crate-name">
<a href="{{ meta.chip }}/{{ meta.package }}/index.html">
{{ meta.chip_pretty }}
</a>
<a href="{{ meta.url }}">{{ meta.name }}</a>
</span>
<span class="crate-description">{{ meta.name }} (targeting {{ meta.chip_pretty }})</span>
<span class="crate-description">Documentation for <code>{{ meta.name }}</code> crate</span>
<span class="crate-version">{{ meta.version }}</span>
</div>
{%- endfor %}

View File

@ -0,0 +1,115 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{{ metadata[0].package }} Documentation</title>
<link rel="icon" href="../../esp-rs.svg" />
<link href="https://fonts.googleapis.com/css2?family=Fira+Sans:wght@400;500&display=swap" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css2?family=Source+Serif+4:ital,wght@0,400;0,600;1,400;1,600&display=swap"
rel="stylesheet" />
<style>
body {
background-color: rgb(53, 53, 53);
font-family: "Fira Sans", sans-serif;
color: white;
margin: 0;
padding: 40px 20px;
display: flex;
height: 100vh;
width: 100vw;
justify-content: center;
box-sizing: border-box;
}
.logo {
text-align: center;
margin-bottom: 50px;
font-size: 2em;
font-weight: 500;
}
.logo img {
width: 100px;
height: auto;
margin-bottom: 20px;
}
.content {
width: 900px;
}
h2 {
margin-top: 3rem;
}
.crate {
display: flex;
align-items: center;
padding: 10px;
border-bottom: 2px solid #454444;
}
.crate-description {
flex: 1;
font-family: "Source Serif 4", serif;
color: #c0c0c0;
text-align: center;
}
.crate-name {
color: #d6991d;
width: 120px;
}
/* Ensure the link color does not change after being clicked */
.crate-name a:link,
.crate-name a:visited,
.crate-name a:hover,
.crate-name a:active,
.crate-name a:focus {
color: #d6991d;
}
.crate-version {
color: #c0c0c0;
text-align: center;
width: 120px;
}
@media screen and (min-height: 650px) {
body {
align-items: center;
}
}
</style>
</head>
<body>
<div class="content">
<div class="logo">
<img src="../../esp-rs.svg" alt="esp-rs logo" />
<div>{{ metadata[0].package }} Documentation</div>
</div>
<h2>{{ metadata[0].package }}</h2>
{%- for meta in metadata %}
<div class="crate">
<span class="crate-name">
<a href="{{ meta.chip }}/{{ meta.package }}/index.html">
{{ meta.chip_pretty }}
</a>
</span>
<span class="crate-description">{{ meta.name }} (targeting {{ meta.chip_pretty }})</span>
<span class="crate-version">{{ meta.version }}</span>
</div>
{%- endfor %}
</div>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -80,6 +80,11 @@ impl Package {
matches!(self, EspHal | EspLpHal | EspWifi)
}
/// Should documentation be built for the package?
pub fn should_document(&self) -> bool {
!matches!(self, Package::Examples | Package::HilTest | Package::QaTest)
}
}
#[derive(Debug, Clone, Copy, Display, ValueEnum)]

View File

@ -484,10 +484,7 @@ fn build_documentation(workspace: &Path, mut args: BuildDocumentationArgs) -> Re
for package in args.packages {
// Not all packages need documentation built:
if matches!(
package,
Package::Examples | Package::HilTest | Package::QaTest
) {
if !package.should_document() {
continue;
}
@ -524,15 +521,13 @@ fn build_documentation_index(
mut args: BuildDocumentationIndexArgs,
) -> Result<()> {
let docs_path = workspace.join("docs");
let resources_path = workspace.join("resources");
args.packages.sort();
for package in args.packages {
// Not all packages have documentation built:
if matches!(
package,
Package::Examples | Package::HilTest | Package::QaTest
) {
if !package.should_document() {
continue;
}
@ -548,14 +543,17 @@ fn build_documentation_index(
// Each path we iterate over should be the directory for a given version of
// the package's documentation:
for path in fs::read_dir(package_docs_path)? {
let path = path?.path();
if path.is_file() {
log::debug!("Path is not a directory, skipping: '{}'", path.display());
for version_path in fs::read_dir(package_docs_path)? {
let version_path = version_path?.path();
if version_path.is_file() {
log::debug!(
"Path is not a directory, skipping: '{}'",
version_path.display()
);
continue;
}
for path in fs::read_dir(&path)? {
for path in fs::read_dir(&version_path)? {
let path = path?.path();
if path.is_dir() {
device_doc_paths.push(path);
@ -567,11 +565,11 @@ fn build_documentation_index(
.map(|path| {
let chip = path
.components()
.into_iter()
.last()
.unwrap()
.as_os_str()
.to_string_lossy();
let chip = Chip::from_str(&chip, true).unwrap();
chip
@ -581,38 +579,87 @@ fn build_documentation_index(
chips.sort();
let meta = generate_documentation_meta_for_package(workspace, package, &chips)?;
generate_index(workspace, &path, &meta)?;
render_template(
"package_index.html.jinja",
"index.html",
&version_path,
&resources_path,
minijinja::context! { metadata => meta },
)?;
}
}
// Copy any additional assets to the documentation's output path:
fs::copy(
resources_path.join("esp-rs.svg"),
docs_path.join("esp-rs.svg"),
)
.context("Failed to copy esp-rs.svg")?;
let meta = generate_documentation_meta_for_index(&workspace)?;
render_template(
"index.html.jinja",
"index.html",
&docs_path,
&resources_path,
minijinja::context! { metadata => meta },
)?;
Ok(())
}
fn generate_index(workspace: &Path, package_version_path: &Path, meta: &[Value]) -> Result<()> {
let resources = workspace.join("resources");
fn generate_documentation_meta_for_index(workspace: &Path) -> Result<Vec<Value>> {
let mut metadata = Vec::new();
// Copy any additional assets to the documentation's output path:
fs::copy(
resources.join("esp-rs.svg"),
package_version_path.join("esp-rs.svg"),
)
.context("Failed to copy esp-rs.svg")?;
for package in Package::iter() {
// Not all packages have documentation built:
if !package.should_document() {
continue;
}
// Render the index and write it out to the documentaiton's output path:
let source = fs::read_to_string(resources.join("index.html.jinja"))
.context("Failed to read index.html.jinja")?;
let version = xtask::package_version(workspace, package)?;
let url = if package.chip_features_matter() {
format!("{package}/{version}/index.html")
} else {
let crate_name = package.to_string().replace('-', "_");
format!("{package}/{version}/{crate_name}/index.html")
};
metadata.push(minijinja::context! {
name => package,
version => version,
url => url,
});
}
Ok(metadata)
}
fn render_template<C>(
template: &str,
name: &str,
path: &Path,
resources: &Path,
ctx: C,
) -> Result<()>
where
C: serde::Serialize,
{
let source = fs::read_to_string(resources.join(template))
.context(format!("Failed to read {template}"))?;
let mut env = minijinja::Environment::new();
env.add_template("index", &source)?;
env.add_template(template, &source)?;
let tmpl = env.get_template("index")?;
let html = tmpl.render(minijinja::context! { metadata => meta })?;
let tmpl = env.get_template(template)?;
let html = tmpl.render(ctx)?;
let index = package_version_path.join("index.html");
fs::write(&index, html).context("Failed to write index.html")?;
log::info!("Created {}", index.display());
// Write out the rendered HTML to the desired path:
let path = path.join(name);
fs::write(&path, html).context(format!("Failed to write {name}"))?;
log::info!("Created {}", path.display());
Ok(())
}