Print Markdown to a paper in your terminal

Update pulldown-cmark

+220 -130
+2 -2
Cargo.lock
··· 520 521 [[package]] 522 name = "pulldown-cmark" 523 - version = "0.4.1" 524 source = "registry+https://github.com/rust-lang/crates.io-index" 525 - checksum = "d1b74cc784b038a9921fd1a48310cc2e238101aa8ae0b94201e2d85121dd68b5" 526 dependencies = [ 527 "bitflags", 528 "getopts",
··· 520 521 [[package]] 522 name = "pulldown-cmark" 523 + version = "0.8.0" 524 source = "registry+https://github.com/rust-lang/crates.io-index" 525 + checksum = "ffade02495f22453cd593159ea2f59827aae7f53fa8323f756799b670881dcf8" 526 dependencies = [ 527 "bitflags", 528 "getopts",
+1 -1
Cargo.toml
··· 19 [dependencies] 20 structopt = "0.3" 21 terminal_size = "0.1" 22 - pulldown-cmark = "0.4" 23 ansi_term = "0.12" 24 image = "0.23" 25 console = "0.13"
··· 19 [dependencies] 20 structopt = "0.3" 21 terminal_size = "0.1" 22 + pulldown-cmark = "0.8" 23 ansi_term = "0.12" 24 image = "0.23" 25 console = "0.13"
+217 -127
src/printer.rs
··· 1 - use std::convert::{TryInto, TryFrom}; 2 - use std::io::{Read as _, Write as _}; 3 - use std::process::{Command, Stdio}; 4 - use ansi_term::Style; 5 - use pulldown_cmark::{Alignment, Event, Tag}; 6 - use image::{self, GenericImageView as _}; 7 - use console::{measure_text_width, AnsiCodeIterator}; 8 - use syncat_stylesheet::{Stylesheet, Query}; 9 use crate::termpix; 10 use crate::words::Words; 11 - use crate::table::Table; 12 13 #[derive(Debug, PartialEq)] 14 enum Scope { ··· 19 Strikethrough, 20 Link, 21 Caption, 22 - Rule, 23 FootnoteDefinition, 24 FootnoteReference, 25 FootnoteContent, 26 - List(Option<usize>), 27 - ListItem(Option<usize>, bool), 28 Code, 29 CodeBlock(String), 30 BlockQuote, ··· 32 TableHead, 33 TableRow, 34 TableCell, 35 - Heading(i32), 36 } 37 38 impl Scope { ··· 45 Scope::BlockQuote => 4, 46 Scope::Heading(2) => 5, 47 Scope::Heading(..) => 4, 48 - _ => 0 49 } 50 } 51 ··· 82 Scope::CodeBlock(..) => 2, 83 Scope::Heading(2) => 5, 84 Scope::Heading(..) => 4, 85 - _ => 0 86 } 87 } 88 ··· 105 Strikethrough => "strikethrough", 106 Link => "link", 107 Caption => "caption", 108 - Rule => "hr", 109 FootnoteDefinition => "footnote-def", 110 FootnoteReference => "footnote-ref", 111 FootnoteContent => "footnote", ··· 144 } 145 146 impl<'a> Printer<'a> { 147 - pub fn new(centering: &'a str, margin: &'a str, width: usize, stylesheet: &'a Stylesheet, opts: &'a crate::Opts) -> Printer<'a> { 148 Printer { 149 centering, 150 margin, ··· 218 } 219 220 fn resolve_scopes(stylesheet: &Stylesheet, scopes: &[&str], token: Option<&str>) -> Style { 221 - if scopes.is_empty() { return Style::default(); } 222 let mut query = Query::new(scopes[0], token.unwrap_or(scopes[0])); 223 let mut index = vec![]; 224 for scope in &scopes[1..] { 225 query[&index[..]].add_child(Query::new(*scope, token.unwrap_or(scope))); 226 index.push(0); 227 } 228 - stylesheet.style(&query).unwrap_or_default().try_into().unwrap_or_default() 229 } 230 231 fn style2(&self, token: Option<&str>) -> Style { ··· 237 } 238 239 fn shadow(&self) -> String { 240 - format!("{}", Style::try_from(self.stylesheet.style(&"shadow".into()).unwrap_or_default()).unwrap_or_default().paint(" ")) 241 } 242 243 fn paper_style(&self) -> Style { 244 - Style::try_from(self.stylesheet.style(&"paper".into()).unwrap_or_default()).unwrap_or_default() 245 } 246 247 fn queue_empty(&mut self) { ··· 256 self.centering, 257 self.margin, 258 prefix, 259 - self.paper_style().paint(" ".repeat(self.width - prefix_len - suffix_len)), 260 suffix, 261 self.margin, 262 self.shadow(), ··· 272 self.centering, 273 self.margin, 274 prefix, 275 - self.style().paint("─".repeat(self.width - prefix_len - suffix_len)), 276 suffix, 277 self.margin, 278 self.shadow(), ··· 282 fn print_table(&mut self) { 283 let alignments = if let Some(Scope::Table(alignments)) = self.scope.last() { 284 alignments 285 - } else { return }; 286 let (heading, rows) = std::mem::replace(&mut self.table, (vec![], vec![])); 287 let available_width = self.width - self.prefix_len() - self.suffix_len(); 288 - let table_str = Table::new(heading, rows, available_width) 289 - .print(self.paper_style(), alignments); 290 for line in table_str.lines() { 291 let (prefix, _) = self.prefix(); 292 let (suffix, _) = self.suffix(); ··· 296 self.margin, 297 line, 298 prefix, 299 - self.paper_style().paint(" ".repeat(available_width - measure_text_width(line))), 300 suffix, 301 self.margin, 302 self.shadow(), ··· 352 output = format!("{}{}\n", output, prefix); 353 line = &line[prefix.len()..]; 354 } 355 - format!("{}{}{}\n", output, line, " ".repeat(available_width - line.chars().count())) 356 }) 357 .collect() 358 }; 359 360 - let (prefix, _) = first_prefix.take().unwrap_or_else(|| self.prefix2(Some(&[&language_context[..]]))); 361 - let (suffix, _) = first_suffix.take().unwrap_or_else(|| self.suffix2(Some(&[&language_context[..]]))); 362 println!( 363 "{}{}{}{}{}{}{}", 364 self.centering, ··· 401 ); 402 } 403 404 - let (prefix, _) = first_prefix.take().unwrap_or_else(|| self.prefix2(Some(&[&language_context[..]]))); 405 - let (suffix, _) = first_suffix.take().unwrap_or_else(|| self.suffix2(Some(&[&language_context[..]]))); 406 println!( 407 "{}{}{}{}{}{}{}", 408 self.centering, 409 self.margin, 410 prefix, 411 - format!("{}{}", 412 - style.paint(" ".repeat(available_width - lang.chars().count())), 413 - self.style3(Some(&[&language_context[..]]), Some("lang-tag")).paint(lang) 414 ), 415 suffix, 416 self.margin, 417 self.shadow(), 418 ); 419 - 420 } 421 _ => {} 422 } ··· 426 if !self.buffer.is_empty() { 427 return; 428 } 429 - if self.scope.iter().find(|scope| if let Scope::Table(..) = scope { true } else { false }).is_some() { 430 return; 431 } 432 - if self.content.is_empty() { return } 433 let (prefix, prefix_len) = self.prefix(); 434 let (suffix, suffix_len) = self.suffix(); 435 println!( ··· 439 prefix, 440 self.content, 441 suffix, 442 - self.paper_style().paint(" ".repeat(self.width - measure_text_width(&self.content) - prefix_len - suffix_len)), 443 self.margin, 444 self.shadow(), 445 ); ··· 447 } 448 449 fn target(&mut self) -> &mut String { 450 - if self.scope.iter().find(|scope| *scope == &Scope::TableHead).is_some() { 451 self.table.0.last_mut().unwrap() 452 - } else if self.scope.iter().find(|scope| *scope == &Scope::TableRow).is_some() { 453 self.table.1.last_mut().unwrap().last_mut().unwrap() 454 } else { 455 &mut self.content 456 } 457 } 458 459 - fn handle_text<S>(&mut self, text: S) where S: AsRef<str> { 460 let s = text.as_ref(); 461 if let Some(Scope::CodeBlock(..)) = self.scope.last() { 462 self.buffer += s; ··· 464 } 465 let style = self.style(); 466 for word in Words::new(s) { 467 - if measure_text_width(&self.content) + word.len() + self.prefix_len() + self.suffix_len() > self.width { 468 self.flush(); 469 } 470 let mut word = if self.target().is_empty() { ··· 491 self.empty(); 492 } 493 match tag { 494 - Tag::Paragraph => { self.flush(); } 495 - Tag::Rule => { 496 self.flush(); 497 - self.scope.push(Scope::Rule); 498 } 499 - Tag::Header(level) => { 500 self.flush(); 501 if level == 1 { 502 self.print_rule(); ··· 507 self.flush(); 508 self.scope.push(Scope::BlockQuote); 509 } 510 - Tag::CodeBlock(language) => { 511 self.flush(); 512 self.scope.push(Scope::CodeBlock(language.to_string())); 513 } ··· 531 self.flush(); 532 self.scope.push(Scope::FootnoteContent); 533 } 534 - Tag::HtmlBlock => { /* do nothing */ } 535 - Tag::Table(columns) => { self.scope.push(Scope::Table(columns)) } 536 Tag::TableHead => { 537 self.scope.push(Scope::TableHead); 538 } ··· 542 } 543 Tag::TableCell => { 544 self.scope.push(Scope::TableCell); 545 - if self.scope.iter().find(|scope| *scope == &Scope::TableHead).is_some() { 546 self.table.0.push(String::new()); 547 } else { 548 self.table.1.last_mut().unwrap().push(String::new()); 549 } 550 } 551 - Tag::Emphasis => { self.scope.push(Scope::Italic); } 552 - Tag::Strong => { self.scope.push(Scope::Bold); } 553 - Tag::Strikethrough => { self.scope.push(Scope::Strikethrough); } 554 - Tag::Code => { self.scope.push(Scope::Code); } 555 Tag::Link(_link_type, _destination, _title) => { 556 self.scope.push(Scope::Link); 557 } ··· 559 self.flush(); 560 561 if !self.opts.no_images { 562 - let available_width = self.width - self.prefix_len() - self.suffix_len(); 563 match image::open(destination.as_ref()) { 564 Ok(image) => { 565 let (mut width, mut height) = image.dimensions(); ··· 626 } 627 } 628 629 - Event::End(tag) => { 630 - match tag { 631 - Tag::Paragraph => { 632 - self.flush(); 633 - self.queue_empty(); 634 - } 635 - Tag::Header(level) => { 636 - self.flush(); 637 - self.scope.pop(); 638 - if level == 1 { 639 - self.print_rule(); 640 - } 641 - self.queue_empty(); 642 - } 643 - Tag::Rule => { 644 - self.flush(); 645 self.print_rule(); 646 - self.scope.pop(); 647 - } 648 - Tag::List(..) => { 649 - self.flush(); 650 - self.scope.pop(); 651 - self.queue_empty(); 652 - } 653 - Tag::Item => { 654 - self.flush(); 655 - self.scope.pop(); 656 - if let Some(Scope::List(index)) = self.scope.last_mut() { 657 - *index = index.map(|x| x + 1); 658 - } 659 - }, 660 - Tag::BlockQuote => { 661 - self.flush(); 662 - self.scope.pop(); 663 - self.queue_empty(); 664 } 665 - Tag::Table(..) => { 666 - self.print_table(); 667 - self.scope.pop(); 668 - self.queue_empty(); 669 - } 670 - Tag::CodeBlock(..) => { 671 - self.flush_buffer(); 672 - self.scope.pop(); 673 - self.queue_empty(); 674 - } 675 - Tag::Link(_link_type, destination, title) => { 676 - if !title.is_empty() && !destination.is_empty() && !self.opts.hide_urls { 677 - self.handle_text(format!(" <{}: {}>", title, destination)); 678 - } else if !destination.is_empty() && !self.opts.hide_urls { 679 - self.handle_text(format!(" <{}>", destination)); 680 - } else if !title.is_empty() { 681 - self.handle_text(format!(" <{}>", title)); 682 - } 683 - self.scope.pop(); 684 - } 685 - Tag::Image(_link_type, _destination, _title) => { 686 - self.flush(); 687 - self.scope.pop(); 688 - self.scope.pop(); 689 - self.queue_empty(); 690 } 691 - Tag::FootnoteDefinition(..) => { 692 - self.flush(); 693 - self.scope.pop(); 694 - self.queue_empty(); 695 } 696 - Tag::HtmlBlock => { /* do nothing */ } 697 - _ => { self.scope.pop(); } 698 } 699 } 700 - Event::Text(text) => { self.handle_text(text); } 701 Event::Html(_text) => { /* unimplemented */ } 702 - Event::InlineHtml(_text) => { /* unimplemented */ } 703 - Event::FootnoteReference(text) => { 704 self.scope.push(Scope::FootnoteReference); 705 - self.handle_text(&format!("[{}]", text)); 706 self.scope.pop(); 707 } 708 - Event::SoftBreak => { self.handle_text(" "); } 709 - Event::HardBreak => { self.flush(); } 710 Event::TaskListMarker(checked) => { 711 self.handle_text(if checked { "[✓] " } else { "[ ] " }); 712 }
··· 1 + use crate::table::Table; 2 use crate::termpix; 3 use crate::words::Words; 4 + use ansi_term::Style; 5 + use console::{measure_text_width, AnsiCodeIterator}; 6 + use image::{self, GenericImageView as _}; 7 + use pulldown_cmark::{Alignment, CodeBlockKind, Event, Tag}; 8 + use std::convert::{TryFrom, TryInto}; 9 + use std::io::{Read as _, Write as _}; 10 + use std::process::{Command, Stdio}; 11 + use syncat_stylesheet::{Query, Stylesheet}; 12 13 #[derive(Debug, PartialEq)] 14 enum Scope { ··· 19 Strikethrough, 20 Link, 21 Caption, 22 FootnoteDefinition, 23 FootnoteReference, 24 FootnoteContent, 25 + List(Option<u64>), 26 + ListItem(Option<u64>, bool), 27 Code, 28 CodeBlock(String), 29 BlockQuote, ··· 31 TableHead, 32 TableRow, 33 TableCell, 34 + Heading(u32), 35 } 36 37 impl Scope { ··· 44 Scope::BlockQuote => 4, 45 Scope::Heading(2) => 5, 46 Scope::Heading(..) => 4, 47 + _ => 0, 48 } 49 } 50 ··· 81 Scope::CodeBlock(..) => 2, 82 Scope::Heading(2) => 5, 83 Scope::Heading(..) => 4, 84 + _ => 0, 85 } 86 } 87 ··· 104 Strikethrough => "strikethrough", 105 Link => "link", 106 Caption => "caption", 107 FootnoteDefinition => "footnote-def", 108 FootnoteReference => "footnote-ref", 109 FootnoteContent => "footnote", ··· 142 } 143 144 impl<'a> Printer<'a> { 145 + pub fn new( 146 + centering: &'a str, 147 + margin: &'a str, 148 + width: usize, 149 + stylesheet: &'a Stylesheet, 150 + opts: &'a crate::Opts, 151 + ) -> Printer<'a> { 152 Printer { 153 centering, 154 margin, ··· 222 } 223 224 fn resolve_scopes(stylesheet: &Stylesheet, scopes: &[&str], token: Option<&str>) -> Style { 225 + if scopes.is_empty() { 226 + return Style::default(); 227 + } 228 let mut query = Query::new(scopes[0], token.unwrap_or(scopes[0])); 229 let mut index = vec![]; 230 for scope in &scopes[1..] { 231 query[&index[..]].add_child(Query::new(*scope, token.unwrap_or(scope))); 232 index.push(0); 233 } 234 + stylesheet 235 + .style(&query) 236 + .unwrap_or_default() 237 + .try_into() 238 + .unwrap_or_default() 239 } 240 241 fn style2(&self, token: Option<&str>) -> Style { ··· 247 } 248 249 fn shadow(&self) -> String { 250 + format!( 251 + "{}", 252 + Style::try_from(self.stylesheet.style(&"shadow".into()).unwrap_or_default()) 253 + .unwrap_or_default() 254 + .paint(" ") 255 + ) 256 } 257 258 fn paper_style(&self) -> Style { 259 + Style::try_from(self.stylesheet.style(&"paper".into()).unwrap_or_default()) 260 + .unwrap_or_default() 261 } 262 263 fn queue_empty(&mut self) { ··· 272 self.centering, 273 self.margin, 274 prefix, 275 + self.paper_style() 276 + .paint(" ".repeat(self.width - prefix_len - suffix_len)), 277 suffix, 278 self.margin, 279 self.shadow(), ··· 289 self.centering, 290 self.margin, 291 prefix, 292 + self.style() 293 + .paint("─".repeat(self.width - prefix_len - suffix_len)), 294 suffix, 295 self.margin, 296 self.shadow(), ··· 300 fn print_table(&mut self) { 301 let alignments = if let Some(Scope::Table(alignments)) = self.scope.last() { 302 alignments 303 + } else { 304 + return; 305 + }; 306 let (heading, rows) = std::mem::replace(&mut self.table, (vec![], vec![])); 307 let available_width = self.width - self.prefix_len() - self.suffix_len(); 308 + let table_str = 309 + Table::new(heading, rows, available_width).print(self.paper_style(), alignments); 310 for line in table_str.lines() { 311 let (prefix, _) = self.prefix(); 312 let (suffix, _) = self.suffix(); ··· 316 self.margin, 317 line, 318 prefix, 319 + self.paper_style() 320 + .paint(" ".repeat(available_width - measure_text_width(line))), 321 suffix, 322 self.margin, 323 self.shadow(), ··· 373 output = format!("{}{}\n", output, prefix); 374 line = &line[prefix.len()..]; 375 } 376 + format!( 377 + "{}{}{}\n", 378 + output, 379 + line, 380 + " ".repeat(available_width - line.chars().count()) 381 + ) 382 }) 383 .collect() 384 }; 385 386 + let (prefix, _) = first_prefix 387 + .take() 388 + .unwrap_or_else(|| self.prefix2(Some(&[&language_context[..]]))); 389 + let (suffix, _) = first_suffix 390 + .take() 391 + .unwrap_or_else(|| self.suffix2(Some(&[&language_context[..]]))); 392 println!( 393 "{}{}{}{}{}{}{}", 394 self.centering, ··· 431 ); 432 } 433 434 + let (prefix, _) = first_prefix 435 + .take() 436 + .unwrap_or_else(|| self.prefix2(Some(&[&language_context[..]]))); 437 + let (suffix, _) = first_suffix 438 + .take() 439 + .unwrap_or_else(|| self.suffix2(Some(&[&language_context[..]]))); 440 println!( 441 "{}{}{}{}{}{}{}", 442 self.centering, 443 self.margin, 444 prefix, 445 + format!( 446 + "{}{}", 447 + style.paint(" ".repeat(available_width - lang.chars().count())), 448 + self.style3(Some(&[&language_context[..]]), Some("lang-tag")) 449 + .paint(lang) 450 ), 451 suffix, 452 self.margin, 453 self.shadow(), 454 ); 455 } 456 _ => {} 457 } ··· 461 if !self.buffer.is_empty() { 462 return; 463 } 464 + if self 465 + .scope 466 + .iter() 467 + .find(|scope| { 468 + if let Scope::Table(..) = scope { 469 + true 470 + } else { 471 + false 472 + } 473 + }) 474 + .is_some() 475 + { 476 + return; 477 + } 478 + if self.content.is_empty() { 479 return; 480 } 481 let (prefix, prefix_len) = self.prefix(); 482 let (suffix, suffix_len) = self.suffix(); 483 println!( ··· 487 prefix, 488 self.content, 489 suffix, 490 + self.paper_style().paint( 491 + " ".repeat( 492 + self.width - measure_text_width(&self.content) - prefix_len - suffix_len 493 + ) 494 + ), 495 self.margin, 496 self.shadow(), 497 ); ··· 499 } 500 501 fn target(&mut self) -> &mut String { 502 + if self 503 + .scope 504 + .iter() 505 + .find(|scope| *scope == &Scope::TableHead) 506 + .is_some() 507 + { 508 self.table.0.last_mut().unwrap() 509 + } else if self 510 + .scope 511 + .iter() 512 + .find(|scope| *scope == &Scope::TableRow) 513 + .is_some() 514 + { 515 self.table.1.last_mut().unwrap().last_mut().unwrap() 516 } else { 517 &mut self.content 518 } 519 } 520 521 + fn handle_text<S>(&mut self, text: S) 522 + where 523 + S: AsRef<str>, 524 + { 525 let s = text.as_ref(); 526 if let Some(Scope::CodeBlock(..)) = self.scope.last() { 527 self.buffer += s; ··· 529 } 530 let style = self.style(); 531 for word in Words::new(s) { 532 + if measure_text_width(&self.content) 533 + + word.len() 534 + + self.prefix_len() 535 + + self.suffix_len() 536 + > self.width 537 + { 538 self.flush(); 539 } 540 let mut word = if self.target().is_empty() { ··· 561 self.empty(); 562 } 563 match tag { 564 + Tag::Paragraph => { 565 self.flush(); 566 } 567 + Tag::Heading(level) => { 568 self.flush(); 569 if level == 1 { 570 self.print_rule(); ··· 575 self.flush(); 576 self.scope.push(Scope::BlockQuote); 577 } 578 + Tag::CodeBlock(CodeBlockKind::Indented) => { 579 + self.flush(); 580 + self.scope.push(Scope::CodeBlock("".to_string())); 581 + } 582 + Tag::CodeBlock(CodeBlockKind::Fenced(language)) => { 583 self.flush(); 584 self.scope.push(Scope::CodeBlock(language.to_string())); 585 } ··· 603 self.flush(); 604 self.scope.push(Scope::FootnoteContent); 605 } 606 + Tag::Table(columns) => self.scope.push(Scope::Table(columns)), 607 Tag::TableHead => { 608 self.scope.push(Scope::TableHead); 609 } ··· 613 } 614 Tag::TableCell => { 615 self.scope.push(Scope::TableCell); 616 + if self 617 + .scope 618 + .iter() 619 + .find(|scope| *scope == &Scope::TableHead) 620 + .is_some() 621 + { 622 self.table.0.push(String::new()); 623 } else { 624 self.table.1.last_mut().unwrap().push(String::new()); 625 } 626 } 627 + Tag::Emphasis => { 628 + self.scope.push(Scope::Italic); 629 + } 630 + Tag::Strong => { 631 + self.scope.push(Scope::Bold); 632 + } 633 + Tag::Strikethrough => { 634 + self.scope.push(Scope::Strikethrough); 635 + } 636 Tag::Link(_link_type, _destination, _title) => { 637 self.scope.push(Scope::Link); 638 } ··· 640 self.flush(); 641 642 if !self.opts.no_images { 643 + let available_width = 644 + self.width - self.prefix_len() - self.suffix_len(); 645 match image::open(destination.as_ref()) { 646 Ok(image) => { 647 let (mut width, mut height) = image.dimensions(); ··· 708 } 709 } 710 711 + Event::End(tag) => match tag { 712 + Tag::Paragraph => { 713 + self.flush(); 714 + self.queue_empty(); 715 + } 716 + Tag::Heading(level) => { 717 + self.flush(); 718 + self.scope.pop(); 719 + if level == 1 { 720 self.print_rule(); 721 } 722 + self.queue_empty(); 723 + } 724 + Tag::List(..) => { 725 + self.flush(); 726 + self.scope.pop(); 727 + self.queue_empty(); 728 + } 729 + Tag::Item => { 730 + self.flush(); 731 + self.scope.pop(); 732 + if let Some(Scope::List(index)) = self.scope.last_mut() { 733 + *index = index.map(|x| x + 1); 734 } 735 + } 736 + Tag::BlockQuote => { 737 + self.flush(); 738 + self.scope.pop(); 739 + self.queue_empty(); 740 + } 741 + Tag::Table(..) => { 742 + self.print_table(); 743 + self.scope.pop(); 744 + self.queue_empty(); 745 + } 746 + Tag::CodeBlock(..) => { 747 + self.flush_buffer(); 748 + self.scope.pop(); 749 + self.queue_empty(); 750 + } 751 + Tag::Link(_link_type, destination, title) => { 752 + if !title.is_empty() && !destination.is_empty() && !self.opts.hide_urls { 753 + self.handle_text(format!(" <{}: {}>", title, destination)); 754 + } else if !destination.is_empty() && !self.opts.hide_urls { 755 + self.handle_text(format!(" <{}>", destination)); 756 + } else if !title.is_empty() { 757 + self.handle_text(format!(" <{}>", title)); 758 } 759 + self.scope.pop(); 760 + } 761 + Tag::Image(_link_type, _destination, _title) => { 762 + self.flush(); 763 + self.scope.pop(); 764 + self.scope.pop(); 765 + self.queue_empty(); 766 } 767 + Tag::FootnoteDefinition(..) => { 768 + self.flush(); 769 + self.scope.pop(); 770 + self.queue_empty(); 771 + } 772 + _ => { 773 + self.scope.pop(); 774 + } 775 + }, 776 + Event::Rule => { 777 + self.flush(); 778 + self.print_rule(); 779 } 780 + Event::Text(text) => { 781 + self.handle_text(text); 782 + } 783 + Event::Code(text) => { 784 + self.scope.push(Scope::Code); 785 + self.handle_text(text); 786 + self.scope.pop(); 787 + } 788 Event::Html(_text) => { /* unimplemented */ } 789 + Event::FootnoteReference(text) => { 790 self.scope.push(Scope::FootnoteReference); 791 + self.handle_text(&format!("[{}]", text)); 792 self.scope.pop(); 793 } 794 + Event::SoftBreak => { 795 + self.handle_text(" "); 796 + } 797 + Event::HardBreak => { 798 + self.flush(); 799 + } 800 Event::TaskListMarker(checked) => { 801 self.handle_text(if checked { "[✓] " } else { "[ ] " }); 802 }