47
47
//! }
48
48
//! }
49
49
//! ```
50
+ #![ allow( missing_docs) ]
50
51
use crate :: core:: border;
51
52
use crate :: core:: font:: { self , Font } ;
52
53
use crate :: core:: padding;
@@ -57,12 +58,47 @@ use crate::core::{
57
58
use crate :: { column, container, rich_text, row, scrollable, span, text} ;
58
59
59
60
use std:: cell:: { Cell , RefCell } ;
61
+ use std:: ops:: Range ;
60
62
use std:: sync:: Arc ;
61
63
62
64
pub use core:: text:: Highlight ;
63
65
pub use pulldown_cmark:: HeadingLevel ;
64
66
pub use url:: Url ;
65
67
68
+ #[ derive( Debug , Clone ) ]
69
+ pub struct Content {
70
+ items : Vec < Item > ,
71
+ state : State ,
72
+ }
73
+
74
+ impl Content {
75
+ pub fn parse ( markdown : & str ) -> Self {
76
+ let mut state = State :: default ( ) ;
77
+ let items = parse_with ( & mut state, markdown) . collect ( ) ;
78
+
79
+ Self { items, state }
80
+ }
81
+
82
+ pub fn push_str ( & mut self , markdown : & str ) {
83
+ // Append to last leftover text
84
+ let mut leftover = std:: mem:: take ( & mut self . state . leftover ) ;
85
+ leftover. push_str ( markdown) ;
86
+
87
+ // Pop the last item
88
+ let _ = self . items . pop ( ) ;
89
+
90
+ // Re-parse last item and new text
91
+ let new_items = parse_with ( & mut self . state , & leftover) ;
92
+ self . items . extend ( new_items) ;
93
+
94
+ dbg ! ( & self . state) ;
95
+ }
96
+
97
+ pub fn items ( & self ) -> & [ Item ] {
98
+ & self . items
99
+ }
100
+ }
101
+
66
102
/// A Markdown item.
67
103
#[ derive( Debug , Clone ) ]
68
104
pub enum Item {
@@ -232,6 +268,24 @@ impl Span {
232
268
/// }
233
269
/// ```
234
270
pub fn parse ( markdown : & str ) -> impl Iterator < Item = Item > + ' _ {
271
+ parse_with ( State :: default ( ) , markdown)
272
+ }
273
+
274
+ #[ derive( Debug , Clone , Default ) ]
275
+ pub struct State {
276
+ leftover : String ,
277
+ }
278
+
279
+ impl AsMut < Self > for State {
280
+ fn as_mut ( & mut self ) -> & mut Self {
281
+ self
282
+ }
283
+ }
284
+
285
+ fn parse_with < ' a > (
286
+ mut state : impl AsMut < State > + ' a ,
287
+ markdown : & ' a str ,
288
+ ) -> impl Iterator < Item = Item > + ' a {
235
289
struct List {
236
290
start : Option < u64 > ,
237
291
items : Vec < Vec < Item > > ,
@@ -255,27 +309,31 @@ pub fn parse(markdown: &str) -> impl Iterator<Item = Item> + '_ {
255
309
| pulldown_cmark:: Options :: ENABLE_PLUSES_DELIMITED_METADATA_BLOCKS
256
310
| pulldown_cmark:: Options :: ENABLE_TABLES
257
311
| pulldown_cmark:: Options :: ENABLE_STRIKETHROUGH ,
258
- ) ;
259
-
260
- let produce = |lists : & mut Vec < List > , item| {
261
- if lists. is_empty ( ) {
262
- Some ( item)
263
- } else {
264
- lists
265
- . last_mut ( )
266
- . expect ( "list context" )
267
- . items
268
- . last_mut ( )
269
- . expect ( "item context" )
270
- . push ( item) ;
312
+ )
313
+ . into_offset_iter ( ) ;
271
314
272
- None
273
- }
274
- } ;
315
+ let mut produce =
316
+ move |lists : & mut Vec < List > , item, source : Range < usize > | {
317
+ if lists. is_empty ( ) {
318
+ state. as_mut ( ) . leftover = markdown[ source. start ..] . to_owned ( ) ;
319
+
320
+ Some ( item)
321
+ } else {
322
+ lists
323
+ . last_mut ( )
324
+ . expect ( "list context" )
325
+ . items
326
+ . last_mut ( )
327
+ . expect ( "item context" )
328
+ . push ( item) ;
329
+
330
+ None
331
+ }
332
+ } ;
275
333
276
334
// We want to keep the `spans` capacity
277
335
#[ allow( clippy:: drain_collect) ]
278
- parser. filter_map ( move |event| match event {
336
+ parser. filter_map ( move |( event, source ) | match event {
279
337
pulldown_cmark:: Event :: Start ( tag) => match tag {
280
338
pulldown_cmark:: Tag :: Strong if !metadata && !table => {
281
339
strong = true ;
@@ -311,6 +369,7 @@ pub fn parse(markdown: &str) -> impl Iterator<Item = Item> + '_ {
311
369
produce (
312
370
& mut lists,
313
371
Item :: Paragraph ( Text :: new ( spans. drain ( ..) . collect ( ) ) ) ,
372
+ source,
314
373
)
315
374
} ;
316
375
@@ -350,6 +409,7 @@ pub fn parse(markdown: &str) -> impl Iterator<Item = Item> + '_ {
350
409
produce (
351
410
& mut lists,
352
411
Item :: Paragraph ( Text :: new ( spans. drain ( ..) . collect ( ) ) ) ,
412
+ source,
353
413
)
354
414
} ;
355
415
@@ -370,6 +430,7 @@ pub fn parse(markdown: &str) -> impl Iterator<Item = Item> + '_ {
370
430
produce (
371
431
& mut lists,
372
432
Item :: Heading ( level, Text :: new ( spans. drain ( ..) . collect ( ) ) ) ,
433
+ source,
373
434
)
374
435
}
375
436
pulldown_cmark:: TagEnd :: Strong if !metadata && !table => {
@@ -392,6 +453,7 @@ pub fn parse(markdown: &str) -> impl Iterator<Item = Item> + '_ {
392
453
produce (
393
454
& mut lists,
394
455
Item :: Paragraph ( Text :: new ( spans. drain ( ..) . collect ( ) ) ) ,
456
+ source,
395
457
)
396
458
}
397
459
pulldown_cmark:: TagEnd :: Item if !metadata && !table => {
@@ -401,6 +463,7 @@ pub fn parse(markdown: &str) -> impl Iterator<Item = Item> + '_ {
401
463
produce (
402
464
& mut lists,
403
465
Item :: Paragraph ( Text :: new ( spans. drain ( ..) . collect ( ) ) ) ,
466
+ source,
404
467
)
405
468
}
406
469
}
@@ -413,6 +476,7 @@ pub fn parse(markdown: &str) -> impl Iterator<Item = Item> + '_ {
413
476
start : list. start ,
414
477
items : list. items ,
415
478
} ,
479
+ source,
416
480
)
417
481
}
418
482
pulldown_cmark:: TagEnd :: CodeBlock if !metadata && !table => {
@@ -424,6 +488,7 @@ pub fn parse(markdown: &str) -> impl Iterator<Item = Item> + '_ {
424
488
produce (
425
489
& mut lists,
426
490
Item :: CodeBlock ( Text :: new ( spans. drain ( ..) . collect ( ) ) ) ,
491
+ source,
427
492
)
428
493
}
429
494
pulldown_cmark:: TagEnd :: MetadataBlock ( _) => {
0 commit comments