From 2eab7eaa99d0f876b67a87055cb54ddb28e31ff7 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Mon, 23 Dec 2024 13:34:21 +0100 Subject: [PATCH] fix(l10n): add sizes to fallback imgs --- crates/rari-doc/src/html/fix_img.rs | 125 +++++++++++++++++++++++++++ crates/rari-doc/src/html/mod.rs | 1 + crates/rari-doc/src/html/rewriter.rs | 94 +------------------- crates/rari-doc/src/pages/page.rs | 2 +- 4 files changed, 129 insertions(+), 93 deletions(-) create mode 100644 crates/rari-doc/src/html/fix_img.rs diff --git a/crates/rari-doc/src/html/fix_img.rs b/crates/rari-doc/src/html/fix_img.rs new file mode 100644 index 00000000..4ebd3cb4 --- /dev/null +++ b/crates/rari-doc/src/html/fix_img.rs @@ -0,0 +1,125 @@ +use std::error::Error; +use std::path::Path; + +use lol_html::html_content::Element; +use lol_html::HandlerResult; +use rari_types::locale::default_locale; +use tracing::warn; +use url::{ParseOptions, Url}; + +use crate::issues::get_issue_counter; +use crate::pages::page::{Page, PageLike}; + +type ImgSize = (Option, Option); + +pub fn handle_img( + el: &mut Element, + page: &impl PageLike, + data_issues: bool, + base: &Url, + base_url: &ParseOptions, +) -> HandlerResult { + // Leave dimensions alone if we have a `width` attribute + if el.get_attribute("width").is_some() { + return Ok(()); + } + if let Some(src) = el.get_attribute("src") { + let url = base_url.parse(&src)?; + if url.host() == base.host() && !url.path().starts_with("/assets/") { + el.set_attribute("src", url.path())?; + let mut file = page.full_path().parent().unwrap().join(&src); + if !file.try_exists().unwrap_or_default() { + if let Ok(en_us_page) = + Page::from_url_with_locale_and_fallback(page.url(), default_locale()) + { + file = en_us_page.full_path().parent().unwrap().join(&src); + } + } + let (width, height) = img_size(el, &src, &file, data_issues)?; + if let Some(width) = width { + el.set_attribute("width", &width)?; + } + if let Some(height) = height { + el.set_attribute("height", &height)?; + } + } + } + Ok(()) +} + +pub fn img_size( + el: &mut Element, + src: &str, + file: &Path, + data_issues: bool, +) -> Result> { + let (width, height) = if src.ends_with(".svg") { + match svg_metadata::Metadata::parse_file(file) { + // If only width and viewbox are given, use width and scale + // the height according to the viewbox size ratio. + // If width and height are given, use these. + // If only a viewbox is given, use the viewbox values. + // If only height and viewbox are given, use height and scale + // the height according to the viewbox size ratio. + Ok(meta) => { + let width = meta.width.map(|w| w.width); + let height = meta.height.map(|h| h.height); + let view_box = meta.view_box; + + let (final_width, final_height) = match (width, height, view_box) { + // Both width and height are given + (Some(w), Some(h), _) => (Some(w), Some(h)), + // Only width and viewbox are given + (Some(w), None, Some(vb)) => (Some(w), Some(w * vb.height / vb.width)), + // Only height and viewbox are given + (None, Some(h), Some(vb)) => (Some(h * vb.width / vb.height), Some(h)), + // Only viewbox is given + (None, None, Some(vb)) => (Some(vb.width), Some(vb.height)), + // Only width is given + (Some(w), None, None) => (Some(w), None), + // Only height is given + (None, Some(h), None) => (None, Some(h)), + // Neither width, height, nor viewbox are given + (None, None, None) => (None, None), + }; + + ( + final_width.map(|w| format!("{:.0}", w)), + final_height.map(|h| format!("{:.0}", h)), + ) + } + Err(e) => { + let ic = get_issue_counter(); + warn!( + source = "image-check", + ic = ic, + "Error parsing {}: {e}", + file.display() + ); + if data_issues { + el.set_attribute("data-flaw", &ic.to_string())?; + } + (None, None) + } + } + } else { + match imagesize::size(file) { + Ok(dim) => (Some(dim.width.to_string()), Some(dim.height.to_string())), + Err(e) => { + let ic = get_issue_counter(); + warn!( + source = "image-check", + ic = ic, + "Error opening {}: {e}", + file.display() + ); + if data_issues { + el.set_attribute("data-flaw", &ic.to_string())?; + } + + (None, None) + } + } + }; + Ok((width, height)) +} diff --git a/crates/rari-doc/src/html/mod.rs b/crates/rari-doc/src/html/mod.rs index 48ed1a9f..e6229871 100644 --- a/crates/rari-doc/src/html/mod.rs +++ b/crates/rari-doc/src/html/mod.rs @@ -1,4 +1,5 @@ pub mod bubble_up; +mod fix_img; mod fix_link; pub mod links; pub mod modifier; diff --git a/crates/rari-doc/src/html/rewriter.rs b/crates/rari-doc/src/html/rewriter.rs index 72a47dc2..7b62170d 100644 --- a/crates/rari-doc/src/html/rewriter.rs +++ b/crates/rari-doc/src/html/rewriter.rs @@ -8,12 +8,11 @@ use rari_md::node_card::NoteCard; use rari_types::fm_types::PageType; use rari_types::globals::settings; use rari_utils::concat_strs; -use tracing::warn; use url::Url; use crate::error::DocError; +use crate::html::fix_img::handle_img; use crate::html::fix_link::check_and_fix_link; -use crate::issues::get_issue_counter; use crate::pages::page::PageLike; use crate::pages::types::curriculum::CurriculumPage; @@ -88,96 +87,7 @@ pub fn post_process_html( Ok(()) }), element!("img[src]", |el| { - // Leave dimensions alone if we have a `width` attribute - if el.get_attribute("width").is_some() { - return Ok(()); - } - if let Some(src) = el.get_attribute("src") { - let url = base_url.parse(&src)?; - if url.host() == base.host() && !url.path().starts_with("/assets/") { - el.set_attribute("src", url.path())?; - let file = page.full_path().parent().unwrap().join(&src); - let (width, height) = if src.ends_with(".svg") { - match svg_metadata::Metadata::parse_file(&file) { - // If only width and viewbox are given, use width and scale - // the height according to the viewbox size ratio. - // If width and height are given, use these. - // If only a viewbox is given, use the viewbox values. - // If only height and viewbox are given, use height and scale - // the height according to the viewbox size ratio. - Ok(meta) => { - let width = meta.width.map(|w| w.width); - let height = meta.height.map(|h| h.height); - let view_box = meta.view_box; - - let (final_width, final_height) = match (width, height, view_box) { - // Both width and height are given - (Some(w), Some(h), _) => (Some(w), Some(h)), - // Only width and viewbox are given - (Some(w), None, Some(vb)) => { - (Some(w), Some(w * vb.height / vb.width)) - } - // Only height and viewbox are given - (None, Some(h), Some(vb)) => { - (Some(h * vb.width / vb.height), Some(h)) - } - // Only viewbox is given - (None, None, Some(vb)) => (Some(vb.width), Some(vb.height)), - // Only width is given - (Some(w), None, None) => (Some(w), None), - // Only height is given - (None, Some(h), None) => (None, Some(h)), - // Neither width, height, nor viewbox are given - (None, None, None) => (None, None), - }; - - ( - final_width.map(|w| format!("{:.0}", w)), - final_height.map(|h| format!("{:.0}", h)), - ) - } - Err(e) => { - let ic = get_issue_counter(); - warn!( - source = "image-check", - ic = ic, - "Error parsing {}: {e}", - file.display() - ); - if data_issues { - el.set_attribute("data-flaw", &ic.to_string())?; - } - (None, None) - } - } - } else { - match imagesize::size(&file) { - Ok(dim) => (Some(dim.width.to_string()), Some(dim.height.to_string())), - Err(e) => { - let ic = get_issue_counter(); - warn!( - source = "image-check", - ic = ic, - "Error opening {}: {e}", - file.display() - ); - if data_issues { - el.set_attribute("data-flaw", &ic.to_string())?; - } - - (None, None) - } - } - }; - if let Some(width) = width { - el.set_attribute("width", &width)?; - } - if let Some(height) = height { - el.set_attribute("height", &height)?; - } - } - } - Ok(()) + handle_img(el, page, data_issues, &base, &base_url) }), element!("img:not([loading])", |el| { el.set_attribute("loading", "lazy")?; diff --git a/crates/rari-doc/src/pages/page.rs b/crates/rari-doc/src/pages/page.rs index f93ee190..3fc05214 100644 --- a/crates/rari-doc/src/pages/page.rs +++ b/crates/rari-doc/src/pages/page.rs @@ -95,7 +95,7 @@ impl Page { Self::internal_from_url(url, Some(locale), true) } - fn internal_from_url( + pub fn internal_from_url( url: &str, locale: Option, fallback: bool,