various: markdown improvements
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I81fda8247814da19eed1e76dbe97bd5b6a6a6964
This commit is contained in:
parent
875bdf5ebc
commit
80a8b5c7ca
23 changed files with 3458 additions and 30 deletions
|
|
@ -154,6 +154,9 @@ pub struct MediaItem {
|
|||
|
||||
/// Soft delete timestamp. If set, the item is in the trash.
|
||||
pub deleted_at: Option<DateTime<Utc>>,
|
||||
|
||||
/// When markdown links were last extracted from this file.
|
||||
pub links_extracted_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
|
|
@ -486,3 +489,100 @@ impl fmt::Display for ReadingStatus {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===== Markdown Links (Obsidian-style) =====
|
||||
|
||||
/// Type of markdown link
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum LinkType {
|
||||
/// Wikilink: [[target]] or [[target|display]]
|
||||
Wikilink,
|
||||
/// Markdown link: [text](path)
|
||||
MarkdownLink,
|
||||
/// Embed: ![[target]]
|
||||
Embed,
|
||||
}
|
||||
|
||||
impl fmt::Display for LinkType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Wikilink => write!(f, "wikilink"),
|
||||
Self::MarkdownLink => write!(f, "markdown_link"),
|
||||
Self::Embed => write!(f, "embed"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for LinkType {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s.to_lowercase().as_str() {
|
||||
"wikilink" => Ok(Self::Wikilink),
|
||||
"markdown_link" => Ok(Self::MarkdownLink),
|
||||
"embed" => Ok(Self::Embed),
|
||||
_ => Err(format!("unknown link type: {}", s)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A markdown link extracted from a file
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct MarkdownLink {
|
||||
pub id: Uuid,
|
||||
pub source_media_id: MediaId,
|
||||
/// Raw link target as written in the source (wikilink name or path)
|
||||
pub target_path: String,
|
||||
/// Resolved target media_id (None if unresolved)
|
||||
pub target_media_id: Option<MediaId>,
|
||||
pub link_type: LinkType,
|
||||
/// Display text for the link
|
||||
pub link_text: Option<String>,
|
||||
/// Line number in source file (1-indexed)
|
||||
pub line_number: Option<i32>,
|
||||
/// Surrounding text for backlink preview
|
||||
pub context: Option<String>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
/// Information about a backlink (incoming link)
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct BacklinkInfo {
|
||||
pub link_id: Uuid,
|
||||
pub source_id: MediaId,
|
||||
pub source_title: Option<String>,
|
||||
pub source_path: String,
|
||||
pub link_text: Option<String>,
|
||||
pub line_number: Option<i32>,
|
||||
pub context: Option<String>,
|
||||
pub link_type: LinkType,
|
||||
}
|
||||
|
||||
/// Graph data for visualization
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
pub struct GraphData {
|
||||
pub nodes: Vec<GraphNode>,
|
||||
pub edges: Vec<GraphEdge>,
|
||||
}
|
||||
|
||||
/// A node in the graph visualization
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct GraphNode {
|
||||
pub id: String,
|
||||
pub label: String,
|
||||
pub title: Option<String>,
|
||||
pub media_type: String,
|
||||
/// Number of outgoing links from this node
|
||||
pub link_count: u32,
|
||||
/// Number of incoming links to this node
|
||||
pub backlink_count: u32,
|
||||
}
|
||||
|
||||
/// An edge (link) in the graph visualization
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct GraphEdge {
|
||||
pub source: String,
|
||||
pub target: String,
|
||||
pub link_type: LinkType,
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue