1- use std:: collections:: HashMap ;
2-
31use anyhow:: { Context , Result } ;
42use arc_swap:: ArcSwap ;
53use data_encoding:: BASE64 ;
64use foldhash:: HashSet ;
75use serde:: Serialize ;
86use tera:: Tera ;
9- use wordbase_api:: { DictionaryId , Record , RecordEntry , RecordId , RecordKind , Term , dict} ;
7+ use wordbase_api:: { DictionaryId , Record , RecordEntry , RecordKind , Term , dict} ;
108
119use crate :: { Engine , IndexMap , lang} ;
1210
@@ -27,20 +25,29 @@ impl Renderer {
2725}
2826
2927impl Engine {
30- /// Renders the results of [`Engine::lookup`] to parts of an HTML document,
31- /// so you can display it to the user in a web view or similar.
28+ /// Renders the results of [`Engine::lookup`] to the `<body>` contents of
29+ /// an HTML document, so you can display it to the user in a web view or
30+ /// similar.
31+ ///
32+ /// To get a valid HTML document, you will need to add:
33+ /// - `<!doctype html>`
34+ /// - `<html></html>`
35+ /// - `<body></body>`
36+ ///
37+ /// You can also include your own HTML to further customize the output,
38+ /// such as adding your own `<style>` block.
3239 ///
3340 /// # Errors
3441 ///
3542 /// Errors if the HTML template cannot be rendered by [`tera`]. This should
3643 /// not happen normally, but if you are modifying the template and
3744 /// hot-reloading it, then this may error. It is usually safe to just
3845 /// `expect` this to be [`Ok`].
39- pub fn render_html (
46+ pub fn render_html_body (
4047 & self ,
4148 entries : & [ RecordEntry ] ,
4249 config : & RenderConfig ,
43- ) -> Result < HtmlRender > {
50+ ) -> Result < String > {
4451 let terms = group_terms ( entries) ;
4552
4653 let mut context = tera:: Context :: new ( ) ;
@@ -49,57 +56,10 @@ impl Engine {
4956 context. insert ( "config" , config) ;
5057 let body = self . renderer . tera . load ( ) . render ( "records.html" , & context) ?;
5158
52- Ok ( HtmlRender {
53- body,
54- audio_blobs : render_audio_blobs ( entries) ,
55- } )
59+ Ok ( body)
5660 }
5761}
5862
59- /// Parts of an HTML document rendered by [`Engine::render_html`].
60- ///
61- /// This intentionally does not contain a complete HTML document, since you must
62- /// do some extra platform-specific things to be able to render this in a web
63- /// view.
64- ///
65- /// [`HtmlRender::body`] holds the main HTML content of the rendering, but it
66- /// does not contain some assets such as audio blobs. This is because the
67- /// base 64 audio blobs may be very large, and platforms such as Android's
68- /// default web view cannot handle that much data in an HTML document.
69- ///
70- /// Finally, you must wrap the HTML content in:
71- /// - `<!doctype html>`
72- /// - `<html>`
73- /// - `<body>`
74- #[ derive( Debug , Clone ) ]
75- #[ cfg_attr( feature = "uniffi" , derive( uniffi:: Record ) ) ]
76- pub struct HtmlRender {
77- /// Main HTML body content of the render.
78- pub body : String ,
79- pub audio_blobs : HashMap < RecordId , String > ,
80- }
81-
82- fn render_audio_blobs ( entries : & [ RecordEntry ] ) -> HashMap < RecordId , String > {
83- entries
84- . iter ( )
85- . filter_map ( |record| {
86- if let Record :: YomichanAudioForvo ( dict:: yomichan_audio:: Forvo { audio, .. } )
87- | Record :: YomichanAudioJpod ( dict:: yomichan_audio:: Jpod { audio } )
88- | Record :: YomichanAudioNhk16 ( dict:: yomichan_audio:: Nhk16 { audio, .. } )
89- | Record :: YomichanAudioShinmeikai8 ( dict:: yomichan_audio:: Shinmeikai8 {
90- audio,
91- ..
92- } ) = & record. record
93- {
94- let blob = audio_blob ( audio) ;
95- Some ( ( record. record_id , blob) )
96- } else {
97- None
98- }
99- } )
100- . collect ( )
101- }
102-
10363#[ derive( Debug , Clone , Serialize ) ]
10464#[ cfg_attr( feature = "uniffi" , derive( uniffi:: Record ) ) ]
10565pub struct RenderConfig {
@@ -111,15 +71,6 @@ pub struct RenderConfig {
11171 /// - `headword`: `string?`
11272 /// - `reading`: `string?`
11373 pub fn_add_note : Option < String > ,
114- /// JavaScript function name to return a [`HtmlRender::audio_blobs`] string
115- /// for a given record ID.
116- ///
117- /// Arguments:
118- /// - `record_id`: `number`
119- ///
120- /// Returns:
121- /// - `string` - corresponding audio blob from [`HtmlRender::audio_blobs`].
122- pub fn_audio_blob : String ,
12374}
12475
12576pub fn group_terms ( entries : & [ RecordEntry ] ) -> Vec < RecordTerm > {
@@ -172,22 +123,19 @@ pub fn group_terms(entries: &[RecordEntry]) -> Vec<RecordTerm> {
172123 Record :: YomichanAudioForvo ( audio) => {
173124 info. audio_no_pitch . entry ( source) . or_default ( ) . push ( Audio {
174125 kind : RecordKind :: YomichanAudioForvo ,
175- mime_type : audio_mime_type ( & audio. audio ) ,
176- record_id : record. record_id ,
126+ blob : audio_blob ( & audio. audio ) ,
177127 } ) ;
178128 }
179129 Record :: YomichanAudioJpod ( audio) => {
180130 info. audio_no_pitch . entry ( source) . or_default ( ) . push ( Audio {
181131 kind : RecordKind :: YomichanAudioJpod ,
182- mime_type : audio_mime_type ( & audio. audio ) ,
183- record_id : record. record_id ,
132+ blob : audio_blob ( & audio. audio ) ,
184133 } ) ;
185134 }
186135 Record :: YomichanAudioNhk16 ( audio) => {
187136 let conv = Audio {
188137 kind : RecordKind :: YomichanAudioNhk16 ,
189- mime_type : audio_mime_type ( & audio. audio ) ,
190- record_id : record. record_id ,
138+ blob : audio_blob ( & audio. audio ) ,
191139 } ;
192140 if audio. pitch_positions . is_empty ( ) {
193141 info. audio_no_pitch . entry ( source) . or_default ( ) . push ( conv) ;
@@ -210,8 +158,7 @@ pub fn group_terms(entries: &[RecordEntry]) -> Vec<RecordTerm> {
210158 Record :: YomichanAudioShinmeikai8 ( audio) => {
211159 let conv = Audio {
212160 kind : RecordKind :: YomichanAudioShinmeikai8 ,
213- mime_type : audio_mime_type ( & audio. audio ) ,
214- record_id : record. record_id ,
161+ blob : audio_blob ( & audio. audio ) ,
215162 } ;
216163 if let Some ( pos) = audio. pitch_number {
217164 info. pitches
@@ -285,8 +232,7 @@ pub fn base_pitch<'a>(term: &Term, downstep: dict::jpn::PitchPosition) -> Pitch<
285232#[ derive( Debug , Clone , Serialize ) ]
286233pub struct Audio {
287234 pub kind : RecordKind ,
288- pub mime_type : & ' static str ,
289- pub record_id : RecordId ,
235+ pub blob : String ,
290236}
291237
292238fn audio_mime_type ( audio : & dict:: yomichan_audio:: Audio ) -> & ' static str {
@@ -308,12 +254,12 @@ const _: () = {
308254
309255 #[ uniffi:: export]
310256 impl Wordbase {
311- pub fn render_html (
257+ pub fn render_html_body (
312258 & self ,
313259 entries : & [ RecordEntry ] ,
314260 config : & RenderConfig ,
315- ) -> FfiResult < HtmlRender > {
316- Ok ( self . 0 . render_html ( entries, config) ?)
261+ ) -> FfiResult < String > {
262+ Ok ( self . 0 . render_html_body ( entries, config) ?)
317263 }
318264 }
319265} ;
0 commit comments