22//!
33//! IPC-kommandoer som kan kalles fra frontend.
44
5+ use crate :: fetcher:: { self , Fetcher } ;
56use crate :: markdown;
67use serde:: { Deserialize , Serialize } ;
78use std:: fs;
89use std:: path:: PathBuf ;
10+ use std:: sync:: LazyLock ;
11+
12+ /// Global HTTP-klient (gjenbrukes for alle forespørsler)
13+ static FETCHER : LazyLock < Fetcher > = LazyLock :: new ( Fetcher :: new) ;
914
1015/// Resultat fra markdown-rendering
1116#[ derive( Debug , Clone , Serialize , Deserialize ) ]
@@ -14,6 +19,12 @@ pub struct RenderedPage {
1419 pub html : String ,
1520 /// Tittel ekstrahert fra markdown (hvis funnet)
1621 pub title : Option < String > ,
22+ /// URL-en som ble brukt (etter eventuelle redirects)
23+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
24+ pub url : Option < String > ,
25+ /// Om innholdet ble hentet fra nettverket
26+ #[ serde( default ) ]
27+ pub is_remote : bool ,
1728}
1829
1930/// Rendrer markdown-tekst til HTML
@@ -28,7 +39,12 @@ pub fn render_markdown(content: String) -> RenderedPage {
2839 let html = markdown:: render ( & content) ;
2940 let title = markdown:: extract_title ( & content) ;
3041
31- RenderedPage { html, title }
42+ RenderedPage {
43+ html,
44+ title,
45+ url : None ,
46+ is_remote : false ,
47+ }
3248}
3349
3450/// Åpner og leser en lokal markdown-fil
@@ -62,7 +78,56 @@ pub fn open_file(path: String) -> Result<RenderedPage, String> {
6278 let html = markdown:: render ( & content) ;
6379 let title = markdown:: extract_title ( & content) ;
6480
65- Ok ( RenderedPage { html, title } )
81+ Ok ( RenderedPage {
82+ html,
83+ title,
84+ url : Some ( format ! ( "file://{}" , path. display( ) ) ) ,
85+ is_remote : false ,
86+ } )
87+ }
88+
89+ /// Henter og rendrer markdown fra en URL
90+ ///
91+ /// # Arguments
92+ /// * `url` - URL til markdown-filen som skal hentes
93+ ///
94+ /// # Returns
95+ /// RenderedPage med HTML og tittel, eller feilmelding
96+ #[ tauri:: command]
97+ pub async fn fetch_url ( url : String ) -> Result < RenderedPage , String > {
98+ let result = FETCHER . fetch ( & url) . await . map_err ( |e| e. to_string ( ) ) ?;
99+
100+ if !result. is_markdown {
101+ // For nå, returner en feilmelding for ikke-markdown innhold
102+ // I Fase 3 vil vi konvertere HTML til markdown
103+ return Err ( format ! (
104+ "Innholdet er ikke markdown (Content-Type: {:?}). HTML-konvertering kommer i en fremtidig versjon." ,
105+ result. content_type
106+ ) ) ;
107+ }
108+
109+ let html = markdown:: render ( & result. content ) ;
110+ let title = markdown:: extract_title ( & result. content ) ;
111+
112+ Ok ( RenderedPage {
113+ html,
114+ title,
115+ url : Some ( result. final_url ) ,
116+ is_remote : true ,
117+ } )
118+ }
119+
120+ /// Løser en relativ URL mot en base-URL
121+ ///
122+ /// # Arguments
123+ /// * `base_url` - Nåværende side sin URL
124+ /// * `relative_url` - Relativ URL som skal løses
125+ ///
126+ /// # Returns
127+ /// Absolutt URL
128+ #[ tauri:: command]
129+ pub fn resolve_url ( base_url : String , relative_url : String ) -> Result < String , String > {
130+ fetcher:: resolve_url ( & base_url, & relative_url) . map_err ( |e| e. to_string ( ) )
66131}
67132
68133/// Returnerer velkomst-innhold for når appen starter
@@ -136,7 +201,12 @@ fn main() {
136201 let html = markdown:: render ( welcome_md) ;
137202 let title = markdown:: extract_title ( welcome_md) ;
138203
139- RenderedPage { html, title }
204+ RenderedPage {
205+ html,
206+ title,
207+ url : None ,
208+ is_remote : false ,
209+ }
140210}
141211
142212#[ cfg( test) ]
@@ -148,12 +218,23 @@ mod tests {
148218 let result = render_markdown ( "# Test" . to_string ( ) ) ;
149219 assert ! ( result. html. contains( "<h1>" ) ) ;
150220 assert_eq ! ( result. title, Some ( "Test" . to_string( ) ) ) ;
221+ assert ! ( !result. is_remote) ;
151222 }
152223
153224 #[ test]
154225 fn test_get_welcome_content ( ) {
155226 let result = get_welcome_content ( ) ;
156227 assert ! ( result. html. contains( "Velkommen til Bare" ) ) ;
157228 assert ! ( result. title. is_some( ) ) ;
229+ assert ! ( !result. is_remote) ;
230+ }
231+
232+ #[ test]
233+ fn test_resolve_url_command ( ) {
234+ let result = resolve_url (
235+ "https://example.com/docs/readme.md" . to_string ( ) ,
236+ "other.md" . to_string ( ) ,
237+ ) ;
238+ assert_eq ! ( result. unwrap( ) , "https://example.com/docs/other.md" ) ;
158239 }
159240}
0 commit comments