Skip to content

Commit

Permalink
Provide a better error message for broken links in mdbook-spec
Browse files Browse the repository at this point in the history
  • Loading branch information
ehuss committed Jan 16, 2025
1 parent b06e1f3 commit dffcb0e
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 4 deletions.
15 changes: 15 additions & 0 deletions mdbook-spec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use once_cell::sync::Lazy;
use regex::{Captures, Regex};
use semver::{Version, VersionReq};
use std::io;
use std::ops::Range;
use std::path::PathBuf;

mod rules;
Expand Down Expand Up @@ -205,3 +206,17 @@ impl Preprocessor for Spec {
Ok(book)
}
}

fn line_from_range<'a>(contents: &'a str, range: &Range<usize>) -> &'a str {
assert!(range.start < contents.len());

let mut start_index = 0;
for line in contents.lines() {
let end_index = start_index + line.len();
if range.start >= start_index && range.start <= end_index {
return line;
}
start_index = end_index + 1;
}
panic!("did not find line {range:?} in contents");
}
19 changes: 15 additions & 4 deletions mdbook-spec/src/std_links.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ pub fn std_links(book: &mut Book) {
}
let key = ch.source_path.as_ref().unwrap();
// Create a list of replacements to make in the raw markdown to point to the new url.
let replacements = compute_replacements(&ch.content, &chapter_links[key], &ch_urls[key]);
let replacements = compute_replacements(&ch, &chapter_links[key], &ch_urls[key]);

let mut new_contents = ch.content.clone();
for (md_link, url, range) in replacements {
Expand Down Expand Up @@ -120,6 +120,9 @@ struct Link<'a> {
dest_url: CowStr<'a>,
/// The span in the original markdown where the link is located.
///
/// Note that this is the post-processed markdown (such as having rules
/// expanded), not the markdown on the disk.
///
/// Note that during translation, all links will be converted to inline
/// links. That means that for reference-style links, the link reference
/// definition will end up being ignored in the final markdown. For
Expand Down Expand Up @@ -288,19 +291,27 @@ fn relative_url(url: &str, chapter: &Chapter) -> String {
/// - `url` is the URL to the standard library.
/// - `range` is the range in the original markdown to replace with the new link.
fn compute_replacements<'a>(
contents: &'a str,
chapter: &'a Chapter,
links: &[Link<'_>],
urls: &[&'a str],
) -> Vec<(&'a str, &'a str, Range<usize>)> {
let mut replacements = Vec::new();

for (url, link) in urls.iter().zip(links) {
let Some(cap) = ANCHOR_URL.captures(url) else {
eprintln!("error: could not find anchor in:\n{url}\nlink={link:#?}");
let line = super::line_from_range(&chapter.content, &link.range);
eprintln!(
"error: broken markdown link found in {}\n\
Line is: {line}\n\
Link to `{}` could not be resolved by rustdoc to a known URL (result was `{}`).\n",
chapter.source_path.as_ref().unwrap().display(),
link.dest_url,
url
);
process::exit(1);
};
let url = cap.get(1).unwrap().as_str();
let md_link = &contents[link.range.clone()];
let md_link = &chapter.content[link.range.clone()];

let range = link.range.clone();
let add_link = |re: &Regex| {
Expand Down

0 comments on commit dffcb0e

Please sign in to comment.