diff --git a/php-transformer/src/HtmlToBlocks/Elements/InlineFlowLowering.php b/php-transformer/src/HtmlToBlocks/Elements/InlineFlowLowering.php
new file mode 100644
index 000000000..7691952a8
--- /dev/null
+++ b/php-transformer/src/HtmlToBlocks/Elements/InlineFlowLowering.php
@@ -0,0 +1,120 @@
+|null
+ */
+ public function textFlowBlockFromElement(DOMElement $element): ?array
+ {
+ if ( 'div' !== strtolower($element->tagName) || '' !== trim(SourceDom::attr($element, 'id')) || '' !== trim(SourceDom::attr($element, 'role')) ) {
+ return null;
+ }
+
+ $hasLineBreak = false;
+ foreach ( $element->childNodes as $child ) {
+ if ( ! $child instanceof DOMElement ) {
+ continue;
+ }
+
+ $tagName = strtolower($child->tagName);
+ if ( 'br' === $tagName ) {
+ $hasLineBreak = true;
+ }
+ if ( 'br' !== $tagName && ! $this->sourceElementClassifier->isInlineContentElement($tagName) && 'a' !== $tagName ) {
+ return null;
+ }
+ }
+
+ if ( ! $hasLineBreak ) {
+ return null;
+ }
+
+ $content = $this->richTextMaterializer->contentWithoutDecorativeSvg($element);
+ if ( '' === trim($this->runtime->stripAllTags($content)) ) {
+ return null;
+ }
+
+ return $this->blocks->createBlock('core/paragraph', array_merge($this->styleResolver->presentationAttributes($element), array( 'content' => $content )), array(), $element);
+ }
+
+ public function inlineTokenGroupBlockFromElement(DOMElement $element, array &$fallbacks): ?array
+ {
+ if ( ! ShellLandmarkPolicy::isInlineTokenContainerTag($element->tagName) ) {
+ return null;
+ }
+
+ if ( ! $this->sourceElementClassifier->hasInlineTokenGroupSignal($element) ) {
+ return null;
+ }
+
+ $children = array();
+ foreach ( $element->childNodes as $child ) {
+ if ( XML_TEXT_NODE === $child->nodeType ) {
+ if ( '' !== trim($child->textContent ?? '') ) {
+ return null;
+ }
+ continue;
+ }
+
+ if ( ! $child instanceof DOMElement ) {
+ continue;
+ }
+
+ if ( ! $this->sourceElementClassifier->isInlineTokenItemElement($child) ) {
+ return null;
+ }
+
+ $tagName = strtolower($child->tagName);
+ if ( in_array($tagName, array( 'a', 'button' ), true) ) {
+ $block = $this->tree->element($child, $fallbacks, true);
+ if ( null === $block ) {
+ return null;
+ }
+ $children[] = $block;
+ continue;
+ }
+
+ $content = $this->styleResolver->innerHtml($child);
+ if ( '' === trim($this->runtime->stripAllTags($content)) ) {
+ return null;
+ }
+ $children[] = $this->blocks->createBlock('core/paragraph', array_merge($this->styleResolver->presentationAttributes($child), array( 'content' => $content )), array(), $child);
+ }
+
+ if ( count($children) < 2 ) {
+ return null;
+ }
+
+ return $this->blocks->createBlock('core/group', $this->styleResolver->presentationAttributes($element), $children, $element);
+ }
+}
diff --git a/php-transformer/src/HtmlToBlocks/HtmlCompilation.php b/php-transformer/src/HtmlToBlocks/HtmlCompilation.php
index f8bd86489..1634d158e 100644
--- a/php-transformer/src/HtmlToBlocks/HtmlCompilation.php
+++ b/php-transformer/src/HtmlToBlocks/HtmlCompilation.php
@@ -291,6 +291,7 @@ final class HtmlCompilation extends SourceBlockCreator implements RichTextInline
private readonly SvgMaterializer $svgMaterializer;
private readonly Elements\AuthoredStateButtonLowering $authoredStateButtons;
private readonly Elements\InlineSvgTextGroupLowering $inlineSvgTextGroups;
+ private readonly Elements\InlineFlowLowering $inlineFlows;
private readonly RichTextMaterializer $richTextMaterializer;
private readonly Style\SourceElementVisibility $sourceVisibility;
@@ -525,6 +526,7 @@ public function __construct(
$this->flankedSeparators = new Elements\FlankedSeparatorLowering($this, $this->styleResolver, $this->sourceElementClassifier);
$this->sourceVisibility = new Style\SourceElementVisibility($this->styleResolver);
$this->richTextMaterializer = new RichTextMaterializer($this->styleResolver, $this->svgMaterializer, $this->session, $this);
+ $this->inlineFlows = new Elements\InlineFlowLowering($this, $this, $this->styleResolver, $this->sourceElementClassifier, $this->richTextMaterializer, $this->runtime);
$this->authoredStateButtons = new Elements\AuthoredStateButtonLowering($this->session, $this->svgMaterializer);
$this->linkedIconTextRows = new Elements\LinkedIconTextRowLowering(
$this,
@@ -1045,14 +1047,14 @@ function (DOMElement $element, array &$fallbacks, bool $captureUnsupported): arr
},
mediaGalleryBlock: fn (DOMElement $element, array &$fallbacks): ?array => $this->mediaGalleryBlockFromElement($element, $fallbacks),
namePriceRowBlock: fn (DOMElement $element, array &$fallbacks): ?array => $this->namePriceRowBlockFromElement($element, $fallbacks),
- inlineTokenGroupBlock: fn (DOMElement $element, array &$fallbacks): ?array => $this->inlineTokenGroupBlockFromElement($element, $fallbacks),
+ inlineTokenGroupBlock: fn (DOMElement $element, array &$fallbacks): ?array => $this->inlineFlows->inlineTokenGroupBlockFromElement($element, $fallbacks),
visualTextWrapperBlock: fn (DOMElement $element): ?array => $this->visualTextWrapperBlockFromElement($element),
standaloneSearchBlock: fn (DOMElement $element): ?array => $this->searchBlockConverter->searchBlockFromStandaloneControl($element),
readableFormControlBlock: fn (DOMElement $element): ?array => $this->readableFormControlBlockConverter->convert($element),
cssAuthoredMarqueeBlock: fn (DOMElement $element): ?array => $this->authoredMarqueeRecognizer->cssAuthoredMarqueeBlock($element),
authoredCarouselBlock: fn (DOMElement $element): ?array => $this->authoredCarouselGenerator->convert($element),
generatedComponentBlock: fn (DOMElement $element, array &$fallbacks): ?array => $this->nativeOrGeneratedComponentBlock($element, $fallbacks),
- textFlowBlock: fn (DOMElement $element): ?array => $this->textFlowBlockFromElement($element),
+ textFlowBlock: fn (DOMElement $element): ?array => $this->inlineFlows->textFlowBlockFromElement($element),
convertChildren: fn (DOMElement $element, array &$fallbacks): array => $this->convertChildren($element, $fallbacks, true),
backgroundImageBlock: fn (DOMElement $element): ?array => $this->imageLowering->backgroundImageBlock($element),
coalescedSingleGroupWrapper: fn (DOMElement $element, array $child): ?array => $this->coalescedSingleGroupWrapper($element, $child),
@@ -5096,42 +5098,6 @@ private function authoredDisplay(DOMElement $element): string
return $this->authorLayoutOwnership->authoredDisplay($element);
}
- /**
- * @return array|null
- */
- private function textFlowBlockFromElement(DOMElement $element): ?array
- {
- if ( 'div' !== strtolower($element->tagName) || '' !== trim($this->attr($element, 'id')) || '' !== trim($this->attr($element, 'role')) ) {
- return null;
- }
-
- $hasLineBreak = false;
- foreach ( $element->childNodes as $child ) {
- if ( ! $child instanceof DOMElement ) {
- continue;
- }
-
- $tagName = strtolower($child->tagName);
- if ( 'br' === $tagName ) {
- $hasLineBreak = true;
- }
- if ( 'br' !== $tagName && ! $this->sourceElementClassifier->isInlineContentElement($tagName) && 'a' !== $tagName ) {
- return null;
- }
- }
-
- if ( ! $hasLineBreak ) {
- return null;
- }
-
- $content = $this->richTextMaterializer->contentWithoutDecorativeSvg($element);
- if ( '' === trim($this->runtime->stripAllTags($content)) ) {
- return null;
- }
-
- return $this->createBlock('core/paragraph', array_merge($this->styleResolver->presentationAttributes($element), array( 'content' => $content )), array(), $element);
- }
-
/**
* Lower a foreignObject-only "fit text" SVG to the native text block its
* inner element renders as (`