diff --git a/php-transformer/src/HtmlToBlocks/Patterns/MediaTextPattern.php b/php-transformer/src/HtmlToBlocks/Patterns/MediaTextPattern.php index 508b6fe7c..2f3b7a080 100644 --- a/php-transformer/src/HtmlToBlocks/Patterns/MediaTextPattern.php +++ b/php-transformer/src/HtmlToBlocks/Patterns/MediaTextPattern.php @@ -208,6 +208,23 @@ public function match( return null; } + // Out-of-flow media (`position: absolute`/`fixed`) sizes against its + // containing block — typically the source media wrapper that sets + // `position: relative`, a min-height and overflow clipping — not a grid + // track. core/media-text replaces that wrapper with its own figure, so + // the media would resolve against a distant ancestor (often the + // viewport) and cover the text pane. Keep the authored wrapper through + // ordinary flow lowering, mirroring the out-of-flow text-pane gate. + if ( $this->declaresUnresolvableGateValue($mediaStyle, array( 'position' )) ) { + return null; + } + $mediaPosition = strtolower($this->normalizedCssValue( + (string) ($this->styleDeclarations($mediaStyle)['position'] ?? '') + )); + if ( in_array($mediaPosition, array( 'absolute', 'fixed' ), true) ) { + return null; + } + // core/media-text sizes its panes as grid tracks: a percentage media // track and the remainder for text. A flex row whose text pane alone // grows into the free space beside a fixed-size media pane has no diff --git a/php-transformer/tests/unit/media-text-pattern.php b/php-transformer/tests/unit/media-text-pattern.php index 3bc8d0b11..a9b68bd6b 100644 --- a/php-transformer/tests/unit/media-text-pattern.php +++ b/php-transformer/tests/unit/media-text-pattern.php @@ -1488,6 +1488,20 @@ static function (string $name, array $attrs, array $innerBlocks, ?DOMElement $so $assertTrue(is_array($genuineTwoPaneBlock), 'A genuine in-flow media/text pair still converts to core/media-text.'); $assertSame('core/heading', $genuineTwoPaneBlock['innerBlocks'][0]['blockName'] ?? null, 'Genuine two-pane text side keeps its heading identity.'); +// Out-of-flow media sizes against its source wrapper (the containing block), +// not a media-text grid track. Replacing that wrapper with media-text's figure +// lets the image resolve against the viewport, so the pattern declines and the +// authored wrapper survives with its stylesheet positioning. +$positionedMediaHtml = '' + . '

Heading

Copy beside a cover image.

' + . '
Photo
'; +$positionedMediaResult = $transformHtml($positionedMediaHtml); +$assertNull($collectMediaText($positionedMediaResult['blocks'] ?? array()), 'Absolutely positioned media keeps its source wrapper instead of lowering to core/media-text.'); +$fixedMediaResult = $transformHtml(str_replace('position:absolute}', 'position:fixed}', $positionedMediaHtml)); +$assertNull($collectMediaText($fixedMediaResult['blocks'] ?? array()), 'Fixed-position media also declines core/media-text.'); +$inFlowMediaResult = $transformHtml(str_replace(';position:absolute}', '}', $positionedMediaHtml)); +$assertTrue(is_array($collectMediaText($inFlowMediaResult['blocks'] ?? array())), 'In-flow media in the same layout still lowers to core/media-text.'); + if ( 0 === $failures ) { echo "media text pattern ok\n"; }