various: inherit workspace lints in all crates; eliminate unwrap()

throughout

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Id8de9d65139ec4cf4cdeaee14c8c95b06a6a6964
This commit is contained in:
raf 2026-03-07 16:55:43 +03:00
commit b8ff35acea
Signed by: NotAShelf
GPG key ID: 29D95B64378DB4BF
12 changed files with 514 additions and 239 deletions

View file

@ -8,13 +8,26 @@
//! - Link resolution strategies
//! - Context extraction for backlink previews
use std::path::Path;
use std::{path::Path, sync::LazyLock};
use regex::Regex;
use uuid::Uuid;
use crate::model::{LinkType, MarkdownLink, MediaId};
// Compile regexes once at startup to avoid recompilation on every call
static WIKILINK_RE: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(r"\[\[([^\]|]+)(?:\|([^\]]+))?\]\]").expect("valid wikilink regex")
});
static EMBED_RE: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(r"!\[\[([^\]|]+)(?:\|([^\]]+))?\]\]").expect("valid embed regex")
});
static MARKDOWN_LINK_RE: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(r"\[([^\]]+)\]\(([^)]+)\)").expect("valid markdown link regex")
});
/// Configuration for context extraction around links
const CONTEXT_CHARS_BEFORE: usize = 50;
const CONTEXT_CHARS_AFTER: usize = 50;
@ -50,13 +63,13 @@ fn extract_wikilinks(
source_media_id: MediaId,
content: &str,
) -> Vec<MarkdownLink> {
// Match [[...]] - we'll manually filter out embeds that are preceded by !
let re = Regex::new(r"\[\[([^\]|]+)(?:\|([^\]]+))?\]\]").unwrap();
let mut links = Vec::new();
for (line_num, line) in content.lines().enumerate() {
for cap in re.captures_iter(line) {
let full_match = cap.get(0).unwrap();
for cap in WIKILINK_RE.captures_iter(line) {
let Some(full_match) = cap.get(0) else {
continue;
};
let match_start = full_match.start();
// Check if preceded by ! (which would make it an embed, not a wikilink)
@ -67,7 +80,10 @@ fn extract_wikilinks(
}
}
let target = cap.get(1).unwrap().as_str().trim();
let Some(target_match) = cap.get(1) else {
continue;
};
let target = target_match.as_str().trim();
let display_text = cap.get(2).map(|m| m.as_str().trim().to_string());
let context = extract_context(
@ -100,13 +116,17 @@ fn extract_embeds(
source_media_id: MediaId,
content: &str,
) -> Vec<MarkdownLink> {
let re = Regex::new(r"!\[\[([^\]|]+)(?:\|([^\]]+))?\]\]").unwrap();
let mut links = Vec::new();
for (line_num, line) in content.lines().enumerate() {
for cap in re.captures_iter(line) {
let full_match = cap.get(0).unwrap();
let target = cap.get(1).unwrap().as_str().trim();
for cap in EMBED_RE.captures_iter(line) {
let Some(full_match) = cap.get(0) else {
continue;
};
let Some(target_match) = cap.get(1) else {
continue;
};
let target = target_match.as_str().trim();
let display_text = cap.get(2).map(|m| m.as_str().trim().to_string());
let context = extract_context(
@ -139,13 +159,13 @@ fn extract_markdown_links(
source_media_id: MediaId,
content: &str,
) -> Vec<MarkdownLink> {
// Match [text](path) where path doesn't start with http:// or https://
let re = Regex::new(r"\[([^\]]+)\]\(([^)]+)\)").unwrap();
let mut links = Vec::new();
for (line_num, line) in content.lines().enumerate() {
for cap in re.captures_iter(line) {
let full_match = cap.get(0).unwrap();
for cap in MARKDOWN_LINK_RE.captures_iter(line) {
let Some(full_match) = cap.get(0) else {
continue;
};
let match_start = full_match.start();
// Skip markdown images: ![alt](image.png)
@ -155,8 +175,14 @@ fn extract_markdown_links(
continue;
}
let text = cap.get(1).unwrap().as_str().trim();
let path = cap.get(2).unwrap().as_str().trim();
let Some(text_match) = cap.get(1) else {
continue;
};
let Some(path_match) = cap.get(2) else {
continue;
};
let text = text_match.as_str().trim();
let path = path_match.as_str().trim();
// Skip external links
if path.starts_with("http://")