Skip to content

Commit

Permalink
feat(issues): issues for ill cased links (#115)
Browse files Browse the repository at this point in the history
* feat(issues): issues for ill cased links

Also fix casing in sidebars via fmt-sidebars

* improve redirects
  • Loading branch information
fiji-flo authored Feb 3, 2025
1 parent 85692ec commit d8b6c2b
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 71 deletions.
17 changes: 15 additions & 2 deletions crates/rari-doc/src/html/fix_link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,15 @@ pub fn handle_internal_link(
url = original_href,
);
} else {
let source = if original_href.to_lowercase()
== resolved_href.to_lowercase()
{
"ill-cased-link"
} else {
"redirected-link"
};
tracing::warn!(
source = "redirected-link",
source = source,
ic = ic,
line = line,
col = col,
Expand All @@ -181,8 +188,14 @@ pub fn handle_internal_link(
if remove_href {
tracing::warn!(source = "broken-link", ic = ic, url = original_href);
} else {
let source = if original_href.to_lowercase() == resolved_href.to_lowercase()
{
"ill-cased-link"
} else {
"redirected-link"
};
tracing::warn!(
source = "redirected-link",
source = source,
ic = ic,
url = original_href,
redirect = resolved_href
Expand Down
10 changes: 10 additions & 0 deletions crates/rari-doc/src/html/links.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use rari_types::locale::Locale;
use rari_utils::concat_strs;

use crate::error::DocError;
use crate::issues::get_issue_counter;
use crate::pages::page::{Page, PageLike};
use crate::resolve::locale_from_url;
use crate::templ::api::RariApi;
Expand Down Expand Up @@ -102,6 +103,15 @@ pub fn render_link_via_page(
}
let (url, anchor) = url.split_once('#').unwrap_or((&url, ""));
if let Ok(page) = RariApi::get_page(url) {
if url != page.url() && url.to_lowercase() == page.url().to_lowercase() {
let ic = get_issue_counter();
tracing::warn!(
source = "ill-cased-link",
ic = ic,
url = url,
redirect = page.url()
);
}
let url = page.url();
let content = if let Some(content) = content {
Cow::Borrowed(content)
Expand Down
14 changes: 14 additions & 0 deletions crates/rari-doc/src/issues.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ pub enum IssueType {
TemplBrokenLink,
RedirectedLink,
BrokenLink,
IllCasedLink,
#[default]
Unknown,
}
Expand All @@ -217,6 +218,7 @@ impl FromStr for IssueType {
"templ-broken-link" => Self::TemplBrokenLink,
"redirected-link" => Self::RedirectedLink,
"broken-link" => Self::BrokenLink,
"ill-cased-link" => Self::IllCasedLink,
_ => Self::Unknown,
})
}
Expand Down Expand Up @@ -309,6 +311,18 @@ impl DIssue {
}
}
match di.name {
IssueType::IllCasedLink => {
di.fixed = false;
di.fixable = Some(true);
di.explanation = Some(format!(
"{} is ill cased",
additional.get("url").map(|s| s.as_str()).unwrap_or("?")
));
DIssue::BrokenLink {
display_issue: di,
href: additional.remove("url"),
}
}
IssueType::RedirectedLink => {
di.fixed = false;
di.fixable = Some(true);
Expand Down
58 changes: 37 additions & 21 deletions crates/rari-doc/src/redirects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use rari_utils::error::RariIoError;
use tracing::error;

use crate::error::DocError;
use crate::pages::page::{Page, PageLike};

static REDIRECTS: LazyLock<HashMap<String, String>> = LazyLock::new(|| {
let mut map = HashMap::new();
Expand Down Expand Up @@ -90,33 +91,48 @@ where
Ok(io::BufReader::new(file).lines())
}

/// Resolves a URL redirect based on the configured redirects.
/// Resolves a given URL to a redirect URL if one exists.
///
/// This function attempts to resolve a redirect for the given URL by looking it up in the `REDIRECTS` hashmap.
/// If a redirect is found, it returns the target URL, optionally appending any hash fragment from the original URL.
/// If no redirect is found, it returns `None`.
/// Takes a URL string as input and returns an Option containing either:
/// - A `Cow<str>` with the redirect URL if a redirect exists
/// - None if no redirect is found
///
/// # Arguments
///
/// * `url` - A string slice that holds the URL to be resolved.
///
/// # Returns
///
/// * `Option<Cow<'_, str>>` - Returns `Some(Cow::Borrowed(target_url))` if a redirect is found and the target URL
/// does not contain a hash fragment, or `Some(Cow::Owned(format!("{target_url}{hash}")))` if the target URL
/// contains a hash fragment or the original URL has a hash fragment. Returns `None` if no redirect is found.
pub(crate) fn resolve_redirect<'a>(url: impl AsRef<str>) -> Option<Cow<'a, str>> {
/// The function handles hash fragments in URLs and preserves them in the redirect.
/// It also normalizes URLs and can resolve both explicit redirects from the redirects file
/// as well as implicit redirects based on page URL normalization.
pub fn resolve_redirect<'a>(url: impl AsRef<str>) -> Option<Cow<'a, str>> {
let url = url.as_ref();
let hash_index = url.find('#').unwrap_or(url.len());
let (url_no_hash, hash) = (&url[..hash_index], &url[hash_index..]);
match (
REDIRECTS
.get(&url_no_hash.to_lowercase())
.map(|s| s.as_str()),
hash,
) {
let redirect = match REDIRECTS
.get(&url_no_hash.to_lowercase())
.map(|s| s.as_str())
{
Some(redirect) if redirect.starts_with("/") => Some(
Page::from_url(redirect)
.ok()
.and_then(|page| {
if url != page.url() {
Some(Cow::Owned(page.url().to_string()))
} else {
None
}
})
.unwrap_or(Cow::Borrowed(redirect)),
),
Some(redirect) => Some(Cow::Borrowed(redirect)),
None if url.starts_with("/") => Page::from_url(url).ok().and_then(|page| {
if url != page.url() {
Some(Cow::Owned(page.url().to_string()))
} else {
None
}
}),
None => None,
};
match (redirect, hash) {
(None, _) => None,
(Some(url), hash) if url.contains('#') || hash.is_empty() => Some(Cow::Borrowed(url)),
(Some(url), hash) if url.contains('#') || hash.is_empty() => Some(url),
(Some(url), hash) => Some(Cow::Owned(format!("{url}{hash}"))),
}
}
Loading

0 comments on commit d8b6c2b

Please sign in to comment.