Skip to content

Commit 1514365

Browse files
committed
Ensure release posts have a releases/... alias
1 parent 6d240cd commit 1514365

File tree

1 file changed

+16
-2
lines changed

1 file changed

+16
-2
lines changed

front_matter/src/lib.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ pub struct FrontMatter {
2828
#[serde(default)]
2929
pub authors: Vec<String>,
3030
pub description: Option<String>,
31-
/// Used to generate redirects from the old URL scheme to preserve
32-
/// permalinks.
31+
/// Used for `releases/X.XX.X` redirects and ones from the old URL scheme to
32+
/// preserve permalinks (e.g. slug.html => slug/).
3333
#[serde(default)]
3434
pub aliases: Vec<String>,
3535
/// Moved to the `extra` table.
@@ -113,12 +113,26 @@ pub fn normalize(
113113
bail!("extra.team and extra.team_url must always come in a pair");
114114
}
115115

116+
if front_matter.extra.release && !front_matter.aliases.iter().any(|a| a.contains("releases")) {
117+
// Make sure release posts have a matching `releases/X.XX.X` alias.
118+
let version = guess_version_from_path(&front_matter.path).unwrap_or("?.??.?".into());
119+
front_matter.aliases.push(format!("releases/{version}"));
120+
}
121+
116122
let serialized = toml::to_string_pretty(&front_matter)?;
117123
let deserialized = toml::from_str(&serialized)?;
118124

119125
Ok(deserialized)
120126
}
121127

128+
fn guess_version_from_path(path: &str) -> Option<String> {
129+
let mut iter = path.split(['-', '.']).filter_map(|s| s.parse::<u32>().ok());
130+
let major = iter.next()?;
131+
let minor = iter.next()?;
132+
let patch = iter.next().unwrap_or(0); // some posts omit the patch version
133+
Some(format!("{major}.{minor}.{patch}"))
134+
}
135+
122136
#[cfg(test)]
123137
mod tests {
124138
use std::{env, fs, path::PathBuf};

0 commit comments

Comments
 (0)