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
1 change: 1 addition & 0 deletions php-transformer/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,7 @@
"php tests/unit/navigation-resolved-projection-spacing.php",
"php tests/unit/source-target-projection-state.php",
"php tests/unit/navigation-layout-default.php",
"php tests/unit/navigation-stacked-block-list-layout.php",
"php tests/unit/navigation-vertical-orientation.php",
"php tests/unit/navigation-source-provenance.php",
"php tests/unit/navigation-dropped-anchors.php",
Expand Down
46 changes: 46 additions & 0 deletions php-transformer/src/HtmlToBlocks/Patterns/NavigationPattern.php
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,9 @@ public function recognize(DOMElement $element, PatternContext $context): ?Patter
$navigationAttrs['layout'] = array( 'type' => 'flex', 'orientation' => 'vertical' );
}
$navigationAttrs['overlayMenu'] = $this->overlayMenu($element, $navigationContext);
if ( 'never' === $navigationAttrs['overlayMenu'] && ! $label instanceof DOMElement ) {
$navigationAttrs = $this->withStackedBlockListLayout($navigationAttrs, $navigationSource, $listSource, $navigationContext);
}
if ( 'mobile' === $navigationAttrs['overlayMenu'] ) {
$navigationAttrs = $this->withClassName($navigationAttrs, 'blocks-engine-native-responsive-navigation');
$navigationAttrs = $this->withResponsiveToggleMarker($navigationAttrs, $element, $navigationContext);
Expand Down Expand Up @@ -1203,6 +1206,49 @@ private function withResolvedNonFlexNavigationLayout(array $attrs, DOMElement $e
return $attrs;
}

/**
* Carry a source list that stacks block items onto core's flow layout.
*
* An in-flow list navigation renders its generated list as
* `display:contents`, so the items lay out in the navigation host. With no
* layout the host is core's flex row, and items the source stacked full
* width shrink to their min-width instead. When neither the host nor its
* list declares a display, the source list is a block box; the items prove
* the stack only when every one declares a block-level display. Floated
* block items still need flow: a flex row ignores the float that the
* projected item rule carries. Without item evidence core's default stays.
*
* @param array<string, mixed> $attrs
* @return array<string, mixed>
*/
private function withStackedBlockListLayout(array $attrs, DOMElement $host, ?DOMElement $list, ?NavigationPatternContext $navigationContext): array
{
if ( null === $navigationContext || ! $list instanceof DOMElement || is_array($attrs['layout'] ?? null)
|| '' !== trim($navigationContext->resolvedDisplay($host))
|| '' !== trim($navigationContext->resolvedDisplay($list))
) {
return $attrs;
}

$items = 0;
foreach ( $list->childNodes as $child ) {
if ( ! $child instanceof DOMElement || 'li' !== strtolower($child->tagName) ) {
continue;
}
$display = strtolower(trim($navigationContext->resolvedDisplay($child)));
if ( ! in_array($display, array( 'block', 'list-item', 'flow-root' ), true) ) {
return $attrs;
}
++$items;
}

if ( 0 < $items ) {
$attrs['layout'] = array( 'type' => 'default' );
}

return $attrs;
}

/**
* Carry a source menu whose cascade stacks its items in a column onto
* core/navigation's vertical orientation.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@
{
"id": "2448c3c2ebf7c03839a1ad542beec24efd2a805c",
"entry": "HtmlTransformer::transform",
"expected_sha256": "241e746902379c4decbeb3b64549c6310791c6d6535c51b83b01b83059f98224",
"expected_sha256": "71634f402ac1c35b2b58aa7a84368a05df1eefae88fd57710e8613f985781b01",
"outcome": "output"
},
{
Expand Down Expand Up @@ -323,7 +323,7 @@
{
"id": "2890e8f1ed5ae188e261c80d3c9a1ad1e1928cd2",
"entry": "HtmlTransformer::transform",
"expected_sha256": "eb37f1652823bd47a70755937fe0632ca5d1464660cad51b999e4dabc1419163",
"expected_sha256": "3eebcdcab44579a25d3086471a45fc14df01fdbbc47b55f8143a61575e554259",
"outcome": "output"
},
{
Expand Down Expand Up @@ -539,7 +539,7 @@
{
"id": "448ead36f649a72e98e642cebc29f9f71af779f5",
"entry": "HtmlTransformer::transform",
"expected_sha256": "631b17e61a09b144cf92acf35c1388d3cbf1542fc15e5aeb858a0dfacac142b7",
"expected_sha256": "788553d7c9d9def419dcde4bcceb82aa342e2738cf5ddc4337578d1e77aab4a9",
"outcome": "output"
},
{
Expand Down Expand Up @@ -569,7 +569,7 @@
{
"id": "46f79246a3c128cd0672e296d1164e4d6882750a",
"entry": "HtmlTransformer::transform",
"expected_sha256": "7bd66a28531c17d5e2b7c45a491a8ab8c1acaa98f59adc4b748fbfe65afcf2b4",
"expected_sha256": "f26a1bc83d32db0bf72caffb515b27c3c8ca10e6806b70220ce8572cb31da295",
"outcome": "output"
},
{
Expand Down Expand Up @@ -1349,7 +1349,7 @@
{
"id": "a5a08a8615d2682ce0d38a5053bcec23199be36f",
"entry": "HtmlTransformer::transform",
"expected_sha256": "7fb14b9b715633998d19b1f060d54e71396285c5e63c30103dfe33760db2c034",
"expected_sha256": "e5b0e2aff14da96082ecfcee6553949478c0a26b6591bd00f94151319390938a",
"outcome": "output"
},
{
Expand Down Expand Up @@ -1439,7 +1439,7 @@
{
"id": "b550beb0271acdd852382b101d2fc6653b1cb107",
"entry": "HtmlTransformer::transform",
"expected_sha256": "03c14aaf5f28dc4d2bc8846e033f7b7a8d4e3e4e92b081af72582825de6f956c",
"expected_sha256": "20727b3683cd0dec389f6ddb8b48258c920462384880aaa2771bdb7c29b37f4d",
"outcome": "output"
},
{
Expand Down Expand Up @@ -1607,7 +1607,7 @@
{
"id": "c7fff215fed715e93aa155c4e0e5e31d7db084b1",
"entry": "HtmlTransformer::transform",
"expected_sha256": "617d6414e9b6c7ea4b1449c99e3032204fadbed75f2928c5fdaaa926d54dba4a",
"expected_sha256": "106e074f127f6f0447ad54bdae1ace6d467caf6cbe642625c1fb6ed05e4d9064",
"outcome": "output"
},
{
Expand Down Expand Up @@ -1817,7 +1817,7 @@
{
"id": "e2e35d0c5c02ff06b23bc87fb59bc585201bc46f",
"entry": "HtmlTransformer::transform",
"expected_sha256": "21ac153f4c03dc58a8aa26d880caed406d3a1c5eff6b433998c6a6be5356f24a",
"expected_sha256": "ae10e2c73a21de5017246eb1b17695f380c99f9a151fc48d7d31dec731980f95",
"outcome": "output"
},
{
Expand Down Expand Up @@ -1937,7 +1937,7 @@
{
"id": "f025cf281f15d03cf61d0c76c1f4bd7adc3b257e",
"entry": "HtmlTransformer::transform",
"expected_sha256": "d593dbb9d4e959252de18457290377da1fb9ccd0b8a840a2cd747d9349c0916d",
"expected_sha256": "fd454ce10af80c82684627e69547bdb36f3fcb030dfcc3e5a2eac6e3c160fd94",
"outcome": "output"
},
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php
declare(strict_types=1);

/**
* A list navigation whose items the source stacks as blocks keeps that flow.
*
* An in-flow list navigation renders its generated list as
* `display:contents`, so the items lay out in core/navigation itself. With no
* layout that is core's flex row: a Wix phone menu (`.menu>ul li{display:block}`
* with no display on the nav or the list) came out as flex items sized by their
* `min-width`, and the longer labels were cut off. Only item evidence switches
* the default: an unstyled menu, inline items, and a flex list keep
* core's row.
*/

require dirname(__DIR__, 2) . '/vendor/autoload.php';

use Automattic\BlocksEngine\PhpTransformer\HtmlToBlocks\HtmlTransformer;

$failures = 0;
$passes = 0;
$assert = static function (bool $ok, string $message, string $detail = '') use (&$failures, &$passes): void {
if ( $ok ) {
++$passes;
return;
}
++$failures;
fwrite(STDERR, 'FAIL: ' . $message . ( '' !== $detail ? ' - ' . $detail : '' ) . PHP_EOL);
};

$items = '';
foreach ( array( 'Contact Us' => '/contact', 'Annual Meetings' => '/meetings', 'News &amp; Events' => '/events' ) as $label => $href ) {
$items .= '<li class="item"><div class="box"><span class="wrap"><a class="link" href="' . $href . '">' . $label . '</a></span></div></li>';
}
$layout = static function (string $css, string $scope = '') use ($items): ?array {
$body = '<nav class="menu"><ul class="list">' . $items . '</ul></nav>';
if ( '' !== $scope ) {
$body = '<div class="data-liberation-mobile-document" data-dla-device-document="mobile" data-dla-document-scope="">'
. '<header>' . $body . '</header><main><p>Body</p></main></div>';
}
$serialized = (string) (( new HtmlTransformer() )->transform('<style>' . $css . '</style>' . $body, array())->toArray()['serialized_blocks'] ?? '');
if ( 1 !== preg_match('/<!-- wp:navigation (\{.*?\}) (?:\/)?-->/', $serialized, $match) ) {
return array( 'missing' => true );
}
$attrs = json_decode($match[1], true);

return is_array($attrs) && is_array($attrs['layout'] ?? null) ? $attrs['layout'] : null;
};
$menu = static fn (string $scope, string $itemRule): string => $scope . '.menu{direction:ltr}'
. $scope . '.menu>ul{box-sizing:border-box;width:100%}'
. $scope . '.menu>ul li{' . $itemRule . '}'
. $scope . '.item{min-width:100px}'
. $scope . '.item .box{display:grid;height:45px}';

$scope = ':where([data-dla-device-document="mobile"]) ';
$assert(
array( 'type' => 'default' ) === $layout($menu($scope, 'display:block'), $scope),
'a device-scoped menu whose items are declared block stacks in core flow',
json_encode($layout($menu($scope, 'display:block'), $scope))
);
$assert(
array( 'type' => 'default' ) === $layout($menu('', 'display:block')),
'the same menu without a device scope stacks in core flow'
);
$assert(
array( 'type' => 'default' ) === $layout($menu('', 'display:list-item')),
'list-item items are block-level too'
);
$assert(null === $layout($menu('', 'display:inline-block')), 'inline-block items keep core\'s row');
$assert(
array( 'type' => 'default' ) === $layout($menu('', 'display:block;float:left')),
'floated block items take flow, where their projected float still applies'
);
$assert(null === $layout($menu('', 'display:block') . '.menu>ul{display:flex}'), 'a flex list keeps core\'s row');
$assert(null === $layout('.menu{direction:ltr}'), 'a menu without item display evidence keeps core\'s default');

if ( 0 < $failures ) {
fwrite(STDERR, "Navigation stacked block list layout: {$failures} failed, {$passes} passed\n");
exit(1);
}

echo "Navigation stacked block list layout passed: {$passes} assertions\n";
6 changes: 6 additions & 0 deletions php-transformer/tools/capture-evidence-equivalence/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ replay by case:
source trigger buttons with `data-blocks-engine-tab-trigger`, so their box
styling carries onto native tab buttons. The projected HTML gains the marker
and the tab-list carrier class hash changes in `173a88a2`, `56cfc02b`, `5ad295f6`, `5af9c0c1`, `6657cdac`, `6a79dc90`, `88ac82df`, `8a631c3c`, `8c22a321`, `983aa909`, `9885239b`, `ca0b670d`, `d28fa845`, `d76cc245`, `e970e58c`, `f159a7b6`.
- **Declared block menu items stack in core flow** (#2726). A list
navigation whose items all declare a block-level display, with no display
on the nav or its list, records `"layout":{"type":"default"}`. That adds
the attribute in `46f79246` and `e2e35d0c`. The extra display lookups only
move the style-rule candidate cache counters in `2448c3c2`, `2890e8f1`,
`448ead36`, `a5a08a86`, `b550beb0`, `c7fff215` and `f025cf28`.

When regenerating from the pre-move commit, re-record these cases from the
checkout that introduced them, and only after checking the difference again.
Expand Down
Loading