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, TocBlock, 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 Toc(TocBlock<'src>),
84
85 DocumentAttribute(Attribute<'src>),
88}
89
90impl<'src> std::fmt::Debug for Block<'src> {
91 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
92 match self {
93 Block::Simple(block) => f.debug_tuple("Block::Simple").field(block).finish(),
94 Block::Media(block) => f.debug_tuple("Block::Media").field(block).finish(),
95 Block::Section(block) => f.debug_tuple("Block::Section").field(block).finish(),
96 Block::List(block) => f.debug_tuple("Block::List").field(block).finish(),
97 Block::ListItem(block) => f.debug_tuple("Block::ListItem").field(block).finish(),
98
99 Block::RawDelimited(block) => {
100 f.debug_tuple("Block::RawDelimited").field(block).finish()
101 }
102
103 Block::CompoundDelimited(block) => f
104 .debug_tuple("Block::CompoundDelimited")
105 .field(block)
106 .finish(),
107
108 Block::Admonition(block) => f.debug_tuple("Block::Admonition").field(block).finish(),
109 Block::Quote(block) => f.debug_tuple("Block::Quote").field(block).finish(),
110 Block::Table(block) => f.debug_tuple("Block::Table").field(block).finish(),
111 Block::Preamble(block) => f.debug_tuple("Block::Preamble").field(block).finish(),
112 Block::Break(break_) => f.debug_tuple("Block::Break").field(break_).finish(),
113 Block::Toc(block) => f.debug_tuple("Block::Toc").field(block).finish(),
114
115 Block::DocumentAttribute(block) => f
116 .debug_tuple("Block::DocumentAttribute")
117 .field(block)
118 .finish(),
119 }
120 }
121}
122
123#[allow(clippy::large_enum_variant)]
135pub(crate) enum BlockParseOutcome<'src> {
136 Parsed(MatchedItem<'src, Block<'src>>),
138
139 Dropped(Span<'src>),
150
151 NoMatch,
153}
154
155impl<'src> Block<'src> {
156 #[cfg(test)]
165 pub(crate) fn parse(
166 source: Span<'src>,
167 parser: &mut Parser,
168 ) -> MatchAndWarnings<'src, Option<MatchedItem<'src, Self>>> {
169 let MatchAndWarnings { item, warnings } = Self::parse_internal(source, parser, None, false);
170
171 MatchAndWarnings {
172 item: match item {
173 BlockParseOutcome::Parsed(mi) => Some(mi),
174 BlockParseOutcome::Dropped(_) | BlockParseOutcome::NoMatch => None,
175 },
176 warnings,
177 }
178 }
179
180 pub(crate) fn parse_with_outcome(
187 source: Span<'src>,
188 parser: &mut Parser,
189 ) -> MatchAndWarnings<'src, BlockParseOutcome<'src>> {
190 Self::parse_internal(source, parser, None, false)
191 }
192
193 pub(crate) fn parse_for_list_item(
204 source: Span<'src>,
205 parser: &mut Parser,
206 parent_list_markers: &[ListItemMarker<'src>],
207 is_continuation: bool,
208 ) -> MatchAndWarnings<'src, BlockParseOutcome<'src>> {
209 Self::parse_internal(source, parser, Some(parent_list_markers), is_continuation)
210 }
211
212 fn parse_internal(
215 source: Span<'src>,
216 parser: &mut Parser,
217 parent_list_markers: Option<&[ListItemMarker<'src>]>,
218 is_continuation: bool,
219 ) -> MatchAndWarnings<'src, BlockParseOutcome<'src>> {
220 let first_line = source.take_line().item.discard_whitespace();
224
225 if let Some(first_char) = first_line.chars().next()
228 && !matches!(
229 first_char,
230 '.' | '#'
231 | '='
232 | '/'
233 | '-'
234 | '+'
235 | '*'
236 | '_'
237 | '`'
238 | '['
239 | ':'
240 | '\''
241 | '<'
242 | '>'
243 | '"'
244 | '•'
245 )
246 && !first_line.contains("::")
247 && !first_line.contains(";;")
248 && !TableBlock::is_table_delimiter(&first_line)
249 && !ListItemMarker::starts_with_marker(first_line)
250 && !starts_with_admonition_label(first_line)
251 && parent_list_markers.is_none()
252 && parser.pending_block_title.is_none()
253 && let Some(MatchedItem {
254 item: simple_block,
255 after,
256 }) = SimpleBlock::parse_fast(source, parser)
257 {
258 let mut warnings = vec![];
259 let block = Self::Simple(simple_block);
260
261 Self::register_block_id(
264 block.id(),
265 Self::block_reftext(&block, None).as_deref(),
266 Self::block_signifier(&block, parser),
267 block.span(),
268 parser,
269 &mut warnings,
270 );
271
272 return MatchAndWarnings {
273 item: BlockParseOutcome::Parsed(MatchedItem { item: block, after }),
274 warnings,
275 };
276 }
277
278 if first_line.starts_with(':')
280 && (first_line.ends_with(':') || first_line.contains(": "))
281 && let Some(attr) = Attribute::parse(source, parser)
282 {
283 let mut warnings: Vec<Warning<'src>> = vec![];
284 parser.set_attribute_from_body(&attr.item, &mut warnings);
285
286 return MatchAndWarnings {
287 item: BlockParseOutcome::Parsed(MatchedItem {
288 item: Self::DocumentAttribute(attr.item),
289 after: attr.after,
290 }),
291 warnings,
292 };
293 }
294
295 let MatchAndWarnings {
298 item: mut metadata,
299 mut warnings,
300 } = BlockMetadata::parse(source, parser);
301
302 if let Some(pending_title) = parser.pending_block_title.take()
308 && metadata.title.is_none()
309 {
310 metadata.title = Some(crate::content::Content::from_owned_title(
314 metadata.block_start,
315 pending_title,
316 ));
317 }
318
319 if parent_list_markers.is_none() && !metadata.is_empty() {
334 let after_blanks = metadata.block_start.discard_empty_lines();
335 if after_blanks != metadata.block_start && !after_blanks.is_empty() {
336 metadata.block_start = after_blanks;
337 }
338 }
339
340 let anchor_reftext = metadata
346 .anchor_reftext
347 .as_ref()
348 .map(|span| substitute_attributes_in_reftext(*span, parser));
349
350 let is_literal =
358 metadata.attrlist.as_ref().and_then(|a| a.block_style()) == Some("literal") && {
359 let first_line = metadata.block_start.take_normalized_line().item;
360 !RawDelimitedBlock::is_valid_delimiter(&first_line)
361 && !CompoundDelimitedBlock::is_valid_delimiter(&first_line)
362 && !TableBlock::is_table_delimiter(&first_line)
363 };
364
365 let mut simple_block_mi = None;
372
373 if !is_literal {
374 if let Some(mut adm_maw) = AdmonitionBlock::parse(&metadata, parser)
375 && let Some(adm) = adm_maw.item
376 {
377 if !adm_maw.warnings.is_empty() {
378 warnings.append(&mut adm_maw.warnings);
379 }
380
381 let block = Self::Admonition(adm.item);
382
383 Self::register_block_id(
384 block.id(),
385 Self::block_reftext(&block, anchor_reftext.as_deref()).as_deref(),
386 Self::block_signifier(&block, parser),
387 block.span(),
388 parser,
389 &mut warnings,
390 );
391
392 return MatchAndWarnings {
393 item: BlockParseOutcome::Parsed(MatchedItem {
394 item: block,
395 after: adm.after,
396 }),
397 warnings,
398 };
399 }
400
401 if let Some(mut quote_maw) = QuoteBlock::parse(&metadata, parser)
402 && let Some(quote) = quote_maw.item
403 {
404 if !quote_maw.warnings.is_empty() {
405 warnings.append(&mut quote_maw.warnings);
406 }
407
408 let block = Self::Quote(quote.item);
409
410 Self::register_block_id(
411 block.id(),
412 Self::block_reftext(&block, anchor_reftext.as_deref()).as_deref(),
413 Self::block_signifier(&block, parser),
414 block.span(),
415 parser,
416 &mut warnings,
417 );
418
419 return MatchAndWarnings {
420 item: BlockParseOutcome::Parsed(MatchedItem {
421 item: block,
422 after: quote.after,
423 }),
424 warnings,
425 };
426 }
427
428 if let Some(mut rdb_maw) = RawDelimitedBlock::parse(&metadata, parser)
429 && let Some(rdb) = rdb_maw.item
430 {
431 if !rdb_maw.warnings.is_empty() {
432 warnings.append(&mut rdb_maw.warnings);
433 }
434
435 let block = Self::RawDelimited(rdb.item);
436
437 Self::register_block_id(
438 block.id(),
439 Self::block_reftext(&block, anchor_reftext.as_deref()).as_deref(),
440 Self::block_signifier(&block, parser),
441 block.span(),
442 parser,
443 &mut warnings,
444 );
445
446 return MatchAndWarnings {
447 item: BlockParseOutcome::Parsed(MatchedItem {
448 item: block,
449 after: rdb.after,
450 }),
451 warnings,
452 };
453 }
454
455 if let Some(mut cdb_maw) = CompoundDelimitedBlock::parse(&metadata, parser)
456 && let Some(cdb) = cdb_maw.item
457 {
458 if !cdb_maw.warnings.is_empty() {
459 warnings.append(&mut cdb_maw.warnings);
460 }
461
462 let block = Self::CompoundDelimited(cdb.item);
463
464 Self::register_block_id(
465 block.id(),
466 Self::block_reftext(&block, anchor_reftext.as_deref()).as_deref(),
467 Self::block_signifier(&block, parser),
468 block.span(),
469 parser,
470 &mut warnings,
471 );
472
473 return MatchAndWarnings {
474 item: BlockParseOutcome::Parsed(MatchedItem {
475 item: block,
476 after: cdb.after,
477 }),
478 warnings,
479 };
480 }
481
482 if let Some(mut table_maw) = TableBlock::parse(&metadata, parser)
483 && let Some(table) = table_maw.item
484 {
485 if !table_maw.warnings.is_empty() {
486 warnings.append(&mut table_maw.warnings);
487 }
488
489 let block = Self::Table(table.item);
490
491 Self::register_block_id(
492 block.id(),
493 Self::block_reftext(&block, anchor_reftext.as_deref()).as_deref(),
494 Self::block_signifier(&block, parser),
495 block.span(),
496 parser,
497 &mut warnings,
498 );
499
500 return MatchAndWarnings {
501 item: BlockParseOutcome::Parsed(MatchedItem {
502 item: block,
503 after: table.after,
504 }),
505 warnings,
506 };
507 }
508
509 let line = metadata.block_start.take_normalized_line();
511
512 if line.item.starts_with("image::")
513 || line.item.starts_with("video::")
514 || line.item.starts_with("audio::")
515 {
516 let mut media_block_maw = MediaBlock::parse(&metadata, parser);
517
518 if let Some(mut media_block) = media_block_maw.item {
519 if !media_block_maw.warnings.is_empty() {
523 warnings.append(&mut media_block_maw.warnings);
524 }
525
526 if media_block.item.resolve_target(parser) == TargetResolution::Drop {
530 return MatchAndWarnings {
531 item: BlockParseOutcome::Dropped(media_block.after),
532 warnings,
533 };
534 }
535
536 media_block.item.assign_caption(parser);
540
541 let block = Self::Media(media_block.item);
542
543 Self::register_block_id(
544 block.id(),
545 Self::block_reftext(&block, anchor_reftext.as_deref()).as_deref(),
546 Self::block_signifier(&block, parser),
547 block.span(),
548 parser,
549 &mut warnings,
550 );
551
552 return MatchAndWarnings {
553 item: BlockParseOutcome::Parsed(MatchedItem {
554 item: block,
555 after: media_block.after,
556 }),
557 warnings,
558 };
559 }
560
561 }
564
565 if line.item.starts_with("toc::") {
566 let mut toc_block_maw = TocBlock::parse(&metadata, parser);
567
568 if let Some(toc_block) = toc_block_maw.item {
569 if !toc_block_maw.warnings.is_empty() {
573 warnings.append(&mut toc_block_maw.warnings);
574 }
575
576 let block = Self::Toc(toc_block.item);
577
578 Self::register_block_id(
579 block.id(),
580 Self::block_reftext(&block, anchor_reftext.as_deref()).as_deref(),
581 Self::block_signifier(&block, parser),
582 block.span(),
583 parser,
584 &mut warnings,
585 );
586
587 return MatchAndWarnings {
588 item: BlockParseOutcome::Parsed(MatchedItem {
589 item: block,
590 after: toc_block.after,
591 }),
592 warnings,
593 };
594 }
595
596 }
599
600 if (line.item.starts_with('=') || line.item.starts_with('#'))
601 && let Some(mi_section_block) =
602 SectionBlock::parse(&metadata, parser, &mut warnings)
603 {
604 return MatchAndWarnings {
608 item: BlockParseOutcome::Parsed(MatchedItem {
609 item: Self::Section(mi_section_block.item),
610 after: mi_section_block.after,
611 }),
612 warnings,
613 };
614 }
615
616 if (line.item.starts_with('\'')
617 || line.item.starts_with('-')
618 || line.item.starts_with('*')
619 || line.item.starts_with('_')
620 || line.item.starts_with('<'))
621 && let Some(mi_break) = Break::parse(&metadata, parser)
622 {
623 return MatchAndWarnings {
626 item: BlockParseOutcome::Parsed(MatchedItem {
627 item: Self::Break(mi_break.item),
628 after: mi_break.after,
629 }),
630 warnings,
631 };
632 }
633
634 if parent_list_markers.is_none()
638 && let Some(mi_list) = ListBlock::parse(&metadata, parser, &mut warnings)
639 {
640 return MatchAndWarnings {
641 item: BlockParseOutcome::Parsed(MatchedItem {
642 item: Self::List(mi_list.item),
643 after: mi_list.after,
644 }),
645 warnings,
646 };
647 }
648
649 simple_block_mi = if let Some(plm) = parent_list_markers {
656 SimpleBlock::parse_for_list_item(&metadata, parser, is_continuation, plm)
657 } else {
658 SimpleBlock::parse(&metadata, parser)
659 };
660
661 if simple_block_mi.is_none() {
662 if !metadata.is_empty() {
663 warnings.push(Warning {
667 source: metadata.source,
668 warning: WarningType::MissingBlockAfterTitleOrAttributeList,
669 origin: None,
670 });
671
672 metadata.title_source = None;
676 metadata.title = None;
677 metadata.anchor = None;
678 metadata.attrlist = None;
679 metadata.block_start = metadata.source;
680 } else if !metadata.source.data().is_empty() {
681 return MatchAndWarnings {
690 item: BlockParseOutcome::Dropped(metadata.block_start),
691 warnings,
692 };
693 }
694 }
695 }
696
697 let simple_block_mi = match simple_block_mi {
701 Some(mi) => Some(mi),
702 None => {
703 if let Some(plm) = parent_list_markers {
704 SimpleBlock::parse_for_list_item(&metadata, parser, is_continuation, plm)
705 } else {
706 SimpleBlock::parse(&metadata, parser)
707 }
708 }
709 };
710
711 let mut result = MatchAndWarnings {
712 item: match simple_block_mi {
713 Some(mi) => BlockParseOutcome::Parsed(MatchedItem {
714 item: Self::Simple(mi.item),
715 after: mi.after,
716 }),
717 None => BlockParseOutcome::NoMatch,
718 },
719 warnings,
720 };
721
722 if let BlockParseOutcome::Parsed(ref matched_item) = result.item {
723 Self::register_block_id(
724 matched_item.item.id(),
725 Self::block_reftext(&matched_item.item, anchor_reftext.as_deref()).as_deref(),
726 Self::block_signifier(&matched_item.item, parser),
727 matched_item.item.span(),
728 parser,
729 &mut result.warnings,
730 );
731 }
732
733 result
734 }
735
736 fn block_signifier<'a>(block: &'a Block<'a>, parser: &Parser) -> Option<XrefSignifier> {
747 let caption = block.caption()?;
749
750 let has_explicit_reftext = block
751 .attrlist()
752 .and_then(|attrlist| attrlist.named_attribute("reftext"))
753 .is_some()
754 || block.anchor_reftext().is_some();
755 if has_explicit_reftext {
756 return None;
757 }
758
759 if Self::has_caption_override(block, parser) {
765 return None;
766 }
767
768 let label = caption.strip_suffix(". ").unwrap_or(caption).to_string();
771 Some(XrefSignifier {
772 label,
773 emphasize: false,
774 })
775 }
776
777 fn has_caption_override<'a>(block: &'a Block<'a>, parser: &Parser) -> bool {
787 let attribute_override = block
788 .attrlist()
789 .and_then(|attrlist| attrlist.named_attribute("caption"))
790 .is_some()
791 || matches!(block, Block::Media(media)
792 if media.macro_attrlist().named_attribute("caption").is_some());
793
794 attribute_override
795 || matches!(
796 parser.attribute_value("caption"),
797 InterpretedValue::Value(value) if !value.is_empty(),
798 )
799 }
800
801 fn block_reftext<'a>(block: &'a Block<'a>, anchor_reftext: Option<&str>) -> Option<CowStr<'a>> {
815 if let Some(attr) = block
816 .attrlist()
817 .and_then(|attrlist| attrlist.named_attribute("reftext"))
818 {
819 return Some(CowStr::from(attr.value()));
820 }
821
822 if let Some(anchor_reftext) = anchor_reftext {
823 return Some(CowStr::from(anchor_reftext.to_string()));
824 }
825
826 block.title().map(CowStr::from)
827 }
828
829 fn register_block_id(
834 id: Option<&str>,
835 reftext: Option<&str>,
836 signifier: Option<XrefSignifier>,
837 span: Span<'src>,
838 parser: &mut Parser,
839 warnings: &mut Vec<Warning<'src>>,
840 ) {
841 if let Some(id) = id {
842 match parser.register_ref(id, reftext, RefType::Anchor) {
843 Ok(()) => {
844 if let Some(signifier) = signifier {
845 parser.set_ref_signifier(id, signifier);
846 }
847 }
848 Err(_duplicate_error) => {
849 warnings.push(Warning {
851 source: span,
852 warning: WarningType::DuplicateId(id.to_string()),
853 origin: None,
854 });
855 }
856 }
857 }
858 }
859
860 pub(crate) fn as_list_item(&self) -> Option<&ListItem<'src>> {
863 match self {
864 Self::ListItem(li) => Some(li),
865 _ => None,
866 }
867 }
868
869 pub(crate) fn resolve_references(
877 &mut self,
878 resolver: &dyn ReferenceResolver,
879 renderer: &dyn InlineSubstitutionRenderer,
880 warnings: &mut ReferenceWarnings<'src>,
881 ) {
882 if let Some(content) = self.content_mut() {
889 content.resolve_references(resolver, renderer, warnings);
890 }
891
892 if let Self::Table(table) = self {
895 table.resolve_references(resolver, renderer, warnings);
896 }
897
898 if let Self::Quote(quote) = self {
902 quote.resolve_references(resolver, renderer, warnings);
903 }
904
905 for child in self.child_blocks_mut() {
906 child.resolve_references(resolver, renderer, warnings);
907 }
908 }
909
910 pub(crate) fn block_title_content_mut(&mut self) -> Option<&mut Content<'src>> {
919 match self {
920 Self::Simple(b) => b.title_content_mut(),
921 Self::Media(b) => b.title_content_mut(),
922 Self::List(b) => b.title_content_mut(),
923 Self::RawDelimited(b) => b.title_content_mut(),
924 Self::CompoundDelimited(b) => b.title_content_mut(),
925 Self::Admonition(b) => b.title_content_mut(),
926 Self::Quote(b) => b.title_content_mut(),
927 Self::Table(b) => b.title_content_mut(),
928 Self::Break(b) => b.title_content_mut(),
929 Self::Toc(b) => b.title_content_mut(),
930 _ => None,
931 }
932 }
933}
934
935impl<'src> IsBlock<'src> for Block<'src> {
936 fn content_model(&self) -> ContentModel {
937 match self {
938 Self::Simple(_) => ContentModel::Simple,
939 Self::Media(b) => b.content_model(),
940 Self::Section(_) => ContentModel::Compound,
941 Self::List(b) => b.content_model(),
942 Self::ListItem(b) => b.content_model(),
943 Self::RawDelimited(b) => b.content_model(),
944 Self::CompoundDelimited(b) => b.content_model(),
945 Self::Admonition(b) => b.content_model(),
946 Self::Quote(b) => b.content_model(),
947 Self::Table(b) => b.content_model(),
948 Self::Preamble(b) => b.content_model(),
949 Self::Break(b) => b.content_model(),
950 Self::Toc(b) => b.content_model(),
951 Self::DocumentAttribute(b) => b.content_model(),
952 }
953 }
954
955 fn declared_style(&'src self) -> Option<&'src str> {
956 match self {
957 Self::Simple(b) => b.declared_style(),
958 Self::Media(b) => b.declared_style(),
959 Self::Section(b) => b.declared_style(),
960 Self::List(b) => b.declared_style(),
961 Self::ListItem(b) => b.declared_style(),
962 Self::RawDelimited(b) => b.declared_style(),
963 Self::CompoundDelimited(b) => b.declared_style(),
964 Self::Admonition(b) => b.declared_style(),
965 Self::Quote(b) => b.declared_style(),
966 Self::Table(b) => b.declared_style(),
967 Self::Preamble(b) => b.declared_style(),
968 Self::Break(b) => b.declared_style(),
969 Self::Toc(b) => b.declared_style(),
970 Self::DocumentAttribute(b) => b.declared_style(),
971 }
972 }
973
974 fn rendered_content(&'src self) -> Option<&'src str> {
975 match self {
976 Self::Simple(b) => b.rendered_content(),
977 Self::Media(b) => b.rendered_content(),
978 Self::Section(b) => b.rendered_content(),
979 Self::List(b) => b.rendered_content(),
980 Self::ListItem(b) => b.rendered_content(),
981 Self::RawDelimited(b) => b.rendered_content(),
982 Self::CompoundDelimited(b) => b.rendered_content(),
983 Self::Admonition(b) => b.rendered_content(),
984 Self::Quote(b) => b.rendered_content(),
985 Self::Table(b) => b.rendered_content(),
986 Self::Preamble(b) => b.rendered_content(),
987 Self::Break(b) => b.rendered_content(),
988 Self::Toc(b) => b.rendered_content(),
989 Self::DocumentAttribute(b) => b.rendered_content(),
990 }
991 }
992
993 fn raw_context(&self) -> CowStr<'src> {
994 match self {
995 Self::Simple(b) => b.raw_context(),
996 Self::Media(b) => b.raw_context(),
997 Self::Section(b) => b.raw_context(),
998 Self::List(b) => b.raw_context(),
999 Self::ListItem(b) => b.raw_context(),
1000 Self::RawDelimited(b) => b.raw_context(),
1001 Self::CompoundDelimited(b) => b.raw_context(),
1002 Self::Admonition(b) => b.raw_context(),
1003 Self::Quote(b) => b.raw_context(),
1004 Self::Table(b) => b.raw_context(),
1005 Self::Preamble(b) => b.raw_context(),
1006 Self::Break(b) => b.raw_context(),
1007 Self::Toc(b) => b.raw_context(),
1008 Self::DocumentAttribute(b) => b.raw_context(),
1009 }
1010 }
1011
1012 fn child_blocks_mut(&mut self) -> &mut [Block<'src>] {
1013 match self {
1014 Self::Simple(b) => b.child_blocks_mut(),
1015 Self::Media(b) => b.child_blocks_mut(),
1016 Self::Section(b) => b.child_blocks_mut(),
1017 Self::List(b) => b.child_blocks_mut(),
1018 Self::ListItem(b) => b.child_blocks_mut(),
1019 Self::RawDelimited(b) => b.child_blocks_mut(),
1020 Self::CompoundDelimited(b) => b.child_blocks_mut(),
1021 Self::Admonition(b) => b.child_blocks_mut(),
1022 Self::Quote(b) => b.child_blocks_mut(),
1023 Self::Table(b) => b.child_blocks_mut(),
1024 Self::Preamble(b) => b.child_blocks_mut(),
1025 Self::Break(b) => b.child_blocks_mut(),
1026 Self::Toc(b) => b.child_blocks_mut(),
1027 Self::DocumentAttribute(b) => b.child_blocks_mut(),
1028 }
1029 }
1030
1031 fn content_mut(&mut self) -> Option<&mut Content<'src>> {
1032 match self {
1033 Self::Simple(b) => b.content_mut(),
1034 Self::Media(b) => b.content_mut(),
1035 Self::Section(b) => b.content_mut(),
1036 Self::List(b) => b.content_mut(),
1037 Self::ListItem(b) => b.content_mut(),
1038 Self::RawDelimited(b) => b.content_mut(),
1039 Self::CompoundDelimited(b) => b.content_mut(),
1040 Self::Admonition(b) => b.content_mut(),
1041 Self::Quote(b) => b.content_mut(),
1042 Self::Table(b) => b.content_mut(),
1043 Self::Preamble(b) => b.content_mut(),
1044 Self::Break(b) => b.content_mut(),
1045 Self::Toc(b) => b.content_mut(),
1046 Self::DocumentAttribute(b) => b.content_mut(),
1047 }
1048 }
1049
1050 fn title_source(&'src self) -> Option<Span<'src>> {
1051 match self {
1052 Self::Simple(b) => b.title_source(),
1053 Self::Media(b) => b.title_source(),
1054 Self::Section(b) => b.title_source(),
1055 Self::List(b) => b.title_source(),
1056 Self::ListItem(b) => b.title_source(),
1057 Self::RawDelimited(b) => b.title_source(),
1058 Self::CompoundDelimited(b) => b.title_source(),
1059 Self::Admonition(b) => b.title_source(),
1060 Self::Quote(b) => b.title_source(),
1061 Self::Table(b) => b.title_source(),
1062 Self::Preamble(b) => b.title_source(),
1063 Self::Break(b) => b.title_source(),
1064 Self::Toc(b) => b.title_source(),
1065 Self::DocumentAttribute(b) => b.title_source(),
1066 }
1067 }
1068
1069 fn title(&self) -> Option<&str> {
1070 match self {
1071 Self::Simple(b) => b.title(),
1072 Self::Media(b) => b.title(),
1073 Self::Section(b) => b.title(),
1074 Self::List(b) => b.title(),
1075 Self::ListItem(b) => b.title(),
1076 Self::RawDelimited(b) => b.title(),
1077 Self::CompoundDelimited(b) => b.title(),
1078 Self::Admonition(b) => b.title(),
1079 Self::Quote(b) => b.title(),
1080 Self::Table(b) => b.title(),
1081 Self::Preamble(b) => b.title(),
1082 Self::Break(b) => b.title(),
1083 Self::Toc(b) => b.title(),
1084 Self::DocumentAttribute(b) => b.title(),
1085 }
1086 }
1087
1088 fn caption(&self) -> Option<&str> {
1089 match self {
1090 Self::Simple(b) => b.caption(),
1091 Self::Media(b) => b.caption(),
1092 Self::Section(b) => b.caption(),
1093 Self::List(b) => b.caption(),
1094 Self::ListItem(b) => b.caption(),
1095 Self::RawDelimited(b) => b.caption(),
1096 Self::CompoundDelimited(b) => b.caption(),
1097 Self::Admonition(b) => b.caption(),
1098 Self::Quote(b) => b.caption(),
1099 Self::Table(b) => b.caption(),
1100 Self::Preamble(b) => b.caption(),
1101 Self::Break(b) => b.caption(),
1102 Self::Toc(b) => b.caption(),
1103 Self::DocumentAttribute(b) => b.caption(),
1104 }
1105 }
1106
1107 fn number(&self) -> Option<usize> {
1108 match self {
1109 Self::Simple(b) => b.number(),
1110 Self::Media(b) => b.number(),
1111 Self::Section(b) => b.number(),
1112 Self::List(b) => b.number(),
1113 Self::ListItem(b) => b.number(),
1114 Self::RawDelimited(b) => b.number(),
1115 Self::CompoundDelimited(b) => b.number(),
1116 Self::Admonition(b) => b.number(),
1117 Self::Quote(b) => b.number(),
1118 Self::Table(b) => b.number(),
1119 Self::Preamble(b) => b.number(),
1120 Self::Break(b) => b.number(),
1121 Self::Toc(b) => b.number(),
1122 Self::DocumentAttribute(b) => b.number(),
1123 }
1124 }
1125
1126 fn id(&'src self) -> Option<&'src str> {
1127 match self {
1144 Self::Media(b) => b.id(),
1145 Self::Section(b) => b.id(),
1146 Self::Toc(b) => b.id(),
1147 _ => self
1148 .anchor()
1149 .map(|a| a.data())
1150 .or_else(|| self.attrlist().and_then(|attrlist| attrlist.id())),
1151 }
1152 }
1153
1154 fn anchor(&'src self) -> Option<Span<'src>> {
1155 match self {
1156 Self::Simple(b) => b.anchor(),
1157 Self::Media(b) => b.anchor(),
1158 Self::Section(b) => b.anchor(),
1159 Self::List(b) => b.anchor(),
1160 Self::ListItem(b) => b.anchor(),
1161 Self::RawDelimited(b) => b.anchor(),
1162 Self::CompoundDelimited(b) => b.anchor(),
1163 Self::Admonition(b) => b.anchor(),
1164 Self::Quote(b) => b.anchor(),
1165 Self::Table(b) => b.anchor(),
1166 Self::Preamble(b) => b.anchor(),
1167 Self::Break(b) => b.anchor(),
1168 Self::Toc(b) => b.anchor(),
1169 Self::DocumentAttribute(b) => b.anchor(),
1170 }
1171 }
1172
1173 fn anchor_reftext(&'src self) -> Option<Span<'src>> {
1174 match self {
1175 Self::Simple(b) => b.anchor_reftext(),
1176 Self::Media(b) => b.anchor_reftext(),
1177 Self::Section(b) => b.anchor_reftext(),
1178 Self::List(b) => b.anchor_reftext(),
1179 Self::ListItem(b) => b.anchor_reftext(),
1180 Self::RawDelimited(b) => b.anchor_reftext(),
1181 Self::CompoundDelimited(b) => b.anchor_reftext(),
1182 Self::Admonition(b) => b.anchor_reftext(),
1183 Self::Quote(b) => b.anchor_reftext(),
1184 Self::Table(b) => b.anchor_reftext(),
1185 Self::Preamble(b) => b.anchor_reftext(),
1186 Self::Break(b) => b.anchor_reftext(),
1187 Self::Toc(b) => b.anchor_reftext(),
1188 Self::DocumentAttribute(b) => b.anchor_reftext(),
1189 }
1190 }
1191
1192 fn attrlist(&'src self) -> Option<&'src Attrlist<'src>> {
1193 match self {
1194 Self::Simple(b) => b.attrlist(),
1195 Self::Media(b) => b.attrlist(),
1196 Self::Section(b) => b.attrlist(),
1197 Self::List(b) => b.attrlist(),
1198 Self::ListItem(b) => b.attrlist(),
1199 Self::RawDelimited(b) => b.attrlist(),
1200 Self::CompoundDelimited(b) => b.attrlist(),
1201 Self::Admonition(b) => b.attrlist(),
1202 Self::Quote(b) => b.attrlist(),
1203 Self::Table(b) => b.attrlist(),
1204 Self::Preamble(b) => b.attrlist(),
1205 Self::Break(b) => b.attrlist(),
1206 Self::Toc(b) => b.attrlist(),
1207 Self::DocumentAttribute(b) => b.attrlist(),
1208 }
1209 }
1210
1211 fn substitution_group(&self) -> SubstitutionGroup {
1212 match self {
1213 Self::Simple(b) => b.substitution_group(),
1214 Self::Media(b) => b.substitution_group(),
1215 Self::Section(b) => b.substitution_group(),
1216 Self::List(b) => b.substitution_group(),
1217 Self::ListItem(b) => b.substitution_group(),
1218 Self::RawDelimited(b) => b.substitution_group(),
1219 Self::CompoundDelimited(b) => b.substitution_group(),
1220 Self::Admonition(b) => b.substitution_group(),
1221 Self::Quote(b) => b.substitution_group(),
1222 Self::Table(b) => b.substitution_group(),
1223 Self::Preamble(b) => b.substitution_group(),
1224 Self::Break(b) => b.substitution_group(),
1225 Self::Toc(b) => b.substitution_group(),
1226 Self::DocumentAttribute(b) => b.substitution_group(),
1227 }
1228 }
1229}
1230
1231impl<'src> HasSpan<'src> for Block<'src> {
1232 fn span(&self) -> Span<'src> {
1233 match self {
1234 Self::Simple(b) => b.span(),
1235 Self::Media(b) => b.span(),
1236 Self::Section(b) => b.span(),
1237 Self::List(b) => b.span(),
1238 Self::ListItem(b) => b.span(),
1239 Self::RawDelimited(b) => b.span(),
1240 Self::CompoundDelimited(b) => b.span(),
1241 Self::Admonition(b) => b.span(),
1242 Self::Quote(b) => b.span(),
1243 Self::Table(b) => b.span(),
1244 Self::Preamble(b) => b.span(),
1245 Self::Break(b) => b.span(),
1246 Self::Toc(b) => b.span(),
1247 Self::DocumentAttribute(b) => b.span(),
1248 }
1249 }
1250}