iris_reader/renderer/
mod.rs1pub mod markdown;
2pub mod text;
3
4use std::path::Path;
5
6use ratatui::text::Line;
7
8use crate::{
9 image::ImageManager,
10 input::{Input, InputKind},
11 search::{SearchMatch, SearchMatcher},
12 theme::Theme,
13};
14
15pub type NodeId = usize;
16pub type HeadingId = NodeId;
17
18#[derive(Debug, Clone)]
19pub struct RenderedLine {
20 pub line: Line<'static>,
21 pub plain: String,
22 pub source_id: Option<NodeId>,
23}
24
25impl RenderedLine {
26 pub fn empty() -> Self {
27 Self {
28 line: Line::default(),
29 plain: String::new(),
30 source_id: None,
31 }
32 }
33}
34
35#[derive(Debug, Clone)]
36pub struct RenderedHeading {
37 pub id: HeadingId,
38 pub level: u8,
39 pub title: String,
40 pub slug: String,
41 pub line: usize,
42}
43
44#[derive(Debug, Clone)]
45pub struct RenderedLink {
46 pub source_id: NodeId,
47 pub destination: String,
48 pub line: usize,
49 pub start_column: usize,
50 pub end_column: usize,
51}
52
53#[derive(Debug, Clone)]
54pub struct RenderedImage {
55 pub source_id: NodeId,
56 pub source: String,
57 pub alt: String,
58 pub destination: Option<String>,
59 pub line: usize,
60 pub column: usize,
61 pub height: u16,
62}
63
64#[derive(Debug, Clone, Default)]
65pub struct RenderedDocument {
66 pub lines: Vec<RenderedLine>,
67 pub headings: Vec<RenderedHeading>,
68 pub links: Vec<RenderedLink>,
69 pub images: Vec<RenderedImage>,
70 pub max_width: usize,
71}
72
73impl RenderedDocument {
74 pub fn finish(mut self) -> Self {
75 self.max_width = self
76 .lines
77 .iter()
78 .map(|line| unicode_width::UnicodeWidthStr::width(line.plain.as_str()))
79 .max()
80 .unwrap_or(0);
81 self
82 }
83}
84
85pub enum ViewDocument {
86 Text(text::TextDocument),
87 Markdown(markdown::Document),
88}
89
90impl ViewDocument {
91 pub fn from_input(input: &Input) -> Self {
92 match input.kind {
93 InputKind::Text => Self::Text(text::TextDocument::new(&input.content)),
94 InputKind::Markdown => Self::Markdown(markdown::parse(&input.content)),
95 }
96 }
97
98 pub fn render(
99 &self,
100 width: u16,
101 theme: &Theme,
102 wrap: bool,
103 tab_width: usize,
104 images: &mut ImageManager,
105 base_dir: Option<&Path>,
106 ) -> RenderedDocument {
107 match self {
108 Self::Text(document) => text::render(document, width, theme, wrap, tab_width),
109 Self::Markdown(document) => {
110 markdown::render(document, width, theme, wrap, tab_width, images, base_dir)
111 }
112 }
113 }
114
115 pub fn search(&self, matcher: &SearchMatcher) -> Vec<SearchMatch> {
116 match self {
117 Self::Text(document) => document.search(matcher),
118 Self::Markdown(document) => document.search(matcher),
119 }
120 }
121
122 pub fn is_markdown(&self) -> bool {
123 matches!(self, Self::Markdown(_))
124 }
125}