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, metadata::BlockMetadata, starts_with_admonition_label,
10 },
11 content::{Content, SubstitutionGroup},
12 document::{Attribute, RefType},
13 parser::{InlineSubstitutionRenderer, ReferenceResolver, ReferenceWarning},
14 span::MatchedItem,
15 strings::CowStr,
16 warnings::{MatchAndWarnings, Warning, WarningType},
17};
18
19#[derive(Clone, Eq, PartialEq)]
32#[allow(clippy::large_enum_variant)] #[non_exhaustive]
34pub enum Block<'src> {
35 Simple(SimpleBlock<'src>),
38
39 Media(MediaBlock<'src>),
42
43 Section(SectionBlock<'src>),
46
47 List(ListBlock<'src>),
51
52 ListItem(ListItem<'src>),
55
56 RawDelimited(RawDelimitedBlock<'src>),
60
61 CompoundDelimited(CompoundDelimitedBlock<'src>),
63
64 Admonition(AdmonitionBlock<'src>),
68
69 Quote(QuoteBlock<'src>),
72
73 Table(TableBlock<'src>),
75
76 Preamble(Preamble<'src>),
79
80 Break(Break<'src>),
82
83 DocumentAttribute(Attribute<'src>),
86}
87
88impl<'src> std::fmt::Debug for Block<'src> {
89 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90 match self {
91 Block::Simple(block) => f.debug_tuple("Block::Simple").field(block).finish(),
92 Block::Media(block) => f.debug_tuple("Block::Media").field(block).finish(),
93 Block::Section(block) => f.debug_tuple("Block::Section").field(block).finish(),
94 Block::List(block) => f.debug_tuple("Block::List").field(block).finish(),
95 Block::ListItem(block) => f.debug_tuple("Block::ListItem").field(block).finish(),
96
97 Block::RawDelimited(block) => {
98 f.debug_tuple("Block::RawDelimited").field(block).finish()
99 }
100
101 Block::CompoundDelimited(block) => f
102 .debug_tuple("Block::CompoundDelimited")
103 .field(block)
104 .finish(),
105
106 Block::Admonition(block) => f.debug_tuple("Block::Admonition").field(block).finish(),
107 Block::Quote(block) => f.debug_tuple("Block::Quote").field(block).finish(),
108 Block::Table(block) => f.debug_tuple("Block::Table").field(block).finish(),
109 Block::Preamble(block) => f.debug_tuple("Block::Preamble").field(block).finish(),
110 Block::Break(break_) => f.debug_tuple("Block::Break").field(break_).finish(),
111
112 Block::DocumentAttribute(block) => f
113 .debug_tuple("Block::DocumentAttribute")
114 .field(block)
115 .finish(),
116 }
117 }
118}
119
120impl<'src> Block<'src> {
121 pub(crate) fn parse(
125 source: Span<'src>,
126 parser: &mut Parser,
127 ) -> MatchAndWarnings<'src, Option<MatchedItem<'src, Self>>> {
128 Self::parse_internal(source, parser, None, false)
129 }
130
131 pub(crate) fn parse_for_list_item(
142 source: Span<'src>,
143 parser: &mut Parser,
144 parent_list_markers: &[ListItemMarker<'src>],
145 is_continuation: bool,
146 ) -> MatchAndWarnings<'src, Option<MatchedItem<'src, Self>>> {
147 Self::parse_internal(source, parser, Some(parent_list_markers), is_continuation)
148 }
149
150 fn parse_internal(
152 source: Span<'src>,
153 parser: &mut Parser,
154 parent_list_markers: Option<&[ListItemMarker<'src>]>,
155 is_continuation: bool,
156 ) -> MatchAndWarnings<'src, Option<MatchedItem<'src, Self>>> {
157 let first_line = source.take_line().item.discard_whitespace();
161
162 if let Some(first_char) = first_line.chars().next()
165 && !matches!(
166 first_char,
167 '.' | '#'
168 | '='
169 | '/'
170 | '-'
171 | '+'
172 | '*'
173 | '_'
174 | '['
175 | ':'
176 | '\''
177 | '<'
178 | '>'
179 | '"'
180 | '•'
181 )
182 && !first_line.contains("::")
183 && !first_line.contains(";;")
184 && !TableBlock::is_table_delimiter(&first_line)
185 && !ListItemMarker::starts_with_marker(first_line)
186 && !starts_with_admonition_label(first_line)
187 && parent_list_markers.is_none()
188 && let Some(MatchedItem {
189 item: simple_block,
190 after,
191 }) = SimpleBlock::parse_fast(source, parser)
192 {
193 let mut warnings = vec![];
194 let block = Self::Simple(simple_block);
195
196 Self::register_block_id(
197 block.id(),
198 block.title(),
199 block.span(),
200 parser,
201 &mut warnings,
202 );
203
204 return MatchAndWarnings {
205 item: Some(MatchedItem { item: block, after }),
206 warnings,
207 };
208 }
209
210 if first_line.starts_with(':')
212 && (first_line.ends_with(':') || first_line.contains(": "))
213 && let Some(attr) = Attribute::parse(source, parser)
214 {
215 let mut warnings: Vec<Warning<'src>> = vec![];
216 parser.set_attribute_from_body(&attr.item, &mut warnings);
217
218 return MatchAndWarnings {
219 item: Some(MatchedItem {
220 item: Self::DocumentAttribute(attr.item),
221 after: attr.after,
222 }),
223 warnings,
224 };
225 }
226
227 let MatchAndWarnings {
230 item: mut metadata,
231 mut warnings,
232 } = BlockMetadata::parse(source, parser);
233
234 let is_literal = metadata.attrlist.as_ref().and_then(|a| a.block_style())
240 == Some("literal")
241 && metadata.block_start.take_normalized_line().item.data() != "--";
242
243 let mut simple_block_mi = None;
250
251 if !is_literal {
252 if let Some(mut adm_maw) = AdmonitionBlock::parse(&metadata, parser)
253 && let Some(adm) = adm_maw.item
254 {
255 if !adm_maw.warnings.is_empty() {
256 warnings.append(&mut adm_maw.warnings);
257 }
258
259 let block = Self::Admonition(adm.item);
260
261 Self::register_block_id(
262 block.id(),
263 block.title(),
264 block.span(),
265 parser,
266 &mut warnings,
267 );
268
269 return MatchAndWarnings {
270 item: Some(MatchedItem {
271 item: block,
272 after: adm.after,
273 }),
274 warnings,
275 };
276 }
277
278 if let Some(mut quote_maw) = QuoteBlock::parse(&metadata, parser)
279 && let Some(quote) = quote_maw.item
280 {
281 if !quote_maw.warnings.is_empty() {
282 warnings.append(&mut quote_maw.warnings);
283 }
284
285 let block = Self::Quote(quote.item);
286
287 Self::register_block_id(
288 block.id(),
289 block.title(),
290 block.span(),
291 parser,
292 &mut warnings,
293 );
294
295 return MatchAndWarnings {
296 item: Some(MatchedItem {
297 item: block,
298 after: quote.after,
299 }),
300 warnings,
301 };
302 }
303
304 if let Some(mut rdb_maw) = RawDelimitedBlock::parse(&metadata, parser)
305 && let Some(rdb) = rdb_maw.item
306 {
307 if !rdb_maw.warnings.is_empty() {
308 warnings.append(&mut rdb_maw.warnings);
309 }
310
311 let block = Self::RawDelimited(rdb.item);
312
313 Self::register_block_id(
314 block.id(),
315 block.title(),
316 block.span(),
317 parser,
318 &mut warnings,
319 );
320
321 return MatchAndWarnings {
322 item: Some(MatchedItem {
323 item: block,
324 after: rdb.after,
325 }),
326 warnings,
327 };
328 }
329
330 if let Some(mut cdb_maw) = CompoundDelimitedBlock::parse(&metadata, parser)
331 && let Some(cdb) = cdb_maw.item
332 {
333 if !cdb_maw.warnings.is_empty() {
334 warnings.append(&mut cdb_maw.warnings);
335 }
336
337 let block = Self::CompoundDelimited(cdb.item);
338
339 Self::register_block_id(
340 block.id(),
341 block.title(),
342 block.span(),
343 parser,
344 &mut warnings,
345 );
346
347 return MatchAndWarnings {
348 item: Some(MatchedItem {
349 item: block,
350 after: cdb.after,
351 }),
352 warnings,
353 };
354 }
355
356 if let Some(mut table_maw) = TableBlock::parse(&metadata, parser)
357 && let Some(table) = table_maw.item
358 {
359 if !table_maw.warnings.is_empty() {
360 warnings.append(&mut table_maw.warnings);
361 }
362
363 let block = Self::Table(table.item);
364
365 Self::register_block_id(
366 block.id(),
367 block.title(),
368 block.span(),
369 parser,
370 &mut warnings,
371 );
372
373 return MatchAndWarnings {
374 item: Some(MatchedItem {
375 item: block,
376 after: table.after,
377 }),
378 warnings,
379 };
380 }
381
382 let line = metadata.block_start.take_normalized_line();
384
385 if line.item.starts_with("image::")
386 || line.item.starts_with("video::")
387 || line.item.starts_with("video::")
388 {
389 let mut media_block_maw = MediaBlock::parse(&metadata, parser);
390
391 if let Some(media_block) = media_block_maw.item {
392 if !media_block_maw.warnings.is_empty() {
396 warnings.append(&mut media_block_maw.warnings);
397 }
398
399 let block = Self::Media(media_block.item);
400
401 Self::register_block_id(
402 block.id(),
403 block.title(),
404 block.span(),
405 parser,
406 &mut warnings,
407 );
408
409 return MatchAndWarnings {
410 item: Some(MatchedItem {
411 item: block,
412 after: media_block.after,
413 }),
414 warnings,
415 };
416 }
417
418 }
421
422 if (line.item.starts_with('=') || line.item.starts_with('#'))
423 && let Some(mi_section_block) =
424 SectionBlock::parse(&metadata, parser, &mut warnings)
425 {
426 return MatchAndWarnings {
430 item: Some(MatchedItem {
431 item: Self::Section(mi_section_block.item),
432 after: mi_section_block.after,
433 }),
434 warnings,
435 };
436 }
437
438 if (line.item.starts_with('\'')
439 || line.item.starts_with('-')
440 || line.item.starts_with('*')
441 || line.item.starts_with('<'))
442 && let Some(mi_break) = Break::parse(&metadata, parser)
443 {
444 return MatchAndWarnings {
447 item: Some(MatchedItem {
448 item: Self::Break(mi_break.item),
449 after: mi_break.after,
450 }),
451 warnings,
452 };
453 }
454
455 if parent_list_markers.is_none()
459 && let Some(mi_list) = ListBlock::parse(&metadata, parser, &mut warnings)
460 {
461 return MatchAndWarnings {
462 item: Some(MatchedItem {
463 item: Self::List(mi_list.item),
464 after: mi_list.after,
465 }),
466 warnings,
467 };
468 }
469
470 simple_block_mi = if let Some(plm) = parent_list_markers {
477 SimpleBlock::parse_for_list_item(&metadata, parser, is_continuation, plm)
478 } else {
479 SimpleBlock::parse(&metadata, parser)
480 };
481
482 if simple_block_mi.is_none() && !metadata.is_empty() {
483 warnings.push(Warning {
487 source: metadata.source,
488 warning: WarningType::MissingBlockAfterTitleOrAttributeList,
489 });
490
491 metadata.title_source = None;
495 metadata.title = None;
496 metadata.anchor = None;
497 metadata.attrlist = None;
498 metadata.block_start = metadata.source;
499 }
500 }
501
502 let simple_block_mi = match simple_block_mi {
506 Some(mi) => Some(mi),
507 None => {
508 if let Some(plm) = parent_list_markers {
509 SimpleBlock::parse_for_list_item(&metadata, parser, is_continuation, plm)
510 } else {
511 SimpleBlock::parse(&metadata, parser)
512 }
513 }
514 };
515
516 let mut result = MatchAndWarnings {
517 item: simple_block_mi.map(|mi| MatchedItem {
518 item: Self::Simple(mi.item),
519 after: mi.after,
520 }),
521 warnings,
522 };
523
524 if let Some(ref matched_item) = result.item {
525 Self::register_block_id(
526 matched_item.item.id(),
527 matched_item.item.title(),
528 matched_item.item.span(),
529 parser,
530 &mut result.warnings,
531 );
532 }
533
534 result
535 }
536
537 fn register_block_id(
542 id: Option<&str>,
543 title: Option<&str>,
544 span: Span<'src>,
545 parser: &mut Parser,
546 warnings: &mut Vec<Warning<'src>>,
547 ) {
548 if let Some(id) = id
549 && let Err(_duplicate_error) = parser.register_ref(
550 id,
551 title, RefType::Anchor,
553 )
554 {
555 warnings.push(Warning {
557 source: span,
558 warning: WarningType::DuplicateId(id.to_string()),
559 });
560 }
561 }
562
563 pub(crate) fn as_list_item(&self) -> Option<&ListItem<'src>> {
566 match self {
567 Self::ListItem(li) => Some(li),
568 _ => None,
569 }
570 }
571
572 pub(crate) fn resolve_references(
580 &mut self,
581 resolver: &dyn ReferenceResolver,
582 renderer: &dyn InlineSubstitutionRenderer,
583 warnings: &mut Vec<ReferenceWarning>,
584 ) {
585 if let Some(content) = self.content_mut() {
586 content.resolve_references(resolver, renderer, warnings);
587 }
588
589 if let Self::Table(table) = self {
592 table.resolve_references(resolver, renderer, warnings);
593 }
594
595 if let Self::Quote(quote) = self {
599 quote.resolve_references(resolver, renderer, warnings);
600 }
601
602 for child in self.nested_blocks_mut() {
603 child.resolve_references(resolver, renderer, warnings);
604 }
605 }
606}
607
608impl<'src> IsBlock<'src> for Block<'src> {
609 fn content_model(&self) -> ContentModel {
610 match self {
611 Self::Simple(_) => ContentModel::Simple,
612 Self::Media(b) => b.content_model(),
613 Self::Section(_) => ContentModel::Compound,
614 Self::List(b) => b.content_model(),
615 Self::ListItem(b) => b.content_model(),
616 Self::RawDelimited(b) => b.content_model(),
617 Self::CompoundDelimited(b) => b.content_model(),
618 Self::Admonition(b) => b.content_model(),
619 Self::Quote(b) => b.content_model(),
620 Self::Table(b) => b.content_model(),
621 Self::Preamble(b) => b.content_model(),
622 Self::Break(b) => b.content_model(),
623 Self::DocumentAttribute(b) => b.content_model(),
624 }
625 }
626
627 fn declared_style(&'src self) -> Option<&'src str> {
628 match self {
629 Self::Simple(b) => b.declared_style(),
630 Self::Media(b) => b.declared_style(),
631 Self::Section(b) => b.declared_style(),
632 Self::List(b) => b.declared_style(),
633 Self::ListItem(b) => b.declared_style(),
634 Self::RawDelimited(b) => b.declared_style(),
635 Self::CompoundDelimited(b) => b.declared_style(),
636 Self::Admonition(b) => b.declared_style(),
637 Self::Quote(b) => b.declared_style(),
638 Self::Table(b) => b.declared_style(),
639 Self::Preamble(b) => b.declared_style(),
640 Self::Break(b) => b.declared_style(),
641 Self::DocumentAttribute(b) => b.declared_style(),
642 }
643 }
644
645 fn rendered_content(&'src self) -> Option<&'src str> {
646 match self {
647 Self::Simple(b) => b.rendered_content(),
648 Self::Media(b) => b.rendered_content(),
649 Self::Section(b) => b.rendered_content(),
650 Self::List(b) => b.rendered_content(),
651 Self::ListItem(b) => b.rendered_content(),
652 Self::RawDelimited(b) => b.rendered_content(),
653 Self::CompoundDelimited(b) => b.rendered_content(),
654 Self::Admonition(b) => b.rendered_content(),
655 Self::Quote(b) => b.rendered_content(),
656 Self::Table(b) => b.rendered_content(),
657 Self::Preamble(b) => b.rendered_content(),
658 Self::Break(b) => b.rendered_content(),
659 Self::DocumentAttribute(b) => b.rendered_content(),
660 }
661 }
662
663 fn raw_context(&self) -> CowStr<'src> {
664 match self {
665 Self::Simple(b) => b.raw_context(),
666 Self::Media(b) => b.raw_context(),
667 Self::Section(b) => b.raw_context(),
668 Self::List(b) => b.raw_context(),
669 Self::ListItem(b) => b.raw_context(),
670 Self::RawDelimited(b) => b.raw_context(),
671 Self::CompoundDelimited(b) => b.raw_context(),
672 Self::Admonition(b) => b.raw_context(),
673 Self::Quote(b) => b.raw_context(),
674 Self::Table(b) => b.raw_context(),
675 Self::Preamble(b) => b.raw_context(),
676 Self::Break(b) => b.raw_context(),
677 Self::DocumentAttribute(b) => b.raw_context(),
678 }
679 }
680
681 fn nested_blocks(&'src self) -> Iter<'src, Block<'src>> {
682 match self {
683 Self::Simple(b) => b.nested_blocks(),
684 Self::Media(b) => b.nested_blocks(),
685 Self::Section(b) => b.nested_blocks(),
686 Self::List(b) => b.nested_blocks(),
687 Self::ListItem(b) => b.nested_blocks(),
688 Self::RawDelimited(b) => b.nested_blocks(),
689 Self::CompoundDelimited(b) => b.nested_blocks(),
690 Self::Admonition(b) => b.nested_blocks(),
691 Self::Quote(b) => b.nested_blocks(),
692 Self::Table(b) => b.nested_blocks(),
693 Self::Preamble(b) => b.nested_blocks(),
694 Self::Break(b) => b.nested_blocks(),
695 Self::DocumentAttribute(b) => b.nested_blocks(),
696 }
697 }
698
699 fn nested_blocks_mut(&mut self) -> &mut [Block<'src>] {
700 match self {
701 Self::Simple(b) => b.nested_blocks_mut(),
702 Self::Media(b) => b.nested_blocks_mut(),
703 Self::Section(b) => b.nested_blocks_mut(),
704 Self::List(b) => b.nested_blocks_mut(),
705 Self::ListItem(b) => b.nested_blocks_mut(),
706 Self::RawDelimited(b) => b.nested_blocks_mut(),
707 Self::CompoundDelimited(b) => b.nested_blocks_mut(),
708 Self::Admonition(b) => b.nested_blocks_mut(),
709 Self::Quote(b) => b.nested_blocks_mut(),
710 Self::Table(b) => b.nested_blocks_mut(),
711 Self::Preamble(b) => b.nested_blocks_mut(),
712 Self::Break(b) => b.nested_blocks_mut(),
713 Self::DocumentAttribute(b) => b.nested_blocks_mut(),
714 }
715 }
716
717 fn content_mut(&mut self) -> Option<&mut Content<'src>> {
718 match self {
719 Self::Simple(b) => b.content_mut(),
720 Self::Media(b) => b.content_mut(),
721 Self::Section(b) => b.content_mut(),
722 Self::List(b) => b.content_mut(),
723 Self::ListItem(b) => b.content_mut(),
724 Self::RawDelimited(b) => b.content_mut(),
725 Self::CompoundDelimited(b) => b.content_mut(),
726 Self::Admonition(b) => b.content_mut(),
727 Self::Quote(b) => b.content_mut(),
728 Self::Table(b) => b.content_mut(),
729 Self::Preamble(b) => b.content_mut(),
730 Self::Break(b) => b.content_mut(),
731 Self::DocumentAttribute(b) => b.content_mut(),
732 }
733 }
734
735 fn title_source(&'src self) -> Option<Span<'src>> {
736 match self {
737 Self::Simple(b) => b.title_source(),
738 Self::Media(b) => b.title_source(),
739 Self::Section(b) => b.title_source(),
740 Self::List(b) => b.title_source(),
741 Self::ListItem(b) => b.title_source(),
742 Self::RawDelimited(b) => b.title_source(),
743 Self::CompoundDelimited(b) => b.title_source(),
744 Self::Admonition(b) => b.title_source(),
745 Self::Quote(b) => b.title_source(),
746 Self::Table(b) => b.title_source(),
747 Self::Preamble(b) => b.title_source(),
748 Self::Break(b) => b.title_source(),
749 Self::DocumentAttribute(b) => b.title_source(),
750 }
751 }
752
753 fn title(&self) -> Option<&str> {
754 match self {
755 Self::Simple(b) => b.title(),
756 Self::Media(b) => b.title(),
757 Self::Section(b) => b.title(),
758 Self::List(b) => b.title(),
759 Self::ListItem(b) => b.title(),
760 Self::RawDelimited(b) => b.title(),
761 Self::CompoundDelimited(b) => b.title(),
762 Self::Admonition(b) => b.title(),
763 Self::Quote(b) => b.title(),
764 Self::Table(b) => b.title(),
765 Self::Preamble(b) => b.title(),
766 Self::Break(b) => b.title(),
767 Self::DocumentAttribute(b) => b.title(),
768 }
769 }
770
771 fn caption(&self) -> Option<&str> {
772 match self {
773 Self::Simple(b) => b.caption(),
774 Self::Media(b) => b.caption(),
775 Self::Section(b) => b.caption(),
776 Self::List(b) => b.caption(),
777 Self::ListItem(b) => b.caption(),
778 Self::RawDelimited(b) => b.caption(),
779 Self::CompoundDelimited(b) => b.caption(),
780 Self::Admonition(b) => b.caption(),
781 Self::Quote(b) => b.caption(),
782 Self::Table(b) => b.caption(),
783 Self::Preamble(b) => b.caption(),
784 Self::Break(b) => b.caption(),
785 Self::DocumentAttribute(b) => b.caption(),
786 }
787 }
788
789 fn number(&self) -> Option<usize> {
790 match self {
791 Self::Simple(b) => b.number(),
792 Self::Media(b) => b.number(),
793 Self::Section(b) => b.number(),
794 Self::List(b) => b.number(),
795 Self::ListItem(b) => b.number(),
796 Self::RawDelimited(b) => b.number(),
797 Self::CompoundDelimited(b) => b.number(),
798 Self::Admonition(b) => b.number(),
799 Self::Quote(b) => b.number(),
800 Self::Table(b) => b.number(),
801 Self::Preamble(b) => b.number(),
802 Self::Break(b) => b.number(),
803 Self::DocumentAttribute(b) => b.number(),
804 }
805 }
806
807 fn anchor(&'src self) -> Option<Span<'src>> {
808 match self {
809 Self::Simple(b) => b.anchor(),
810 Self::Media(b) => b.anchor(),
811 Self::Section(b) => b.anchor(),
812 Self::List(b) => b.anchor(),
813 Self::ListItem(b) => b.anchor(),
814 Self::RawDelimited(b) => b.anchor(),
815 Self::CompoundDelimited(b) => b.anchor(),
816 Self::Admonition(b) => b.anchor(),
817 Self::Quote(b) => b.anchor(),
818 Self::Table(b) => b.anchor(),
819 Self::Preamble(b) => b.anchor(),
820 Self::Break(b) => b.anchor(),
821 Self::DocumentAttribute(b) => b.anchor(),
822 }
823 }
824
825 fn anchor_reftext(&'src self) -> Option<Span<'src>> {
826 match self {
827 Self::Simple(b) => b.anchor_reftext(),
828 Self::Media(b) => b.anchor_reftext(),
829 Self::Section(b) => b.anchor_reftext(),
830 Self::List(b) => b.anchor_reftext(),
831 Self::ListItem(b) => b.anchor_reftext(),
832 Self::RawDelimited(b) => b.anchor_reftext(),
833 Self::CompoundDelimited(b) => b.anchor_reftext(),
834 Self::Admonition(b) => b.anchor_reftext(),
835 Self::Quote(b) => b.anchor_reftext(),
836 Self::Table(b) => b.anchor_reftext(),
837 Self::Preamble(b) => b.anchor_reftext(),
838 Self::Break(b) => b.anchor_reftext(),
839 Self::DocumentAttribute(b) => b.anchor_reftext(),
840 }
841 }
842
843 fn attrlist(&'src self) -> Option<&'src Attrlist<'src>> {
844 match self {
845 Self::Simple(b) => b.attrlist(),
846 Self::Media(b) => b.attrlist(),
847 Self::Section(b) => b.attrlist(),
848 Self::List(b) => b.attrlist(),
849 Self::ListItem(b) => b.attrlist(),
850 Self::RawDelimited(b) => b.attrlist(),
851 Self::CompoundDelimited(b) => b.attrlist(),
852 Self::Admonition(b) => b.attrlist(),
853 Self::Quote(b) => b.attrlist(),
854 Self::Table(b) => b.attrlist(),
855 Self::Preamble(b) => b.attrlist(),
856 Self::Break(b) => b.attrlist(),
857 Self::DocumentAttribute(b) => b.attrlist(),
858 }
859 }
860
861 fn substitution_group(&self) -> SubstitutionGroup {
862 match self {
863 Self::Simple(b) => b.substitution_group(),
864 Self::Media(b) => b.substitution_group(),
865 Self::Section(b) => b.substitution_group(),
866 Self::List(b) => b.substitution_group(),
867 Self::ListItem(b) => b.substitution_group(),
868 Self::RawDelimited(b) => b.substitution_group(),
869 Self::CompoundDelimited(b) => b.substitution_group(),
870 Self::Admonition(b) => b.substitution_group(),
871 Self::Quote(b) => b.substitution_group(),
872 Self::Table(b) => b.substitution_group(),
873 Self::Preamble(b) => b.substitution_group(),
874 Self::Break(b) => b.substitution_group(),
875 Self::DocumentAttribute(b) => b.substitution_group(),
876 }
877 }
878}
879
880impl<'src> HasSpan<'src> for Block<'src> {
881 fn span(&self) -> Span<'src> {
882 match self {
883 Self::Simple(b) => b.span(),
884 Self::Media(b) => b.span(),
885 Self::Section(b) => b.span(),
886 Self::List(b) => b.span(),
887 Self::ListItem(b) => b.span(),
888 Self::RawDelimited(b) => b.span(),
889 Self::CompoundDelimited(b) => b.span(),
890 Self::Admonition(b) => b.span(),
891 Self::Quote(b) => b.span(),
892 Self::Table(b) => b.span(),
893 Self::Preamble(b) => b.span(),
894 Self::Break(b) => b.span(),
895 Self::DocumentAttribute(b) => b.span(),
896 }
897 }
898}