Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

53 changes: 53 additions & 0 deletions tests/BFBConversionUnitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,35 @@ public function detect( string $content ): bool {
$this->assertSame( array( 'mode' => 'fidelity' ), $probe->received_options, 'Generic adapters should receive public conversion options.' );
}

/**
* Resolved asset metadata should flow through BFB into h2bc media transforms.
*/
public function test_asset_metadata_context_enriches_h2bc_image_blocks(): void {
$serialized = bfb_convert(
'<img src="assets/hero.jpg" alt="Source alt" width="1200" height="800">',
'html',
'blocks',
array(
'context' => array(
'asset_metadata' => array(
'assets/hero.jpg' => array(
'id' => 42,
'url' => 'https://example.test/wp-content/uploads/hero.jpg',
),
),
),
)
);

$blocks = parse_blocks( $serialized );
$image = $this->first_block_named( $blocks, 'core/image' );

$this->assertNotNull( $image );
$this->assertSame( 42, $image['attrs']['id'] ?? null );
$this->assertStringContainsString( 'alt="Source alt"', $image['innerHTML'] ?? '' );
$this->assertStringContainsString( 'src="https://example.test/wp-content/uploads/hero.jpg"', $image['innerHTML'] ?? '' );
}

/**
* BFB should expose h2bc's expanded layout transforms through bfb_convert().
*/
Expand Down Expand Up @@ -1000,6 +1029,30 @@ private function flatten_blocks( array $blocks ): array {
return $names;
}

/**
* Find the first block with the requested name in a parsed block tree.
*
* @param array<int, array<string, mixed>> $blocks Parsed blocks.
* @param string $name Block name.
* @return array<string, mixed>|null Matching block, or null.
*/
private function first_block_named( array $blocks, string $name ): ?array {
foreach ( $blocks as $block ) {
if ( $name === ( $block['blockName'] ?? null ) ) {
return $block;
}

if ( ! empty( $block['innerBlocks'] ) && is_array( $block['innerBlocks'] ) ) {
$inner = $this->first_block_named( $block['innerBlocks'], $name );
if ( null !== $inner ) {
return $inner;
}
}
}

return null;
}

/**
* Assert every expected substring appears in a conversion result.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ public static function from_html(string $html): ?self
if (empty($html)) {
return null;
}
if (\preg_match('/^<\s*(area|base|br|col|embed|hr|img|input|link|meta|param|source|track|wbr)\b([^>]*)\/?>\s*$/i', $html, $matches)) {
return new self($matches[1], self::parse_attribute_string($matches[2]), $html, '');
}
$processor = \WP_HTML_Processor::create_fragment($html);
if (!$processor) {
return null;
Expand Down Expand Up @@ -102,6 +105,30 @@ private static function extract_attributes(\WP_HTML_Processor $processor): array
}
return $attributes;
}
/**
* Parses attributes from a raw opening tag string.
*
* @param string $attribute_string Raw attribute markup.
* @return array Attribute map.
*/
private static function parse_attribute_string(string $attribute_string): array
{
$attributes = array();
if (\preg_match_all('/([a-zA-Z_:][-a-zA-Z0-9_:.]*)\s*=\s*("([^"]*)"|\'([^\']*)\'|([^\s"\'>]+))/', $attribute_string, $matches, \PREG_SET_ORDER)) {
foreach ($matches as $match) {
$value = '';
if (isset($match[3]) && '' !== $match[3]) {
$value = $match[3];
} elseif (isset($match[4]) && '' !== $match[4]) {
$value = $match[4];
} elseif (isset($match[5])) {
$value = $match[5];
}
$attributes[\strtolower($match[1])] = \html_entity_decode($value, \ENT_QUOTES, 'UTF-8');
}
}
return $attributes;
}
/**
* Extracts inner HTML from an element string
*
Expand Down
Loading
Loading