Skip to content

Commit 351ff6f

Browse files
committed
chore: reuse regexes
1 parent 95fa0a8 commit 351ff6f

1 file changed

Lines changed: 38 additions & 9 deletions

File tree

src/core.rs

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use serde_json::{Value, json};
77
use std::collections::HashMap;
88
use std::path::{Path, PathBuf};
99
use std::sync::Arc;
10+
use std::sync::LazyLock;
1011
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
1112
use time::OffsetDateTime;
1213
use time::format_description::well_known::Rfc3339;
@@ -414,7 +415,7 @@ async fn localize_figures(
414415
}
415416
}
416417

417-
let rewritten = replace_image_urls(&markdown, &replacements)?;
418+
let rewritten = replace_image_urls(&markdown, &replacements);
418419
Ok((
419420
rewritten,
420421
downloaded_figures,
@@ -582,11 +583,16 @@ fn url_suffix(url: &str) -> Option<String> {
582583
Some(format!(".{ext}"))
583584
}
584585

585-
fn replace_image_urls(markdown: &str, replacements: &HashMap<String, String>) -> Result<String> {
586-
let markdown_pattern = Regex::new(r"\((https?://[^)\s]+)\)")?;
587-
let html_pattern = Regex::new(r#"(src\s*=\s*)(['"])(https?://[^'"]+)(['"])"#)?;
586+
static MARKDOWN_IMAGE_URL_PATTERN: LazyLock<Regex> = LazyLock::new(|| {
587+
Regex::new(r"\((https?://[^)\s]+)\)").expect("valid markdown image URL regex")
588+
});
588589

589-
let updated = markdown_pattern
590+
static HTML_IMAGE_URL_PATTERN: LazyLock<Regex> = LazyLock::new(|| {
591+
Regex::new(r#"(src\s*=\s*)(['"])(https?://[^'"]+)(['"])"#).expect("valid HTML image URL regex")
592+
});
593+
594+
fn replace_image_urls(markdown: &str, replacements: &HashMap<String, String>) -> String {
595+
let updated = MARKDOWN_IMAGE_URL_PATTERN
590596
.replace_all(markdown, |caps: &regex::Captures<'_>| {
591597
let remote_url = caps.get(1).map(|m| m.as_str()).unwrap_or_default();
592598
let replacement = replacements
@@ -597,7 +603,7 @@ fn replace_image_urls(markdown: &str, replacements: &HashMap<String, String>) ->
597603
})
598604
.into_owned();
599605

600-
Ok(html_pattern
606+
HTML_IMAGE_URL_PATTERN
601607
.replace_all(&updated, |caps: &regex::Captures<'_>| {
602608
let prefix = caps.get(1).map(|m| m.as_str()).unwrap_or_default();
603609
let quote = caps.get(2).map(|m| m.as_str()).unwrap_or("\"");
@@ -609,7 +615,7 @@ fn replace_image_urls(markdown: &str, replacements: &HashMap<String, String>) ->
609615
.unwrap_or_else(|| remote_url.to_string());
610616
format!("{prefix}{quote}{replacement}{suffix}")
611617
})
612-
.into_owned())
618+
.into_owned()
613619
}
614620

615621
async fn append_log(log_path: &Path, entry: Value) -> Result<()> {
@@ -1211,7 +1217,7 @@ mod tests {
12111217
"https://x/fig.png".to_string(),
12121218
"figures/f1.png".to_string(),
12131219
);
1214-
let updated = replace_image_urls(markdown, &replacements).unwrap();
1220+
let updated = replace_image_urls(markdown, &replacements);
12151221
assert!(updated.contains("![](figures/f1.png)"));
12161222
assert!(updated.contains("![](https://x/fig.png?v=1)"));
12171223
}
@@ -1224,10 +1230,33 @@ mod tests {
12241230
"https://x/fig.png".to_string(),
12251231
"figures/f1.png".to_string(),
12261232
);
1227-
let updated = replace_image_urls(markdown, &replacements).unwrap();
1233+
let updated = replace_image_urls(markdown, &replacements);
12281234
assert_eq!(updated, "<img src='figures/f1.png' alt='x'/>");
12291235
}
12301236

1237+
#[test]
1238+
fn replace_image_urls_mixed_markdown_and_html() {
1239+
let markdown = "start ![](https://x/a.png) mid <img src=\"https://x/b.jpg\" alt='x'/> end ![](https://x/c.png?query=1)";
1240+
let mut replacements = HashMap::new();
1241+
replacements.insert("https://x/a.png".to_string(), "figures/a.png".to_string());
1242+
replacements.insert("https://x/b.jpg".to_string(), "figures/b.jpg".to_string());
1243+
1244+
let updated = replace_image_urls(markdown, &replacements);
1245+
assert_eq!(
1246+
updated,
1247+
"start ![](figures/a.png) mid <img src=\"figures/b.jpg\" alt='x'/> end ![](https://x/c.png?query=1)"
1248+
);
1249+
}
1250+
1251+
#[test]
1252+
fn replace_image_urls_no_replacements_passthrough() {
1253+
let markdown = "plain text ![](https://x/a.png) <img src='https://x/b.jpg' alt='x'/>";
1254+
let replacements = HashMap::new();
1255+
1256+
let updated = replace_image_urls(markdown, &replacements);
1257+
assert_eq!(updated, markdown);
1258+
}
1259+
12311260
#[test]
12321261
fn prepare_output_without_overwrite_fails_on_existing_managed_artifacts() {
12331262
let tmp = TempDir::new().unwrap();

0 commit comments

Comments
 (0)