Simplify building documentation, automatically generate documentation index (#1279)

This commit is contained in:
Jesse Braham 2024-03-13 17:02:13 +00:00 committed by GitHub
parent 1d3fa8e93b
commit 7983923b16
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 198 additions and 195 deletions

View File

@ -1,25 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# Extract the package version from `esp-hal` (using arcane methods):
PKG_VERSION=$(
cargo metadata --format-version=1 --no-deps --manifest-path=esp-hal/Cargo.toml \
| jq -r '.packages[] | select(.name=="esp-hal") | .version'
)
# Build the documentation for each supported cheap, namespacing by
# package version and chip:
CHIPS=("esp32" "esp32c2" "esp32c3" "esp32c6" "esp32h2" "esp32p4" "esp32s2" "esp32s3")
for CHIP in "${CHIPS[@]}"; do
cargo xtask build-documentation \
--output-path="docs/esp-hal/$PKG_VERSION"/"$CHIP"/ \
esp-hal \
"$CHIP"
done
# Copy any additional resources (such as the index and our logo)
# to the location of the built documentation as well:
cp resources/esp-rs.svg docs/
cp resources/index.html docs/

View File

@ -17,7 +17,7 @@ jobs:
ldproxy: false
- name: Build documentation
run: ./.github/scripts/build_docs.sh
run: cargo xtask build-documentation esp-hal
# https://github.com/actions/deploy-pages/issues/303#issuecomment-1951207879
- name: Remove problematic '.lock' files

View File

@ -1,139 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>esp-rs docs</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;
}
.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>esp-rs docs</div>
</div>
<!-- TODO: Generate the index from a template, rather than hard-coding
the package version in the URL and '.crate-version' span. -->
<div class="crate">
<span class="crate-name"><a href="esp-hal/0.16.1/esp32/esp_hal/index.html">esp32</a></span>
<span class="crate-description">esp-hal (targeting ESP32)</span>
<span class="crate-version">0.16.1</span>
</div>
<div class="crate">
<span class="crate-name"><a href="esp-hal/0.16.1/esp32c2/esp_hal/index.html">esp32c2</a></span>
<span class="crate-description">esp-hal (targeting ESP32-C2)</span>
<span class="crate-version">0.16.1</span>
</div>
<div class="crate">
<span class="crate-name"><a href="esp-hal/0.16.1/esp32c3/esp_hal/index.html">esp32c3</a></span>
<span class="crate-description">esp-hal (targeting ESP32-C3)</span>
<span class="crate-version">0.16.1</span>
</div>
<div class="crate">
<span class="crate-name"><a href="esp-hal/0.16.1/esp32c6/esp_hal/index.html">esp32c6</a></span>
<span class="crate-description">esp-hal (targeting ESP32-C6)</span>
<span class="crate-version">0.16.1</span>
</div>
<div class="crate">
<span class="crate-name"><a href="esp-hal/0.16.1/esp32h2/esp_hal/index.html">esp32h2</a></span>
<span class="crate-description">esp-hal (targeting ESP32-H2)</span>
<span class="crate-version">0.16.1</span>
</div>
<div class="crate">
<span class="crate-name"><a href="esp-hal/0.16.1/esp32p4/esp_hal/index.html">esp32p4</a></span>
<span class="crate-description">esp-hal (targeting ESP32-P4)</span>
<span class="crate-version">0.16.1</span>
</div>
<div class="crate">
<span class="crate-name"><a href="esp-hal/0.16.1/esp32s2/esp_hal/index.html">esp32s2</a></span>
<span class="crate-description">esp-hal (targeting ESP32-S2)</span>
<span class="crate-version">0.16.1</span>
</div>
<div class="crate">
<span class="crate-name"><a href="esp-hal/0.16.1/esp32s3/esp_hal/index.html">esp32s3</a></span>
<span class="crate-description">esp-hal (targeting ESP32-S3)</span>
<span class="crate-version">0.16.1</span>
</div>
</div>
</body>
</html>

109
resources/index.html.jinja Normal file
View File

@ -0,0 +1,109 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>esp-rs docs</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;
}
.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>esp-rs docs</div>
</div>
{%- for crate in crates %}
<div class="crate">
<span class="crate-name">
<a href="{{ crate.name }}/{{ crate.version }}/{{ crate.chip }}/{{ crate.package }}">
{{ crate.chip_pretty }}
</a>
</span>
<span class="crate-description">{{ crate.description }}</span>
<span class="crate-version">{{ crate.version }}</span>
</div>
{%- endfor %}
</div>
</body>
</html>

View File

@ -5,13 +5,15 @@ edition = "2021"
publish = false
[dependencies]
anyhow = "1.0.79"
anyhow = "1.0.81"
basic-toml = "0.1.9"
chrono = "0.4.35"
clap = { version = "4.5.0", features = ["derive"] }
clap = { version = "4.5.2", features = ["derive"] }
csv = "1.3.0"
env_logger = "0.11.1"
log = "0.4.20"
semver = "1.0.21"
env_logger = "0.11.3"
log = "0.4.21"
minijinja = "1.0.12"
semver = { version = "1.0.22", features = ["serde"] }
serde = { version = "1.0.197", features = ["derive"] }
strum = { version = "0.26.1", features = ["derive"] }
toml_edit = "0.22.5"
strum = { version = "0.26.2", features = ["derive"] }
toml_edit = "0.22.7"

View File

@ -25,7 +25,7 @@ pub enum Package {
Examples,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Display, EnumIter, ValueEnum)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Display, EnumIter, ValueEnum, serde::Serialize)]
#[strum(serialize_all = "kebab-case")]
pub enum Chip {
Esp32,
@ -369,7 +369,7 @@ pub fn bump_version(workspace: &Path, package: Package, amount: Version) -> Resu
let manifest_path = workspace.join(package.to_string()).join("Cargo.toml");
let manifest = fs::read_to_string(&manifest_path)?;
let mut manifest = manifest.parse::<toml_edit::Document>()?;
let mut manifest = manifest.parse::<toml_edit::DocumentMut>()?;
let version = manifest["package"]["version"]
.to_string()
@ -553,6 +553,27 @@ pub fn generate_efuse_table(
Ok(())
}
// ----------------------------------------------------------------------------
// Helper Functions
/// Parse the version from the specified package's Cargo manifest.
pub fn package_version(workspace: &Path, package: Package) -> Result<semver::Version> {
#[derive(Debug, serde::Deserialize)]
pub struct Manifest {
package: Package,
}
#[derive(Debug, serde::Deserialize)]
pub struct Package {
version: semver::Version,
}
let manifest = fs::read_to_string(workspace.join(package.to_string()).join("Cargo.toml"))?;
let manifest: Manifest = basic_toml::from_str(&manifest)?;
Ok(manifest.package.version)
}
/// Make the path "Windows"-safe
pub fn windows_safe_path(path: &Path) -> PathBuf {
PathBuf::from(path.to_str().unwrap().to_string().replace("\\\\?\\", ""))

View File

@ -29,18 +29,15 @@ enum Cli {
#[derive(Debug, Args)]
struct BuildDocumentationArgs {
/// Open the documentation in the default browser once built.
#[arg(long)]
open: bool,
/// Package to build documentation for.
#[arg(value_enum)]
package: Package,
/// Which chip to build the documentation for.
#[arg(value_enum)]
chip: Chip,
/// Open the documentation in the default browser once built.
#[arg(long)]
open: bool,
/// Directory in which to place the built documentation.
#[arg(long)]
output_path: Option<PathBuf>,
#[arg(value_enum, default_values_t = Chip::iter())]
chips: Vec<Chip>,
}
#[derive(Debug, Args)]
@ -125,34 +122,72 @@ fn main() -> Result<()> {
// Subcommands
fn build_documentation(workspace: &Path, args: BuildDocumentationArgs) -> Result<()> {
// Ensure that the package/chip combination provided are valid:
validate_package_chip(&args.package, &args.chip)?;
let output_path = workspace.join("docs");
let resources = workspace.join("resources");
// Determine the appropriate build target for the given package and chip:
let target = target_triple(&args.package, &args.chip)?;
let package = args.package.to_string();
let version = xtask::package_version(&workspace, args.package)?;
// Simply build the documentation for the specified package, targeting the
// specified chip:
xtask::build_documentation(workspace, args.package, args.chip, target, args.open)?;
let mut crates = Vec::new();
for chip in args.chips {
// Ensure that the package/chip combination provided are valid:
validate_package_chip(&args.package, &chip)?;
// Determine the appropriate build target for the given package and chip:
let target = target_triple(&args.package, &chip)?;
// Build the documentation for the specified package, targeting the
// specified chip:
xtask::build_documentation(workspace, args.package, chip, target, args.open)?;
// If an output path was specified, once the documentation has been built we
// will copy it to the provided path, creating any required directories in the
// process:
if let Some(output_path) = args.output_path {
let docs_path = xtask::windows_safe_path(
&workspace
.join(args.package.to_string())
.join(package.clone())
.join("target")
.join(target)
.join("doc"),
);
let output_path = output_path
.join(package.clone())
.join(version.to_string())
.join(chip.to_string());
let output_path = xtask::windows_safe_path(&output_path);
fs::create_dir_all(&output_path)?;
// Create the output directory, and copy the built documentation into it:
fs::create_dir_all(&output_path)?;
copy_dir_all(&docs_path, &output_path)?;
// Build the context object required for rendering this particular build's
// information on the documentation index:
crates.push(minijinja::context! {
name => package,
version => version,
chip => chip.to_string(),
chip_pretty => chip.pretty_name(),
package => package.replace('-', "_"),
description => format!("{} (targeting {})", package, chip.pretty_name()),
});
}
// Copy any additional assets to the documentation's output path:
fs::copy(
&resources.join("esp-rs.svg"),
&output_path.join("esp-rs.svg"),
)?;
// Render the index and write it out to the documentaiton's output path:
let source = fs::read_to_string(resources.join("index.html.jinja"))?;
let mut env = minijinja::Environment::new();
env.add_template("index", &source)?;
let tmpl = env.get_template("index")?;
let html = tmpl.render(minijinja::context! { crates => crates })?;
fs::write(output_path.join("index.html"), html)?;
Ok(())
}