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:
parent
1fe2c7998d
commit
b8ff35acea
12 changed files with 514 additions and 239 deletions
|
|
@ -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: 
|
||||
|
|
@ -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://")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue