@@ -20,10 +20,15 @@ pub struct MDImporter {
2020 /// - math text, math flow, autolink features.
2121 /// - default Markdown features.
2222 pub parse_options : ParseOptions ,
23+
24+ /// If true, paragraphs containing only inline linked text will be converted to link_preview blocks.
25+ ///
26+ /// [link](https://example.com) -> link_preview block
27+ pub parse_link_as_link_preview : bool ,
2328}
2429
2530impl MDImporter {
26- pub fn new ( parse_options : Option < ParseOptions > ) -> Self {
31+ pub fn new ( parse_options : Option < ParseOptions > , parse_link_as_link_preview : bool ) -> Self {
2732 let parse_options = parse_options. unwrap_or_else ( || ParseOptions {
2833 gfm_strikethrough_single_tilde : true ,
2934 constructs : Constructs {
@@ -35,7 +40,10 @@ impl MDImporter {
3540 ..ParseOptions :: gfm ( )
3641 } ) ;
3742
38- Self { parse_options }
43+ Self {
44+ parse_options,
45+ parse_link_as_link_preview,
46+ }
3947 }
4048
4149 pub fn import ( & self , document_id : & str , md : String ) -> Result < DocumentData , DocumentError > {
@@ -58,12 +66,22 @@ impl MDImporter {
5866 Some ( document_id. to_string ( ) ) ,
5967 None ,
6068 None ,
69+ self . parse_link_as_link_preview ,
6170 ) ;
6271
6372 Ok ( document_data)
6473 }
6574}
6675
76+ fn is_paragraph_with_only_link ( para : & mdast:: Paragraph ) -> Option < String > {
77+ if para. children . len ( ) == 1 {
78+ if let mdast:: Node :: Link ( link) = & para. children [ 0 ] {
79+ return Some ( link. url . clone ( ) ) ;
80+ }
81+ }
82+ None
83+ }
84+
6785/// This function will recursively process the mdast node and convert it to document blocks
6886/// The document blocks will be stored in the document data
6987fn process_mdast_node (
@@ -73,6 +91,7 @@ fn process_mdast_node(
7391 block_id : Option < String > ,
7492 list_type : Option < & str > ,
7593 start_number : Option < u32 > ,
94+ parse_link_as_link_preview : bool ,
7695) {
7796 // If the node is an inline node, process it as an inline node
7897 if is_inline_node ( node) {
@@ -90,6 +109,7 @@ fn process_mdast_node(
90109 children,
91110 Some ( & list_type) ,
92111 start_number,
112+ parse_link_as_link_preview,
93113 ) ;
94114 return ;
95115 }
@@ -119,7 +139,7 @@ fn process_mdast_node(
119139
120140 document_data. blocks . insert ( id. clone ( ) , block) ;
121141
122- update_children_map ( document_data, parent_id, & id) ;
142+ update_children_map ( document_data, parent_id. clone ( ) , & id) ;
123143
124144 match node {
125145 mdast:: Node :: Root ( root) => {
@@ -129,16 +149,28 @@ fn process_mdast_node(
129149 & root. children ,
130150 None ,
131151 start_number,
152+ parse_link_as_link_preview,
132153 ) ;
133154 } ,
134155 mdast:: Node :: Paragraph ( para) => {
156+ if let Some ( parent_id) = parent_id {
157+ if parse_link_as_link_preview {
158+ if let Some ( url) = is_paragraph_with_only_link ( para) {
159+ let link_preview_block = create_link_preview_block ( & id, url, & parent_id) ;
160+ document_data. blocks . insert ( id. clone ( ) , link_preview_block) ;
161+ return ;
162+ }
163+ }
164+ }
165+
135166 // Process paragraph as before
136167 process_mdast_node_children (
137168 document_data,
138169 Some ( id. clone ( ) ) ,
139170 & para. children ,
140171 None ,
141172 start_number,
173+ parse_link_as_link_preview,
142174 ) ;
143175 } ,
144176 mdast:: Node :: Heading ( heading) => {
@@ -148,6 +180,7 @@ fn process_mdast_node(
148180 & heading. children ,
149181 None ,
150182 start_number,
183+ parse_link_as_link_preview,
151184 ) ;
152185 } ,
153186 // handle the blockquote and list item node
@@ -166,6 +199,7 @@ fn process_mdast_node(
166199 & para. children ,
167200 None ,
168201 start_number,
202+ parse_link_as_link_preview,
169203 ) ;
170204 }
171205
@@ -176,6 +210,7 @@ fn process_mdast_node(
176210 rest,
177211 list_type,
178212 start_number,
213+ parse_link_as_link_preview,
179214 ) ;
180215 }
181216 }
@@ -189,7 +224,14 @@ fn process_mdast_node(
189224 // Process each row and create SimpleTableRow blocks
190225 for ( row_index, row) in table. children . iter ( ) . enumerate ( ) {
191226 if let mdast:: Node :: TableRow ( row_node) = row {
192- process_table_row ( document_data, row_node, row_index, & id, & table. align ) ;
227+ process_table_row (
228+ document_data,
229+ row_node,
230+ row_index,
231+ & id,
232+ & table. align ,
233+ parse_link_as_link_preview,
234+ ) ;
193235 }
194236 }
195237 } ,
@@ -257,6 +299,7 @@ fn process_table_row(
257299 row_index : usize ,
258300 table_id : & str ,
259301 align : & [ AlignKind ] ,
302+ parse_link_as_link_preview : bool ,
260303) {
261304 let row_id = generate_id ( ) ;
262305 let row_block = create_simple_table_row_block ( & row_id, table_id) ;
@@ -279,6 +322,7 @@ fn process_table_row(
279322 & cell_node. children ,
280323 None ,
281324 None ,
325+ parse_link_as_link_preview,
282326 ) ;
283327 }
284328 }
@@ -326,6 +370,20 @@ pub fn create_image_block(block_id: &str, url: String, parent_id: &str) -> Block
326370 }
327371}
328372
373+ fn create_link_preview_block ( block_id : & str , url : String , parent_id : & str ) -> Block {
374+ let mut data = BlockData :: new ( ) ;
375+ data. insert ( URL_FIELD . to_string ( ) , url. into ( ) ) ;
376+ Block {
377+ id : block_id. to_string ( ) ,
378+ ty : BlockType :: LinkPreview . to_string ( ) ,
379+ data,
380+ parent : parent_id. to_string ( ) ,
381+ children : "" . to_string ( ) ,
382+ external_id : None ,
383+ external_type : None ,
384+ }
385+ }
386+
329387fn create_simple_table_row_block ( id : & str , parent_id : & str ) -> Block {
330388 Block {
331389 id : id. to_string ( ) ,
@@ -379,6 +437,7 @@ fn process_mdast_node_children(
379437 children : & [ mdast:: Node ] ,
380438 list_type : Option < & str > ,
381439 start_number : Option < u32 > ,
440+ parse_link_as_link_preview : bool ,
382441) {
383442 for child in children {
384443 process_mdast_node (
@@ -388,6 +447,7 @@ fn process_mdast_node_children(
388447 None ,
389448 list_type,
390449 start_number,
450+ parse_link_as_link_preview,
391451 ) ;
392452 }
393453}
0 commit comments