1use crate::{
2 HasSpan, Parser, Span,
3 attributes::Attrlist,
4 blocks::{
5 AdmonitionBlock, Break, CompoundDelimitedBlock, ContentModel, IsBlock, ListBlock, ListItem,
6 ListItemMarker, MediaBlock, Preamble, QuoteBlock, RawDelimitedBlock, SectionBlock,
7 SimpleBlock, TableBlock, media::TargetResolution, metadata::BlockMetadata,
8 starts_with_admonition_label,
9 },
10 content::{Content, SubstitutionGroup, substitute_attributes_in_reftext},
11 document::{Attribute, InterpretedValue, RefType},
12 parser::{InlineSubstitutionRenderer, ReferenceResolver, ReferenceWarnings, XrefSignifier},
13 span::MatchedItem,
14 strings::CowStr,
15 warnings::{MatchAndWarnings, Warning, WarningType},
16};
17
18#[derive(Clone, Eq, Hash, PartialEq)]
31#[non_exhaustive]
32pub enum Block<'src> {
33 Simple(SimpleBlock<'src>),
36
37 Media(MediaBlock<'src>),
40
41 Section(SectionBlock<'src>),
44
45 List(ListBlock<'src>),
49
50 ListItem(ListItem<'src>),
53
54 RawDelimited(RawDelimitedBlock<'src>),
58
59 CompoundDelimited(CompoundDelimitedBlock<'src>),
61
62 Admonition(AdmonitionBlock<'src>),
66
67 Quote(QuoteBlock<'src>),
70
71 Table(TableBlock<'src>),
73
74 Preamble(Preamble<'src>),
77
78 Break(Break<'src>),
80
81 DocumentAttribute(Attribute<'src>),
84}
85
86impl<'src> std::fmt::Debug for Block<'src> {
87 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
88 match self {
89 Block::Simple(block) => f.debug_tuple("Block::Simple").field(block).finish(),
90 Block::Media(block) => f.debug_tuple("Block::Media").field(block).finish(),
91 Block::Section(block) => f.debug_tuple("Block::Section").field(block).finish(),
92 Block::List(block) => f.debug_tuple("Block::List").field(block).finish(),
93 Block::ListItem(block) => f.debug_tuple("Block::ListItem").field(block).finish(),
94
95 Block::RawDelimited(block) => {
96 f.debug_tuple("Block::RawDelimited").field(block).finish()
97 }
98
99 Block::CompoundDelimited(block) => f
100 .debug_tuple("Block::CompoundDelimited")
101 .field(block)
102 .finish(),
103
104 Block::Admonition(block) => f.debug_tuple("Block::Admonition").field(block).finish(),
105 Block::Quote(block) => f.debug_tuple("Block::Quote").field(block).finish(),
106 Block::Table(block) => f.debug_tuple("Block::Table").field(block).finish(),
107 Block::Preamble(block) => f.debug_tuple("Block::Preamble").field(block).finish(),
108 Block::Break(break_) => f.debug_tuple("Block::Break").field(break_).finish(),
109
110 Block::DocumentAttribute(block) => f
111 .debug_tuple("Block::DocumentAttribute")
112 .field(block)
113 .finish(),
114 }
115 }
116}
117
118#[allow(clippy::large_enum_variant)]
130pub(crate) enum BlockParseOutcome<'src> {
131 Parsed(MatchedItem<'src, Block<'src>>),
133
134 Dropped(Span<'src>),
139
140 NoMatch,
142}
143
144impl<'src> Block<'src> {
145 #[cfg(test)]
154 pub(crate) fn parse(
155 source: Span<'src>,
156 parser: &mut Parser,
157 ) -> MatchAndWarnings<'src, Option<MatchedItem<'src, Self>>> {
158 let MatchAndWarnings { item, warnings } = Self::parse_internal(source, parser, None, false);
159
160 MatchAndWarnings {
161 item: match item {
162 BlockParseOutcome::Parsed(mi) => Some(mi),
163 BlockParseOutcome::Dropped(_) | BlockParseOutcome::NoMatch => None,
164 },
165 warnings,
166 }
167 }
168
169 pub(crate) fn parse_with_outcome(
176 source: Span<'src>,
177 parser: &mut Parser,
178 ) -> MatchAndWarnings<'src, BlockParseOutcome<'src>> {
179 Self::parse_internal(source, parser, None, false)
180 }
181
182 pub(crate) fn parse_for_list_item(
193 source: Span<'src>,
194 parser: &mut Parser,
195 parent_list_markers: &[ListItemMarker<'src>],
196 is_continuation: bool,
197 ) -> MatchAndWarnings<'src, BlockParseOutcome<'src>> {
198 Self::parse_internal(source, parser, Some(parent_list_markers), is_continuation)
199 }
200
201 fn parse_internal(
204 source: Span<'src>,
205 parser: &mut Parser,
206 parent_list_markers: Option<&[ListItemMarker<'src>]>,
207 is_continuation: bool,
208 ) -> MatchAndWarnings<'src, BlockParseOutcome<'src>> {
209 let first_line = source.take_line().item.discard_whitespace();
213
214 if let Some(first_char) = first_line.chars().next()
217 && !matches!(
218 first_char,
219 '.' | '#'
220 | '='
221 | '/'
222 | '-'
223 | '+'
224 | '*'
225 | '_'
226 | '`'
227 | '['
228 | ':'
229 | '\''
230 | '<'
231 | '>'
232 | '"'
233 | '•'
234 )
235 && !first_line.contains("::")
236 && !first_line.contains(";;")
237 && !TableBlock::is_table_delimiter(&first_line)
238 && !ListItemMarker::starts_with_marker(first_line)
239 && !starts_with_admonition_label(first_line)
240 && parent_list_markers.is_none()
241 && parser.pending_block_title.is_none()
242 && let Some(MatchedItem {
243 item: simple_block,
244 after,
245 }) = SimpleBlock::parse_fast(source, parser)
246 {
247 let mut warnings = vec![];
248 let block = Self::Simple(simple_block);
249
250 Self::register_block_id(
253 block.id(),
254 Self::block_reftext(&block, None).as_deref(),
255 Self::block_signifier(&block, parser),
256 block.span(),
257 parser,
258 &mut warnings,
259 );
260
261 return MatchAndWarnings {
262 item: BlockParseOutcome::Parsed(MatchedItem { item: block, after }),
263 warnings,
264 };
265 }
266
267 if first_line.starts_with(':')
269 && (first_line.ends_with(':') || first_line.contains(": "))
270 && let Some(attr) = Attribute::parse(source, parser)
271 {
272 let mut warnings: Vec<Warning<'src>> = vec![];
273 parser.set_attribute_from_body(&attr.item, &mut warnings);
274
275 return MatchAndWarnings {
276 item: BlockParseOutcome::Parsed(MatchedItem {
277 item: Self::DocumentAttribute(attr.item),
278 after: attr.after,
279 }),
280 warnings,
281 };
282 }
283
284 let MatchAndWarnings {
287 item: mut metadata,
288 mut warnings,
289 } = BlockMetadata::parse(source, parser);
290
291 if let Some(pending_title) = parser.pending_block_title.take()
297 && metadata.title.is_none()
298 {
299 metadata.title = Some(crate::content::Content::from_owned_title(
303 metadata.block_start,
304 pending_title,
305 ));
306 }
307
308 if parent_list_markers.is_none() && !metadata.is_empty() {
323 let after_blanks = metadata.block_start.discard_empty_lines();
324 if after_blanks != metadata.block_start && !after_blanks.is_empty() {
325 metadata.block_start = after_blanks;
326 }
327 }
328
329 let anchor_reftext = metadata
335 .anchor_reftext
336 .as_ref()
337 .map(|span| substitute_attributes_in_reftext(*span, parser));
338
339 let is_literal =
347 metadata.attrlist.as_ref().and_then(|a| a.block_style()) == Some("literal") && {
348 let first_line = metadata.block_start.take_normalized_line().item;
349 !RawDelimitedBlock::is_valid_delimiter(&first_line)
350 && !CompoundDelimitedBlock::is_valid_delimiter(&first_line)
351 && !TableBlock::is_table_delimiter(&first_line)
352 };
353
354 let mut simple_block_mi = None;
361
362 if !is_literal {
363 if let Some(mut adm_maw) = AdmonitionBlock::parse(&metadata, parser)
364 && let Some(adm) = adm_maw.item
365 {
366 if !adm_maw.warnings.is_empty() {
367 warnings.append(&mut adm_maw.warnings);
368 }
369
370 let block = Self::Admonition(adm.item);
371
372 Self::register_block_id(
373 block.id(),
374 Self::block_reftext(&block, anchor_reftext.as_deref()).as_deref(),
375 Self::block_signifier(&block, parser),
376 block.span(),
377 parser,
378 &mut warnings,
379 );
380
381 return MatchAndWarnings {
382 item: BlockParseOutcome::Parsed(MatchedItem {
383 item: block,
384 after: adm.after,
385 }),
386 warnings,
387 };
388 }
389
390 if let Some(mut quote_maw) = QuoteBlock::parse(&metadata, parser)
391 && let Some(quote) = quote_maw.item
392 {
393 if !quote_maw.warnings.is_empty() {
394 warnings.append(&mut quote_maw.warnings);
395 }
396
397 let block = Self::Quote(quote.item);
398
399 Self::register_block_id(
400 block.id(),
401 Self::block_reftext(&block, anchor_reftext.as_deref()).as_deref(),
402 Self::block_signifier(&block, parser),
403 block.span(),
404 parser,
405 &mut warnings,
406 );
407
408 return MatchAndWarnings {
409 item: BlockParseOutcome::Parsed(MatchedItem {
410 item: block,
411 after: quote.after,
412 }),
413 warnings,
414 };
415 }
416
417 if let Some(mut rdb_maw) = RawDelimitedBlock::parse(&metadata, parser)
418 && let Some(rdb) = rdb_maw.item
419 {
420 if !rdb_maw.warnings.is_empty() {
421 warnings.append(&mut rdb_maw.warnings);
422 }
423
424 let block = Self::RawDelimited(rdb.item);
425
426 Self::register_block_id(
427 block.id(),
428 Self::block_reftext(&block, anchor_reftext.as_deref()).as_deref(),
429 Self::block_signifier(&block, parser),
430 block.span(),
431 parser,
432 &mut warnings,
433 );
434
435 return MatchAndWarnings {
436 item: BlockParseOutcome::Parsed(MatchedItem {
437 item: block,
438 after: rdb.after,
439 }),
440 warnings,
441 };
442 }
443
444 if let Some(mut cdb_maw) = CompoundDelimitedBlock::parse(&metadata, parser)
445 && let Some(cdb) = cdb_maw.item
446 {
447 if !cdb_maw.warnings.is_empty() {
448 warnings.append(&mut cdb_maw.warnings);
449 }
450
451 let block = Self::CompoundDelimited(cdb.item);
452
453 Self::register_block_id(
454 block.id(),
455 Self::block_reftext(&block, anchor_reftext.as_deref()).as_deref(),
456 Self::block_signifier(&block, parser),
457 block.span(),
458 parser,
459 &mut warnings,
460 );
461
462 return MatchAndWarnings {
463 item: BlockParseOutcome::Parsed(MatchedItem {
464 item: block,
465 after: cdb.after,
466 }),
467 warnings,
468 };
469 }
470
471 if let Some(mut table_maw) = TableBlock::parse(&metadata, parser)
472 && let Some(table) = table_maw.item
473 {
474 if !table_maw.warnings.is_empty() {
475 warnings.append(&mut table_maw.warnings);
476 }
477
478 let block = Self::Table(table.item);
479
480 Self::register_block_id(
481 block.id(),
482 Self::block_reftext(&block, anchor_reftext.as_deref()).as_deref(),
483 Self::block_signifier(&block, parser),
484 block.span(),
485 parser,
486 &mut warnings,
487 );
488
489 return MatchAndWarnings {
490 item: BlockParseOutcome::Parsed(MatchedItem {
491 item: block,
492 after: table.after,
493 }),
494 warnings,
495 };
496 }
497
498 let line = metadata.block_start.take_normalized_line();
500
501 if line.item.starts_with("image::")
502 || line.item.starts_with("video::")
503 || line.item.starts_with("audio::")
504 {
505 let mut media_block_maw = MediaBlock::parse(&metadata, parser);
506
507 if let Some(mut media_block) = media_block_maw.item {
508 if !media_block_maw.warnings.is_empty() {
512 warnings.append(&mut media_block_maw.warnings);
513 }
514
515 if media_block.item.resolve_target(parser) == TargetResolution::Drop {
519 return MatchAndWarnings {
520 item: BlockParseOutcome::Dropped(media_block.after),
521 warnings,
522 };
523 }
524
525 media_block.item.assign_caption(parser);
529
530 let block = Self::Media(media_block.item);
531
532 Self::register_block_id(
533 block.id(),
534 Self::block_reftext(&block, anchor_reftext.as_deref()).as_deref(),
535 Self::block_signifier(&block, parser),
536 block.span(),
537 parser,
538 &mut warnings,
539 );
540
541 return MatchAndWarnings {
542 item: BlockParseOutcome::Parsed(MatchedItem {
543 item: block,
544 after: media_block.after,
545 }),
546 warnings,
547 };
548 }
549
550 }
553
554 if (line.item.starts_with('=') || line.item.starts_with('#'))
555 && let Some(mi_section_block) =
556 SectionBlock::parse(&metadata, parser, &mut warnings)
557 {
558 return MatchAndWarnings {
562 item: BlockParseOutcome::Parsed(MatchedItem {
563 item: Self::Section(mi_section_block.item),
564 after: mi_section_block.after,
565 }),
566 warnings,
567 };
568 }
569
570 if (line.item.starts_with('\'')
571 || line.item.starts_with('-')
572 || line.item.starts_with('*')
573 || line.item.starts_with('_')
574 || line.item.starts_with('<'))
575 && let Some(mi_break) = Break::parse(&metadata, parser)
576 {
577 return MatchAndWarnings {
580 item: BlockParseOutcome::Parsed(MatchedItem {
581 item: Self::Break(mi_break.item),
582 after: mi_break.after,
583 }),
584 warnings,
585 };
586 }
587
588 if parent_list_markers.is_none()
592 && let Some(mi_list) = ListBlock::parse(&metadata, parser, &mut warnings)
593 {
594 return MatchAndWarnings {
595 item: BlockParseOutcome::Parsed(MatchedItem {
596 item: Self::List(mi_list.item),
597 after: mi_list.after,
598 }),
599 warnings,
600 };
601 }
602
603 simple_block_mi = if let Some(plm) = parent_list_markers {
610 SimpleBlock::parse_for_list_item(&metadata, parser, is_continuation, plm)
611 } else {
612 SimpleBlock::parse(&metadata, parser)
613 };
614
615 if simple_block_mi.is_none() && !metadata.is_empty() {
616 warnings.push(Warning {
620 source: metadata.source,
621 warning: WarningType::MissingBlockAfterTitleOrAttributeList,
622 origin: None,
623 });
624
625 metadata.title_source = None;
629 metadata.title = None;
630 metadata.anchor = None;
631 metadata.attrlist = None;
632 metadata.block_start = metadata.source;
633 }
634 }
635
636 let simple_block_mi = match simple_block_mi {
640 Some(mi) => Some(mi),
641 None => {
642 if let Some(plm) = parent_list_markers {
643 SimpleBlock::parse_for_list_item(&metadata, parser, is_continuation, plm)
644 } else {
645 SimpleBlock::parse(&metadata, parser)
646 }
647 }
648 };
649
650 let mut result = MatchAndWarnings {
651 item: match simple_block_mi {
652 Some(mi) => BlockParseOutcome::Parsed(MatchedItem {
653 item: Self::Simple(mi.item),
654 after: mi.after,
655 }),
656 None => BlockParseOutcome::NoMatch,
657 },
658 warnings,
659 };
660
661 if let BlockParseOutcome::Parsed(ref matched_item) = result.item {
662 Self::register_block_id(
663 matched_item.item.id(),
664 Self::block_reftext(&matched_item.item, anchor_reftext.as_deref()).as_deref(),
665 Self::block_signifier(&matched_item.item, parser),
666 matched_item.item.span(),
667 parser,
668 &mut result.warnings,
669 );
670 }
671
672 result
673 }
674
675 fn block_signifier<'a>(block: &'a Block<'a>, parser: &Parser) -> Option<XrefSignifier> {
686 let caption = block.caption()?;
688
689 let has_explicit_reftext = block
690 .attrlist()
691 .and_then(|attrlist| attrlist.named_attribute("reftext"))
692 .is_some()
693 || block.anchor_reftext().is_some();
694 if has_explicit_reftext {
695 return None;
696 }
697
698 if Self::has_caption_override(block, parser) {
704 return None;
705 }
706
707 let label = caption.strip_suffix(". ").unwrap_or(caption).to_string();
710 Some(XrefSignifier {
711 label,
712 emphasize: false,
713 })
714 }
715
716 fn has_caption_override<'a>(block: &'a Block<'a>, parser: &Parser) -> bool {
726 let attribute_override = block
727 .attrlist()
728 .and_then(|attrlist| attrlist.named_attribute("caption"))
729 .is_some()
730 || matches!(block, Block::Media(media)
731 if media.macro_attrlist().named_attribute("caption").is_some());
732
733 attribute_override
734 || matches!(
735 parser.attribute_value("caption"),
736 InterpretedValue::Value(value) if !value.is_empty(),
737 )
738 }
739
740 fn block_reftext<'a>(block: &'a Block<'a>, anchor_reftext: Option<&str>) -> Option<CowStr<'a>> {
754 if let Some(attr) = block
755 .attrlist()
756 .and_then(|attrlist| attrlist.named_attribute("reftext"))
757 {
758 return Some(CowStr::from(attr.value()));
759 }
760
761 if let Some(anchor_reftext) = anchor_reftext {
762 return Some(CowStr::from(anchor_reftext.to_string()));
763 }
764
765 block.title().map(CowStr::from)
766 }
767
768 fn register_block_id(
773 id: Option<&str>,
774 reftext: Option<&str>,
775 signifier: Option<XrefSignifier>,
776 span: Span<'src>,
777 parser: &mut Parser,
778 warnings: &mut Vec<Warning<'src>>,
779 ) {
780 if let Some(id) = id {
781 match parser.register_ref(id, reftext, RefType::Anchor) {
782 Ok(()) => {
783 if let Some(signifier) = signifier {
784 parser.set_ref_signifier(id, signifier);
785 }
786 }
787 Err(_duplicate_error) => {
788 warnings.push(Warning {
790 source: span,
791 warning: WarningType::DuplicateId(id.to_string()),
792 origin: None,
793 });
794 }
795 }
796 }
797 }
798
799 pub(crate) fn as_list_item(&self) -> Option<&ListItem<'src>> {
802 match self {
803 Self::ListItem(li) => Some(li),
804 _ => None,
805 }
806 }
807
808 pub(crate) fn resolve_references(
816 &mut self,
817 resolver: &dyn ReferenceResolver,
818 renderer: &dyn InlineSubstitutionRenderer,
819 warnings: &mut ReferenceWarnings<'src>,
820 ) {
821 if let Some(content) = self.content_mut() {
828 content.resolve_references(resolver, renderer, warnings);
829 }
830
831 if let Self::Table(table) = self {
834 table.resolve_references(resolver, renderer, warnings);
835 }
836
837 if let Self::Quote(quote) = self {
841 quote.resolve_references(resolver, renderer, warnings);
842 }
843
844 for child in self.child_blocks_mut() {
845 child.resolve_references(resolver, renderer, warnings);
846 }
847 }
848
849 pub(crate) fn block_title_content_mut(&mut self) -> Option<&mut Content<'src>> {
858 match self {
859 Self::Simple(b) => b.title_content_mut(),
860 Self::Media(b) => b.title_content_mut(),
861 Self::List(b) => b.title_content_mut(),
862 Self::RawDelimited(b) => b.title_content_mut(),
863 Self::CompoundDelimited(b) => b.title_content_mut(),
864 Self::Admonition(b) => b.title_content_mut(),
865 Self::Quote(b) => b.title_content_mut(),
866 Self::Table(b) => b.title_content_mut(),
867 Self::Break(b) => b.title_content_mut(),
868 _ => None,
869 }
870 }
871}
872
873impl<'src> IsBlock<'src> for Block<'src> {
874 fn content_model(&self) -> ContentModel {
875 match self {
876 Self::Simple(_) => ContentModel::Simple,
877 Self::Media(b) => b.content_model(),
878 Self::Section(_) => ContentModel::Compound,
879 Self::List(b) => b.content_model(),
880 Self::ListItem(b) => b.content_model(),
881 Self::RawDelimited(b) => b.content_model(),
882 Self::CompoundDelimited(b) => b.content_model(),
883 Self::Admonition(b) => b.content_model(),
884 Self::Quote(b) => b.content_model(),
885 Self::Table(b) => b.content_model(),
886 Self::Preamble(b) => b.content_model(),
887 Self::Break(b) => b.content_model(),
888 Self::DocumentAttribute(b) => b.content_model(),
889 }
890 }
891
892 fn declared_style(&'src self) -> Option<&'src str> {
893 match self {
894 Self::Simple(b) => b.declared_style(),
895 Self::Media(b) => b.declared_style(),
896 Self::Section(b) => b.declared_style(),
897 Self::List(b) => b.declared_style(),
898 Self::ListItem(b) => b.declared_style(),
899 Self::RawDelimited(b) => b.declared_style(),
900 Self::CompoundDelimited(b) => b.declared_style(),
901 Self::Admonition(b) => b.declared_style(),
902 Self::Quote(b) => b.declared_style(),
903 Self::Table(b) => b.declared_style(),
904 Self::Preamble(b) => b.declared_style(),
905 Self::Break(b) => b.declared_style(),
906 Self::DocumentAttribute(b) => b.declared_style(),
907 }
908 }
909
910 fn rendered_content(&'src self) -> Option<&'src str> {
911 match self {
912 Self::Simple(b) => b.rendered_content(),
913 Self::Media(b) => b.rendered_content(),
914 Self::Section(b) => b.rendered_content(),
915 Self::List(b) => b.rendered_content(),
916 Self::ListItem(b) => b.rendered_content(),
917 Self::RawDelimited(b) => b.rendered_content(),
918 Self::CompoundDelimited(b) => b.rendered_content(),
919 Self::Admonition(b) => b.rendered_content(),
920 Self::Quote(b) => b.rendered_content(),
921 Self::Table(b) => b.rendered_content(),
922 Self::Preamble(b) => b.rendered_content(),
923 Self::Break(b) => b.rendered_content(),
924 Self::DocumentAttribute(b) => b.rendered_content(),
925 }
926 }
927
928 fn raw_context(&self) -> CowStr<'src> {
929 match self {
930 Self::Simple(b) => b.raw_context(),
931 Self::Media(b) => b.raw_context(),
932 Self::Section(b) => b.raw_context(),
933 Self::List(b) => b.raw_context(),
934 Self::ListItem(b) => b.raw_context(),
935 Self::RawDelimited(b) => b.raw_context(),
936 Self::CompoundDelimited(b) => b.raw_context(),
937 Self::Admonition(b) => b.raw_context(),
938 Self::Quote(b) => b.raw_context(),
939 Self::Table(b) => b.raw_context(),
940 Self::Preamble(b) => b.raw_context(),
941 Self::Break(b) => b.raw_context(),
942 Self::DocumentAttribute(b) => b.raw_context(),
943 }
944 }
945
946 fn child_blocks_mut(&mut self) -> &mut [Block<'src>] {
947 match self {
948 Self::Simple(b) => b.child_blocks_mut(),
949 Self::Media(b) => b.child_blocks_mut(),
950 Self::Section(b) => b.child_blocks_mut(),
951 Self::List(b) => b.child_blocks_mut(),
952 Self::ListItem(b) => b.child_blocks_mut(),
953 Self::RawDelimited(b) => b.child_blocks_mut(),
954 Self::CompoundDelimited(b) => b.child_blocks_mut(),
955 Self::Admonition(b) => b.child_blocks_mut(),
956 Self::Quote(b) => b.child_blocks_mut(),
957 Self::Table(b) => b.child_blocks_mut(),
958 Self::Preamble(b) => b.child_blocks_mut(),
959 Self::Break(b) => b.child_blocks_mut(),
960 Self::DocumentAttribute(b) => b.child_blocks_mut(),
961 }
962 }
963
964 fn content_mut(&mut self) -> Option<&mut Content<'src>> {
965 match self {
966 Self::Simple(b) => b.content_mut(),
967 Self::Media(b) => b.content_mut(),
968 Self::Section(b) => b.content_mut(),
969 Self::List(b) => b.content_mut(),
970 Self::ListItem(b) => b.content_mut(),
971 Self::RawDelimited(b) => b.content_mut(),
972 Self::CompoundDelimited(b) => b.content_mut(),
973 Self::Admonition(b) => b.content_mut(),
974 Self::Quote(b) => b.content_mut(),
975 Self::Table(b) => b.content_mut(),
976 Self::Preamble(b) => b.content_mut(),
977 Self::Break(b) => b.content_mut(),
978 Self::DocumentAttribute(b) => b.content_mut(),
979 }
980 }
981
982 fn title_source(&'src self) -> Option<Span<'src>> {
983 match self {
984 Self::Simple(b) => b.title_source(),
985 Self::Media(b) => b.title_source(),
986 Self::Section(b) => b.title_source(),
987 Self::List(b) => b.title_source(),
988 Self::ListItem(b) => b.title_source(),
989 Self::RawDelimited(b) => b.title_source(),
990 Self::CompoundDelimited(b) => b.title_source(),
991 Self::Admonition(b) => b.title_source(),
992 Self::Quote(b) => b.title_source(),
993 Self::Table(b) => b.title_source(),
994 Self::Preamble(b) => b.title_source(),
995 Self::Break(b) => b.title_source(),
996 Self::DocumentAttribute(b) => b.title_source(),
997 }
998 }
999
1000 fn title(&self) -> Option<&str> {
1001 match self {
1002 Self::Simple(b) => b.title(),
1003 Self::Media(b) => b.title(),
1004 Self::Section(b) => b.title(),
1005 Self::List(b) => b.title(),
1006 Self::ListItem(b) => b.title(),
1007 Self::RawDelimited(b) => b.title(),
1008 Self::CompoundDelimited(b) => b.title(),
1009 Self::Admonition(b) => b.title(),
1010 Self::Quote(b) => b.title(),
1011 Self::Table(b) => b.title(),
1012 Self::Preamble(b) => b.title(),
1013 Self::Break(b) => b.title(),
1014 Self::DocumentAttribute(b) => b.title(),
1015 }
1016 }
1017
1018 fn caption(&self) -> Option<&str> {
1019 match self {
1020 Self::Simple(b) => b.caption(),
1021 Self::Media(b) => b.caption(),
1022 Self::Section(b) => b.caption(),
1023 Self::List(b) => b.caption(),
1024 Self::ListItem(b) => b.caption(),
1025 Self::RawDelimited(b) => b.caption(),
1026 Self::CompoundDelimited(b) => b.caption(),
1027 Self::Admonition(b) => b.caption(),
1028 Self::Quote(b) => b.caption(),
1029 Self::Table(b) => b.caption(),
1030 Self::Preamble(b) => b.caption(),
1031 Self::Break(b) => b.caption(),
1032 Self::DocumentAttribute(b) => b.caption(),
1033 }
1034 }
1035
1036 fn number(&self) -> Option<usize> {
1037 match self {
1038 Self::Simple(b) => b.number(),
1039 Self::Media(b) => b.number(),
1040 Self::Section(b) => b.number(),
1041 Self::List(b) => b.number(),
1042 Self::ListItem(b) => b.number(),
1043 Self::RawDelimited(b) => b.number(),
1044 Self::CompoundDelimited(b) => b.number(),
1045 Self::Admonition(b) => b.number(),
1046 Self::Quote(b) => b.number(),
1047 Self::Table(b) => b.number(),
1048 Self::Preamble(b) => b.number(),
1049 Self::Break(b) => b.number(),
1050 Self::DocumentAttribute(b) => b.number(),
1051 }
1052 }
1053
1054 fn id(&'src self) -> Option<&'src str> {
1055 match self {
1069 Self::Media(b) => b.id(),
1070 Self::Section(b) => b.id(),
1071 _ => self
1072 .anchor()
1073 .map(|a| a.data())
1074 .or_else(|| self.attrlist().and_then(|attrlist| attrlist.id())),
1075 }
1076 }
1077
1078 fn anchor(&'src self) -> Option<Span<'src>> {
1079 match self {
1080 Self::Simple(b) => b.anchor(),
1081 Self::Media(b) => b.anchor(),
1082 Self::Section(b) => b.anchor(),
1083 Self::List(b) => b.anchor(),
1084 Self::ListItem(b) => b.anchor(),
1085 Self::RawDelimited(b) => b.anchor(),
1086 Self::CompoundDelimited(b) => b.anchor(),
1087 Self::Admonition(b) => b.anchor(),
1088 Self::Quote(b) => b.anchor(),
1089 Self::Table(b) => b.anchor(),
1090 Self::Preamble(b) => b.anchor(),
1091 Self::Break(b) => b.anchor(),
1092 Self::DocumentAttribute(b) => b.anchor(),
1093 }
1094 }
1095
1096 fn anchor_reftext(&'src self) -> Option<Span<'src>> {
1097 match self {
1098 Self::Simple(b) => b.anchor_reftext(),
1099 Self::Media(b) => b.anchor_reftext(),
1100 Self::Section(b) => b.anchor_reftext(),
1101 Self::List(b) => b.anchor_reftext(),
1102 Self::ListItem(b) => b.anchor_reftext(),
1103 Self::RawDelimited(b) => b.anchor_reftext(),
1104 Self::CompoundDelimited(b) => b.anchor_reftext(),
1105 Self::Admonition(b) => b.anchor_reftext(),
1106 Self::Quote(b) => b.anchor_reftext(),
1107 Self::Table(b) => b.anchor_reftext(),
1108 Self::Preamble(b) => b.anchor_reftext(),
1109 Self::Break(b) => b.anchor_reftext(),
1110 Self::DocumentAttribute(b) => b.anchor_reftext(),
1111 }
1112 }
1113
1114 fn attrlist(&'src self) -> Option<&'src Attrlist<'src>> {
1115 match self {
1116 Self::Simple(b) => b.attrlist(),
1117 Self::Media(b) => b.attrlist(),
1118 Self::Section(b) => b.attrlist(),
1119 Self::List(b) => b.attrlist(),
1120 Self::ListItem(b) => b.attrlist(),
1121 Self::RawDelimited(b) => b.attrlist(),
1122 Self::CompoundDelimited(b) => b.attrlist(),
1123 Self::Admonition(b) => b.attrlist(),
1124 Self::Quote(b) => b.attrlist(),
1125 Self::Table(b) => b.attrlist(),
1126 Self::Preamble(b) => b.attrlist(),
1127 Self::Break(b) => b.attrlist(),
1128 Self::DocumentAttribute(b) => b.attrlist(),
1129 }
1130 }
1131
1132 fn substitution_group(&self) -> SubstitutionGroup {
1133 match self {
1134 Self::Simple(b) => b.substitution_group(),
1135 Self::Media(b) => b.substitution_group(),
1136 Self::Section(b) => b.substitution_group(),
1137 Self::List(b) => b.substitution_group(),
1138 Self::ListItem(b) => b.substitution_group(),
1139 Self::RawDelimited(b) => b.substitution_group(),
1140 Self::CompoundDelimited(b) => b.substitution_group(),
1141 Self::Admonition(b) => b.substitution_group(),
1142 Self::Quote(b) => b.substitution_group(),
1143 Self::Table(b) => b.substitution_group(),
1144 Self::Preamble(b) => b.substitution_group(),
1145 Self::Break(b) => b.substitution_group(),
1146 Self::DocumentAttribute(b) => b.substitution_group(),
1147 }
1148 }
1149}
1150
1151impl<'src> HasSpan<'src> for Block<'src> {
1152 fn span(&self) -> Span<'src> {
1153 match self {
1154 Self::Simple(b) => b.span(),
1155 Self::Media(b) => b.span(),
1156 Self::Section(b) => b.span(),
1157 Self::List(b) => b.span(),
1158 Self::ListItem(b) => b.span(),
1159 Self::RawDelimited(b) => b.span(),
1160 Self::CompoundDelimited(b) => b.span(),
1161 Self::Admonition(b) => b.span(),
1162 Self::Quote(b) => b.span(),
1163 Self::Table(b) => b.span(),
1164 Self::Preamble(b) => b.span(),
1165 Self::Break(b) => b.span(),
1166 Self::DocumentAttribute(b) => b.span(),
1167 }
1168 }
1169}