···66#[derive(Debug, Default, Clone, thiserror::Error)]
77pub enum LinkStatus {
88 #[default]
99- #[error("link is ignored as it is not supported")]
99+ #[error("links ignored")]
1010 Ignored,
11111212 // "published" as in published with the book
1313- #[error("link to book page or file")]
1313+ #[error("linking to book page or file")]
1414 Published,
15151616- #[error("link to book page or file rewritten as path")]
1616+ #[error("linking to book page or file, rewritten as paths")]
1717 Rewritten,
1818- #[error("link converted to permalink")]
1818+ #[error("links converted to permalinks")]
1919 Permalink,
20202121- #[error("path to a file outside source control")]
2121+ #[error("paths outside of repository")]
2222 PathNotCheckedIn,
2323- #[error("file does not exist at path")]
2323+ #[error("paths inaccessible")]
2424 NoSuchPath(Vec<Url>),
25252626- #[error("error generating a link: {0}")]
2626+ #[error("error encountered: {0}")]
2727 Error(String),
2828}
2929
+9-11
crates/mdbook-permalinks/src/main.rs
···207207impl Resolver<'_, '_> {
208208 fn resolve(self) {
209209 if let Some(book) = &self.env.config.book_url {
210210- if let Some(path) = book.0.make_relative(&self.file_url) {
210210+ if let Some(path) = book.0.make_relative(&self.file_url)
211211+ && !path.starts_with("../")
212212+ {
211213 self.resolve_book(path)
212214 } else {
213215 self.resolve_file()
···253255 };
254256255257 if relative_to_repo.starts_with("../") {
256256- // `path` could also be a symlink to a file outside source control somehow
257257- // in which case it would NOT be marked as LinkStatus::External;
258258 link.status = LinkStatus::PathNotCheckedIn;
259259 return;
260260 }
···265265 .tap_err(log_debug!());
266266267267 if !matches!(exists, Ok(true)) {
268268- link.status = LinkStatus::NoSuchPath(vec![]);
268268+ link.status = LinkStatus::NoSuchPath(vec![file_url]);
269269 return;
270270 }
271271···320320321321 let path = {
322322 let mut path = path;
323323- if let Some(idx) = path.rfind('#') {
323323+ if let Some(idx) = path.find('#') {
324324 path.truncate(idx)
325325 };
326326- if let Some(idx) = path.rfind('?') {
326326+ if let Some(idx) = path.find('?') {
327327 path.truncate(idx)
328328 };
329329 path.strip_suffix(".html")
···358358 ]
359359 };
360360361361- let mut not_found = None;
361361+ let mut not_found = vec![];
362362363363 for file in try_files {
364364 let Ok(file) = self.env.book_src.join(file).tap_err(log_debug!()) else {
···388388 return;
389389 }
390390391391- not_found.get_or_insert(file);
391391+ not_found.push(file);
392392 }
393393394394- if let Some(file) = not_found {
395395- link.status = LinkStatus::NoSuchPath(vec![]);
396396- }
394394+ link.status = LinkStatus::NoSuchPath(not_found);
397395 }
398396}
399397
···11-Minato City, Tokyo, Japan.jpg, David Kernan, CC BY 4.0 <https://creativecommons.org/licenses/by/4.0>, via Wikimedia Commons, <https://commons.wikimedia.org/wiki/File:Minato_City,_Tokyo,_Japan.jpg>
11+Minato City,_Tokyo,_Japan.jpg, David Kernan, CC BY 4.0 <https://creativecommons.org/licenses/by/4.0>, via Wikimedia Commons, <https://commons.wikimedia.org/wiki/File:Minato_City,_Tokyo,_Japan.jpg>
···11+---
22+source: crates/mdbook-permalinks/src/tests.rs
33+assertion_line: 61
44+expression: output
55+---
66+# URLs to book
77+88+[]()
99+1010+[]()
1111+1212+[](trailing-slash/index.md)
1313+1414+[](trailing-slash/index.md)
1515+1616+
1717+1818+# URLs to HEAD
1919+2020+[](https://example.org/git/tree/v0.0/LICENSE-APACHE.md)
2121+2222+[](https://example.org/git/tree/v0.0/Cargo.toml#L8-9)
2323+2424+
2525+2626+# not found
2727+2828+[](https://example.org/book/tests/urls/)
2929+3030+[](https://example.org/book/tests/url)
3131+3232+[](https://example.org/git/tree/HEAD/LICENSE-GPL.md)
3333+3434+# not applicable
3535+3636+[](https://example.org/boo)
3737+3838+[](https://example.org/git)
···11+# URLs to book
22+33+[](https://example.org/book/tests/urls)
44+55+[](https://example.org/book/tests/urls.html)
66+77+[](https://example.org/book/tests/trailing-slash)
88+99+[](https://example.org/book/tests/trailing-slash/)
1010+1111+
1212+1313+# URLs to HEAD
1414+1515+[](https://example.org/git/tree/HEAD/LICENSE-APACHE.md)
1616+1717+[](https://example.org/git/tree/HEAD/Cargo.toml#L8-9)
1818+1919+
2020+2121+# not found
2222+2323+[](https://example.org/book/tests/urls/)
2424+2525+[](https://example.org/book/tests/url)
2626+2727+[](https://example.org/git/tree/HEAD/LICENSE-GPL.md)
2828+2929+# not applicable
3030+3131+[](https://example.org/boo)
3232+3333+[](https://example.org/git)