Repository: typst/typst
File: crates/typst-pdf/src/tags/tree/build.rs (Rust)

Code before:
        if !matches!(tree.parent_kind(), GroupKind::Grid(..)) {
            let kind = GroupKind::InternalGridCell(InternalGridCellKind::Transparent);
            return push_stack(tree, elem, kind);
        }

        // The grid cells are collected into a grid to ensure proper reading
        // order, even when using rowspans, which may be laid out later than
        // other cells in the same row.

        // Only repeated grid headers and footer cells are laid out multiple
        // times. Mark duplicate headers as artifacts, since they have no
        // semantic meaning in the tag tree, which doesn't use page breaks for
        // it's semantic structure.
        let kind = if cell.is_repeated.val() {
            let artifact = InternalGridCellKind::Artifact(ArtifactType::Other);
            GroupKind::InternalGridCell(artifact)
        } else {
            GroupKind::GridCell(cell.clone(), None)
        };
        push_stack(tree, elem, kind)
    } else if let Some(heading) = elem.to_packed::<HeadingElem>() {
        let level = heading.level().try_into().unwrap_or(NonZeroU16::MAX);
        let title = heading.body.plain_text().to_string();
        if title.is_empty() && tree.options.is_pdf_ua() {
            let contains_context = heading.body.traverse(&mut |c| {
                if c.elem() == ContextElem::ELEM {
                    return ControlFlow::Break(());
                }
                ControlFlow::Continue(())
            });
            let validator = tree.options.standards.config.validator().as_str();
            tree.errors.push(if contains_context.is_break() {
                error!(
                    heading.span(),
                    "{validator} error: heading title is empty";
                    hint: "this seems to be caused by a context expression";
                    hint: "consider wrapping the entire heading in a context expression"
                )
            } else {
                error!(heading.span(), "{validator} error: heading title is empty")
            });
        }
        push_tag(tree, elem, Tag::Hn(level, Some(title)))
    } else if let Some(_) = elem.to_packed::<FootnoteElem>() {
        push_stack(tree, elem, GroupKind::LogicalParent(elem.clone()))
    } else if let Some(_) = elem.to_packed::<FootnoteEntry>() {
        push_tag(tree, elem, Tag::Note)
    } else if let Some(quote) = elem.to_packed::<QuoteElem>() {
        // TODO: should the attribution be handled somehow?
        if quote.block.val() {
            push_tag(tree, elem, Tag::BlockQuote)

Review comment (suggestion):
```suggestion
                if c.is::<ContextElem>() {
```

Code after:
        if !matches!(tree.parent_kind(), GroupKind::Grid(..)) {
            let kind = GroupKind::InternalGridCell(InternalGridCellKind::Transparent);
            return push_stack(tree, elem, kind);
        }

        // The grid cells are collected into a grid to ensure proper reading
        // order, even when using rowspans, which may be laid out later than
        // other cells in the same row.

        // Only repeated grid headers and footer cells are laid out multiple
        // times. Mark duplicate headers as artifacts, since they have no
        // semantic meaning in the tag tree, which doesn't use page breaks for
        // it's semantic structure.
        let kind = if cell.is_repeated.val() {
            let artifact = InternalGridCellKind::Artifact(ArtifactType::Other);
            GroupKind::InternalGridCell(artifact)
        } else {
            GroupKind::GridCell(cell.clone(), None)
        };
        push_stack(tree, elem, kind)
    } else if let Some(heading) = elem.to_packed::<HeadingElem>() {
        let level = heading.level().try_into().unwrap_or(NonZeroU16::MAX);
        let title = heading.body.plain_text().to_string();
        if title.is_empty() && tree.options.is_pdf_ua() {
            let contains_context = heading.body.traverse(&mut |c| {
                if c.is::<ContextElem>() {
                    return ControlFlow::Break(());
                }
                ControlFlow::Continue(())
            });
            let validator = tree.options.standards.config.validator().as_str();
            tree.errors.push(if contains_context.is_break() {
                error!(
                    heading.span(),
                    "{validator} error: heading title could not be determined";
                    hint: "this seems to be caused by a context expression within the heading";
                    hint: "consider wrapping the entire heading in a context expression instead"
                )
            } else {
                error!(heading.span(), "{validator} error: heading title is empty")
            });
        }
        push_tag(tree, elem, Tag::Hn(level, Some(title)))
    } else if let Some(_) = elem.to_packed::<FootnoteElem>() {
        push_stack(tree, elem, GroupKind::LogicalParent(elem.clone()))
    } else if let Some(_) = elem.to_packed::<FootnoteEntry>() {
        push_tag(tree, elem, Tag::Note)
    } else if let Some(quote) = elem.to_packed::<QuoteElem>() {
        // TODO: should the attribution be handled somehow?
        if quote.block.val() {
            push_tag(tree, elem, Tag::BlockQuote)