1use std::slice::Iter;
2
3use crate::{
4 HasSpan, Parser, Span,
5 attributes::Attrlist,
6 blocks::{
7 AdmonitionBlock, Break, CompoundDelimitedBlock, ContentModel, IsBlock, ListBlock, ListItem,
8 ListItemMarker, MediaBlock, Preamble, QuoteBlock, RawDelimitedBlock, SectionBlock,
9 SimpleBlock, TableBlock, media::TargetResolution, metadata::BlockMetadata,
10 starts_with_admonition_label,
11 },
12 content::{Content, SubstitutionGroup},
13 document::{Attribute, RefType},
14 parser::{InlineSubstitutionRenderer, ReferenceResolver, ReferenceWarning},
15 span::MatchedItem,
16 strings::CowStr,
17 warnings::{MatchAndWarnings, Warning, WarningType},
18};
19
20#[derive(Clone, Eq, PartialEq)]
33#[allow(clippy::large_enum_variant)] #[non_exhaustive]
35pub enum Block<'src> {
36 Simple(SimpleBlock<'src>),
39
40 Media(MediaBlock<'src>),
43
44 Section(SectionBlock<'src>),
47
48 List(ListBlock<'src>),
52
53 ListItem(ListItem<'src>),
56
57 RawDelimited(RawDelimitedBlock<'src>),
61
62 CompoundDelimited(CompoundDelimitedBlock<'src>),
64
65 Admonition(AdmonitionBlock<'src>),
69
70 Quote(QuoteBlock<'src>),
73
74 Table(TableBlock<'src>),
76
77 Preamble(Preamble<'src>),
80
81 Break(Break<'src>),
83
84 DocumentAttribute(Attribute<'src>),
87}
88
89impl<'src> std::fmt::Debug for Block<'src> {
90 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91 match self {
92 Block::Simple(block) => f.debug_tuple("Block::Simple").field(block).finish(),
93 Block::Media(block) => f.debug_tuple("Block::Media").field(block).finish(),
94 Block::Section(block) => f.debug_tuple("Block::Section").field(block).finish(),
95 Block::List(block) => f.debug_tuple("Block::List").field(block).finish(),
96 Block::ListItem(block) => f.debug_tuple("Block::ListItem").field(block).finish(),
97
98 Block::RawDelimited(block) => {
99 f.debug_tuple("Block::RawDelimited").field(block).finish()
100 }
101
102 Block::CompoundDelimited(block) => f
103 .debug_tuple("Block::CompoundDelimited")
104 .field(block)
105 .finish(),
106
107 Block::Admonition(block) => f.debug_tuple("Block::Admonition").field(block).finish(),
108 Block::Quote(block) => f.debug_tuple("Block::Quote").field(block).finish(),
109 Block::Table(block) => f.debug_tuple("Block::Table").field(block).finish(),
110 Block::Preamble(block) => f.debug_tuple("Block::Preamble").field(block).finish(),
111 Block::Break(break_) => f.debug_tuple("Block::Break").field(break_).finish(),
112
113 Block::DocumentAttribute(block) => f
114 .debug_tuple("Block::DocumentAttribute")
115 .field(block)
116 .finish(),
117 }
118 }
119}
120
121#[allow(clippy::large_enum_variant)]
133pub(crate) enum BlockParseOutcome<'src> {
134 Parsed(MatchedItem<'src, Block<'src>>),
136
137 Dropped(Span<'src>),
142
143 NoMatch,
145}
146
147impl<'src> Block<'src> {
148 #[cfg(test)]
157 pub(crate) fn parse(
158 source: Span<'src>,
159 parser: &mut Parser,
160 ) -> MatchAndWarnings<'src, Option<MatchedItem<'src, Self>>> {
161 let MatchAndWarnings { item, warnings } = Self::parse_internal(source, parser, None, false);
162
163 MatchAndWarnings {
164 item: match item {
165 BlockParseOutcome::Parsed(mi) => Some(mi),
166 BlockParseOutcome::Dropped(_) | BlockParseOutcome::NoMatch => None,
167 },
168 warnings,
169 }
170 }
171
172 pub(crate) fn parse_with_outcome(
179 source: Span<'src>,
180 parser: &mut Parser,
181 ) -> MatchAndWarnings<'src, BlockParseOutcome<'src>> {
182 Self::parse_internal(source, parser, None, false)
183 }
184
185 pub(crate) fn parse_for_list_item(
196 source: Span<'src>,
197 parser: &mut Parser,
198 parent_list_markers: &[ListItemMarker<'src>],
199 is_continuation: bool,
200 ) -> MatchAndWarnings<'src, BlockParseOutcome<'src>> {
201 Self::parse_internal(source, parser, Some(parent_list_markers), is_continuation)
202 }
203
204 fn parse_internal(
207 source: Span<'src>,
208 parser: &mut Parser,
209 parent_list_markers: Option<&[ListItemMarker<'src>]>,
210 is_continuation: bool,
211 ) -> MatchAndWarnings<'src, BlockParseOutcome<'src>> {
212 let first_line = source.take_line().item.discard_whitespace();
216
217 if let Some(first_char) = first_line.chars().next()
220 && !matches!(
221 first_char,
222 '.' | '#'
223 | '='
224 | '/'
225 | '-'
226 | '+'
227 | '*'
228 | '_'
229 | '`'
230 | '['
231 | ':'
232 | '\''
233 | '<'
234 | '>'
235 | '"'
236 | '•'
237 )
238 && !first_line.contains("::")
239 && !first_line.contains(";;")
240 && !TableBlock::is_table_delimiter(&first_line)
241 && !ListItemMarker::starts_with_marker(first_line)
242 && !starts_with_admonition_label(first_line)
243 && parent_list_markers.is_none()
244 && let Some(MatchedItem {
245 item: simple_block,
246 after,
247 }) = SimpleBlock::parse_fast(source, parser)
248 {
249 let mut warnings = vec![];
250 let block = Self::Simple(simple_block);
251
252 Self::register_block_id(
253 block.id(),
254 Self::block_reftext(&block),
255 block.span(),
256 parser,
257 &mut warnings,
258 );
259
260 return MatchAndWarnings {
261 item: BlockParseOutcome::Parsed(MatchedItem { item: block, after }),
262 warnings,
263 };
264 }
265
266 if first_line.starts_with(':')
268 && (first_line.ends_with(':') || first_line.contains(": "))
269 && let Some(attr) = Attribute::parse(source, parser)
270 {
271 let mut warnings: Vec<Warning<'src>> = vec![];
272 parser.set_attribute_from_body(&attr.item, &mut warnings);
273
274 return MatchAndWarnings {
275 item: BlockParseOutcome::Parsed(MatchedItem {
276 item: Self::DocumentAttribute(attr.item),
277 after: attr.after,
278 }),
279 warnings,
280 };
281 }
282
283 let MatchAndWarnings {
286 item: mut metadata,
287 mut warnings,
288 } = BlockMetadata::parse(source, parser);
289
290 let is_literal =
298 metadata.attrlist.as_ref().and_then(|a| a.block_style()) == Some("literal") && {
299 let first_line = metadata.block_start.take_normalized_line().item;
300 !RawDelimitedBlock::is_valid_delimiter(&first_line)
301 && !CompoundDelimitedBlock::is_valid_delimiter(&first_line)
302 && !TableBlock::is_table_delimiter(&first_line)
303 };
304
305 let mut simple_block_mi = None;
312
313 if !is_literal {
314 if let Some(mut adm_maw) = AdmonitionBlock::parse(&metadata, parser)
315 && let Some(adm) = adm_maw.item
316 {
317 if !adm_maw.warnings.is_empty() {
318 warnings.append(&mut adm_maw.warnings);
319 }
320
321 let block = Self::Admonition(adm.item);
322
323 Self::register_block_id(
324 block.id(),
325 Self::block_reftext(&block),
326 block.span(),
327 parser,
328 &mut warnings,
329 );
330
331 return MatchAndWarnings {
332 item: BlockParseOutcome::Parsed(MatchedItem {
333 item: block,
334 after: adm.after,
335 }),
336 warnings,
337 };
338 }
339
340 if let Some(mut quote_maw) = QuoteBlock::parse(&metadata, parser)
341 && let Some(quote) = quote_maw.item
342 {
343 if !quote_maw.warnings.is_empty() {
344 warnings.append(&mut quote_maw.warnings);
345 }
346
347 let block = Self::Quote(quote.item);
348
349 Self::register_block_id(
350 block.id(),
351 Self::block_reftext(&block),
352 block.span(),
353 parser,
354 &mut warnings,
355 );
356
357 return MatchAndWarnings {
358 item: BlockParseOutcome::Parsed(MatchedItem {
359 item: block,
360 after: quote.after,
361 }),
362 warnings,
363 };
364 }
365
366 if let Some(mut rdb_maw) = RawDelimitedBlock::parse(&metadata, parser)
367 && let Some(rdb) = rdb_maw.item
368 {
369 if !rdb_maw.warnings.is_empty() {
370 warnings.append(&mut rdb_maw.warnings);
371 }
372
373 let block = Self::RawDelimited(rdb.item);
374
375 Self::register_block_id(
376 block.id(),
377 Self::block_reftext(&block),
378 block.span(),
379 parser,
380 &mut warnings,
381 );
382
383 return MatchAndWarnings {
384 item: BlockParseOutcome::Parsed(MatchedItem {
385 item: block,
386 after: rdb.after,
387 }),
388 warnings,
389 };
390 }
391
392 if let Some(mut cdb_maw) = CompoundDelimitedBlock::parse(&metadata, parser)
393 && let Some(cdb) = cdb_maw.item
394 {
395 if !cdb_maw.warnings.is_empty() {
396 warnings.append(&mut cdb_maw.warnings);
397 }
398
399 let block = Self::CompoundDelimited(cdb.item);
400
401 Self::register_block_id(
402 block.id(),
403 Self::block_reftext(&block),
404 block.span(),
405 parser,
406 &mut warnings,
407 );
408
409 return MatchAndWarnings {
410 item: BlockParseOutcome::Parsed(MatchedItem {
411 item: block,
412 after: cdb.after,
413 }),
414 warnings,
415 };
416 }
417
418 if let Some(mut table_maw) = TableBlock::parse(&metadata, parser)
419 && let Some(table) = table_maw.item
420 {
421 if !table_maw.warnings.is_empty() {
422 warnings.append(&mut table_maw.warnings);
423 }
424
425 let block = Self::Table(table.item);
426
427 Self::register_block_id(
428 block.id(),
429 Self::block_reftext(&block),
430 block.span(),
431 parser,
432 &mut warnings,
433 );
434
435 return MatchAndWarnings {
436 item: BlockParseOutcome::Parsed(MatchedItem {
437 item: block,
438 after: table.after,
439 }),
440 warnings,
441 };
442 }
443
444 let line = metadata.block_start.take_normalized_line();
446
447 if line.item.starts_with("image::")
448 || line.item.starts_with("video::")
449 || line.item.starts_with("audio::")
450 {
451 let mut media_block_maw = MediaBlock::parse(&metadata, parser);
452
453 if let Some(mut media_block) = media_block_maw.item {
454 if !media_block_maw.warnings.is_empty() {
458 warnings.append(&mut media_block_maw.warnings);
459 }
460
461 if media_block.item.resolve_target(parser) == TargetResolution::Drop {
465 return MatchAndWarnings {
466 item: BlockParseOutcome::Dropped(media_block.after),
467 warnings,
468 };
469 }
470
471 media_block.item.assign_caption(parser);
475
476 let block = Self::Media(media_block.item);
477
478 Self::register_block_id(
479 block.id(),
480 Self::block_reftext(&block),
481 block.span(),
482 parser,
483 &mut warnings,
484 );
485
486 return MatchAndWarnings {
487 item: BlockParseOutcome::Parsed(MatchedItem {
488 item: block,
489 after: media_block.after,
490 }),
491 warnings,
492 };
493 }
494
495 }
498
499 if (line.item.starts_with('=') || line.item.starts_with('#'))
500 && let Some(mi_section_block) =
501 SectionBlock::parse(&metadata, parser, &mut warnings)
502 {
503 return MatchAndWarnings {
507 item: BlockParseOutcome::Parsed(MatchedItem {
508 item: Self::Section(mi_section_block.item),
509 after: mi_section_block.after,
510 }),
511 warnings,
512 };
513 }
514
515 if (line.item.starts_with('\'')
516 || line.item.starts_with('-')
517 || line.item.starts_with('*')
518 || line.item.starts_with('<'))
519 && let Some(mi_break) = Break::parse(&metadata, parser)
520 {
521 return MatchAndWarnings {
524 item: BlockParseOutcome::Parsed(MatchedItem {
525 item: Self::Break(mi_break.item),
526 after: mi_break.after,
527 }),
528 warnings,
529 };
530 }
531
532 if parent_list_markers.is_none()
536 && let Some(mi_list) = ListBlock::parse(&metadata, parser, &mut warnings)
537 {
538 return MatchAndWarnings {
539 item: BlockParseOutcome::Parsed(MatchedItem {
540 item: Self::List(mi_list.item),
541 after: mi_list.after,
542 }),
543 warnings,
544 };
545 }
546
547 simple_block_mi = if let Some(plm) = parent_list_markers {
554 SimpleBlock::parse_for_list_item(&metadata, parser, is_continuation, plm)
555 } else {
556 SimpleBlock::parse(&metadata, parser)
557 };
558
559 if simple_block_mi.is_none() && !metadata.is_empty() {
560 warnings.push(Warning {
564 source: metadata.source,
565 warning: WarningType::MissingBlockAfterTitleOrAttributeList,
566 });
567
568 metadata.title_source = None;
572 metadata.title = None;
573 metadata.anchor = None;
574 metadata.attrlist = None;
575 metadata.block_start = metadata.source;
576 }
577 }
578
579 let simple_block_mi = match simple_block_mi {
583 Some(mi) => Some(mi),
584 None => {
585 if let Some(plm) = parent_list_markers {
586 SimpleBlock::parse_for_list_item(&metadata, parser, is_continuation, plm)
587 } else {
588 SimpleBlock::parse(&metadata, parser)
589 }
590 }
591 };
592
593 let mut result = MatchAndWarnings {
594 item: match simple_block_mi {
595 Some(mi) => BlockParseOutcome::Parsed(MatchedItem {
596 item: Self::Simple(mi.item),
597 after: mi.after,
598 }),
599 None => BlockParseOutcome::NoMatch,
600 },
601 warnings,
602 };
603
604 if let BlockParseOutcome::Parsed(ref matched_item) = result.item {
605 Self::register_block_id(
606 matched_item.item.id(),
607 Self::block_reftext(&matched_item.item),
608 matched_item.item.span(),
609 parser,
610 &mut result.warnings,
611 );
612 }
613
614 result
615 }
616
617 fn block_reftext<'a>(block: &'a Block<'a>) -> Option<&'a str> {
622 block
623 .attrlist()
624 .and_then(|attrlist| attrlist.named_attribute("reftext"))
625 .map(|attr| attr.value())
626 .or_else(|| block.anchor_reftext().map(|span| span.data()))
627 .or_else(|| block.title())
628 }
629
630 fn register_block_id(
635 id: Option<&str>,
636 reftext: Option<&str>,
637 span: Span<'src>,
638 parser: &mut Parser,
639 warnings: &mut Vec<Warning<'src>>,
640 ) {
641 if let Some(id) = id
642 && let Err(_duplicate_error) = parser.register_ref(id, reftext, RefType::Anchor)
643 {
644 warnings.push(Warning {
646 source: span,
647 warning: WarningType::DuplicateId(id.to_string()),
648 });
649 }
650 }
651
652 pub(crate) fn as_list_item(&self) -> Option<&ListItem<'src>> {
655 match self {
656 Self::ListItem(li) => Some(li),
657 _ => None,
658 }
659 }
660
661 pub(crate) fn resolve_references(
669 &mut self,
670 resolver: &dyn ReferenceResolver,
671 renderer: &dyn InlineSubstitutionRenderer,
672 warnings: &mut Vec<ReferenceWarning>,
673 ) {
674 if let Some(content) = self.content_mut() {
675 content.resolve_references(resolver, renderer, warnings);
676 }
677
678 if let Self::Table(table) = self {
681 table.resolve_references(resolver, renderer, warnings);
682 }
683
684 if let Self::Quote(quote) = self {
688 quote.resolve_references(resolver, renderer, warnings);
689 }
690
691 for child in self.nested_blocks_mut() {
692 child.resolve_references(resolver, renderer, warnings);
693 }
694 }
695}
696
697impl<'src> IsBlock<'src> for Block<'src> {
698 fn content_model(&self) -> ContentModel {
699 match self {
700 Self::Simple(_) => ContentModel::Simple,
701 Self::Media(b) => b.content_model(),
702 Self::Section(_) => ContentModel::Compound,
703 Self::List(b) => b.content_model(),
704 Self::ListItem(b) => b.content_model(),
705 Self::RawDelimited(b) => b.content_model(),
706 Self::CompoundDelimited(b) => b.content_model(),
707 Self::Admonition(b) => b.content_model(),
708 Self::Quote(b) => b.content_model(),
709 Self::Table(b) => b.content_model(),
710 Self::Preamble(b) => b.content_model(),
711 Self::Break(b) => b.content_model(),
712 Self::DocumentAttribute(b) => b.content_model(),
713 }
714 }
715
716 fn declared_style(&'src self) -> Option<&'src str> {
717 match self {
718 Self::Simple(b) => b.declared_style(),
719 Self::Media(b) => b.declared_style(),
720 Self::Section(b) => b.declared_style(),
721 Self::List(b) => b.declared_style(),
722 Self::ListItem(b) => b.declared_style(),
723 Self::RawDelimited(b) => b.declared_style(),
724 Self::CompoundDelimited(b) => b.declared_style(),
725 Self::Admonition(b) => b.declared_style(),
726 Self::Quote(b) => b.declared_style(),
727 Self::Table(b) => b.declared_style(),
728 Self::Preamble(b) => b.declared_style(),
729 Self::Break(b) => b.declared_style(),
730 Self::DocumentAttribute(b) => b.declared_style(),
731 }
732 }
733
734 fn rendered_content(&'src self) -> Option<&'src str> {
735 match self {
736 Self::Simple(b) => b.rendered_content(),
737 Self::Media(b) => b.rendered_content(),
738 Self::Section(b) => b.rendered_content(),
739 Self::List(b) => b.rendered_content(),
740 Self::ListItem(b) => b.rendered_content(),
741 Self::RawDelimited(b) => b.rendered_content(),
742 Self::CompoundDelimited(b) => b.rendered_content(),
743 Self::Admonition(b) => b.rendered_content(),
744 Self::Quote(b) => b.rendered_content(),
745 Self::Table(b) => b.rendered_content(),
746 Self::Preamble(b) => b.rendered_content(),
747 Self::Break(b) => b.rendered_content(),
748 Self::DocumentAttribute(b) => b.rendered_content(),
749 }
750 }
751
752 fn raw_context(&self) -> CowStr<'src> {
753 match self {
754 Self::Simple(b) => b.raw_context(),
755 Self::Media(b) => b.raw_context(),
756 Self::Section(b) => b.raw_context(),
757 Self::List(b) => b.raw_context(),
758 Self::ListItem(b) => b.raw_context(),
759 Self::RawDelimited(b) => b.raw_context(),
760 Self::CompoundDelimited(b) => b.raw_context(),
761 Self::Admonition(b) => b.raw_context(),
762 Self::Quote(b) => b.raw_context(),
763 Self::Table(b) => b.raw_context(),
764 Self::Preamble(b) => b.raw_context(),
765 Self::Break(b) => b.raw_context(),
766 Self::DocumentAttribute(b) => b.raw_context(),
767 }
768 }
769
770 fn nested_blocks(&'src self) -> Iter<'src, Block<'src>> {
771 match self {
772 Self::Simple(b) => b.nested_blocks(),
773 Self::Media(b) => b.nested_blocks(),
774 Self::Section(b) => b.nested_blocks(),
775 Self::List(b) => b.nested_blocks(),
776 Self::ListItem(b) => b.nested_blocks(),
777 Self::RawDelimited(b) => b.nested_blocks(),
778 Self::CompoundDelimited(b) => b.nested_blocks(),
779 Self::Admonition(b) => b.nested_blocks(),
780 Self::Quote(b) => b.nested_blocks(),
781 Self::Table(b) => b.nested_blocks(),
782 Self::Preamble(b) => b.nested_blocks(),
783 Self::Break(b) => b.nested_blocks(),
784 Self::DocumentAttribute(b) => b.nested_blocks(),
785 }
786 }
787
788 fn nested_blocks_mut(&mut self) -> &mut [Block<'src>] {
789 match self {
790 Self::Simple(b) => b.nested_blocks_mut(),
791 Self::Media(b) => b.nested_blocks_mut(),
792 Self::Section(b) => b.nested_blocks_mut(),
793 Self::List(b) => b.nested_blocks_mut(),
794 Self::ListItem(b) => b.nested_blocks_mut(),
795 Self::RawDelimited(b) => b.nested_blocks_mut(),
796 Self::CompoundDelimited(b) => b.nested_blocks_mut(),
797 Self::Admonition(b) => b.nested_blocks_mut(),
798 Self::Quote(b) => b.nested_blocks_mut(),
799 Self::Table(b) => b.nested_blocks_mut(),
800 Self::Preamble(b) => b.nested_blocks_mut(),
801 Self::Break(b) => b.nested_blocks_mut(),
802 Self::DocumentAttribute(b) => b.nested_blocks_mut(),
803 }
804 }
805
806 fn content_mut(&mut self) -> Option<&mut Content<'src>> {
807 match self {
808 Self::Simple(b) => b.content_mut(),
809 Self::Media(b) => b.content_mut(),
810 Self::Section(b) => b.content_mut(),
811 Self::List(b) => b.content_mut(),
812 Self::ListItem(b) => b.content_mut(),
813 Self::RawDelimited(b) => b.content_mut(),
814 Self::CompoundDelimited(b) => b.content_mut(),
815 Self::Admonition(b) => b.content_mut(),
816 Self::Quote(b) => b.content_mut(),
817 Self::Table(b) => b.content_mut(),
818 Self::Preamble(b) => b.content_mut(),
819 Self::Break(b) => b.content_mut(),
820 Self::DocumentAttribute(b) => b.content_mut(),
821 }
822 }
823
824 fn title_source(&'src self) -> Option<Span<'src>> {
825 match self {
826 Self::Simple(b) => b.title_source(),
827 Self::Media(b) => b.title_source(),
828 Self::Section(b) => b.title_source(),
829 Self::List(b) => b.title_source(),
830 Self::ListItem(b) => b.title_source(),
831 Self::RawDelimited(b) => b.title_source(),
832 Self::CompoundDelimited(b) => b.title_source(),
833 Self::Admonition(b) => b.title_source(),
834 Self::Quote(b) => b.title_source(),
835 Self::Table(b) => b.title_source(),
836 Self::Preamble(b) => b.title_source(),
837 Self::Break(b) => b.title_source(),
838 Self::DocumentAttribute(b) => b.title_source(),
839 }
840 }
841
842 fn title(&self) -> Option<&str> {
843 match self {
844 Self::Simple(b) => b.title(),
845 Self::Media(b) => b.title(),
846 Self::Section(b) => b.title(),
847 Self::List(b) => b.title(),
848 Self::ListItem(b) => b.title(),
849 Self::RawDelimited(b) => b.title(),
850 Self::CompoundDelimited(b) => b.title(),
851 Self::Admonition(b) => b.title(),
852 Self::Quote(b) => b.title(),
853 Self::Table(b) => b.title(),
854 Self::Preamble(b) => b.title(),
855 Self::Break(b) => b.title(),
856 Self::DocumentAttribute(b) => b.title(),
857 }
858 }
859
860 fn caption(&self) -> Option<&str> {
861 match self {
862 Self::Simple(b) => b.caption(),
863 Self::Media(b) => b.caption(),
864 Self::Section(b) => b.caption(),
865 Self::List(b) => b.caption(),
866 Self::ListItem(b) => b.caption(),
867 Self::RawDelimited(b) => b.caption(),
868 Self::CompoundDelimited(b) => b.caption(),
869 Self::Admonition(b) => b.caption(),
870 Self::Quote(b) => b.caption(),
871 Self::Table(b) => b.caption(),
872 Self::Preamble(b) => b.caption(),
873 Self::Break(b) => b.caption(),
874 Self::DocumentAttribute(b) => b.caption(),
875 }
876 }
877
878 fn number(&self) -> Option<usize> {
879 match self {
880 Self::Simple(b) => b.number(),
881 Self::Media(b) => b.number(),
882 Self::Section(b) => b.number(),
883 Self::List(b) => b.number(),
884 Self::ListItem(b) => b.number(),
885 Self::RawDelimited(b) => b.number(),
886 Self::CompoundDelimited(b) => b.number(),
887 Self::Admonition(b) => b.number(),
888 Self::Quote(b) => b.number(),
889 Self::Table(b) => b.number(),
890 Self::Preamble(b) => b.number(),
891 Self::Break(b) => b.number(),
892 Self::DocumentAttribute(b) => b.number(),
893 }
894 }
895
896 fn id(&'src self) -> Option<&'src str> {
897 match self {
911 Self::Media(b) => b.id(),
912 Self::Section(b) => b.id(),
913 _ => self
914 .anchor()
915 .map(|a| a.data())
916 .or_else(|| self.attrlist().and_then(|attrlist| attrlist.id())),
917 }
918 }
919
920 fn anchor(&'src self) -> Option<Span<'src>> {
921 match self {
922 Self::Simple(b) => b.anchor(),
923 Self::Media(b) => b.anchor(),
924 Self::Section(b) => b.anchor(),
925 Self::List(b) => b.anchor(),
926 Self::ListItem(b) => b.anchor(),
927 Self::RawDelimited(b) => b.anchor(),
928 Self::CompoundDelimited(b) => b.anchor(),
929 Self::Admonition(b) => b.anchor(),
930 Self::Quote(b) => b.anchor(),
931 Self::Table(b) => b.anchor(),
932 Self::Preamble(b) => b.anchor(),
933 Self::Break(b) => b.anchor(),
934 Self::DocumentAttribute(b) => b.anchor(),
935 }
936 }
937
938 fn anchor_reftext(&'src self) -> Option<Span<'src>> {
939 match self {
940 Self::Simple(b) => b.anchor_reftext(),
941 Self::Media(b) => b.anchor_reftext(),
942 Self::Section(b) => b.anchor_reftext(),
943 Self::List(b) => b.anchor_reftext(),
944 Self::ListItem(b) => b.anchor_reftext(),
945 Self::RawDelimited(b) => b.anchor_reftext(),
946 Self::CompoundDelimited(b) => b.anchor_reftext(),
947 Self::Admonition(b) => b.anchor_reftext(),
948 Self::Quote(b) => b.anchor_reftext(),
949 Self::Table(b) => b.anchor_reftext(),
950 Self::Preamble(b) => b.anchor_reftext(),
951 Self::Break(b) => b.anchor_reftext(),
952 Self::DocumentAttribute(b) => b.anchor_reftext(),
953 }
954 }
955
956 fn attrlist(&'src self) -> Option<&'src Attrlist<'src>> {
957 match self {
958 Self::Simple(b) => b.attrlist(),
959 Self::Media(b) => b.attrlist(),
960 Self::Section(b) => b.attrlist(),
961 Self::List(b) => b.attrlist(),
962 Self::ListItem(b) => b.attrlist(),
963 Self::RawDelimited(b) => b.attrlist(),
964 Self::CompoundDelimited(b) => b.attrlist(),
965 Self::Admonition(b) => b.attrlist(),
966 Self::Quote(b) => b.attrlist(),
967 Self::Table(b) => b.attrlist(),
968 Self::Preamble(b) => b.attrlist(),
969 Self::Break(b) => b.attrlist(),
970 Self::DocumentAttribute(b) => b.attrlist(),
971 }
972 }
973
974 fn substitution_group(&self) -> SubstitutionGroup {
975 match self {
976 Self::Simple(b) => b.substitution_group(),
977 Self::Media(b) => b.substitution_group(),
978 Self::Section(b) => b.substitution_group(),
979 Self::List(b) => b.substitution_group(),
980 Self::ListItem(b) => b.substitution_group(),
981 Self::RawDelimited(b) => b.substitution_group(),
982 Self::CompoundDelimited(b) => b.substitution_group(),
983 Self::Admonition(b) => b.substitution_group(),
984 Self::Quote(b) => b.substitution_group(),
985 Self::Table(b) => b.substitution_group(),
986 Self::Preamble(b) => b.substitution_group(),
987 Self::Break(b) => b.substitution_group(),
988 Self::DocumentAttribute(b) => b.substitution_group(),
989 }
990 }
991}
992
993impl<'src> HasSpan<'src> for Block<'src> {
994 fn span(&self) -> Span<'src> {
995 match self {
996 Self::Simple(b) => b.span(),
997 Self::Media(b) => b.span(),
998 Self::Section(b) => b.span(),
999 Self::List(b) => b.span(),
1000 Self::ListItem(b) => b.span(),
1001 Self::RawDelimited(b) => b.span(),
1002 Self::CompoundDelimited(b) => b.span(),
1003 Self::Admonition(b) => b.span(),
1004 Self::Quote(b) => b.span(),
1005 Self::Table(b) => b.span(),
1006 Self::Preamble(b) => b.span(),
1007 Self::Break(b) => b.span(),
1008 Self::DocumentAttribute(b) => b.span(),
1009 }
1010 }
1011}