Correctly interpret prefixes in CSS display.

This commit is contained in:
Martín Lucas Golini
2026-07-30 19:53:20 -03:00
parent a2ee615553
commit 774e09efc2
3 changed files with 80 additions and 0 deletions
+10
View File
@@ -40,6 +40,16 @@ std::string CSSDisplayHelper::toString( CSSDisplay display ) {
};
CSSDisplay CSSDisplayHelper::fromString( std::string_view val ) {
static constexpr std::string_view VendorPrefixes[] = { "-webkit-", "-moz-", "-ms-", "-o-" };
if ( !val.empty() && val.front() == '-' ) {
for ( std::string_view prefix : VendorPrefixes ) {
if ( val.size() > prefix.size() && val.substr( 0, prefix.size() ) == prefix ) {
val.remove_prefix( prefix.size() );
break;
}
}
}
CSSDisplay display = CSSDisplay::Block;
if ( val == "inline" )
display = CSSDisplay::Inline;
+57
View File
@@ -35,6 +35,63 @@ static void init_flex_test() {
themeManager->applyDefaultTheme( sceneNode->getRoot() );
}
UTEST( FlexContainer, vendorPrefixedDisplayValues ) {
EXPECT_EQ( CSSDisplayHelper::fromString( "-webkit-flex" ), CSSDisplay::Flex );
EXPECT_EQ( CSSDisplayHelper::fromString( "-webkit-inline-flex" ), CSSDisplay::InlineFlex );
EXPECT_EQ( CSSDisplayHelper::fromString( "-moz-flex" ), CSSDisplay::Flex );
EXPECT_EQ( CSSDisplayHelper::fromString( "-ms-inline-grid" ), CSSDisplay::InlineGrid );
}
UTEST( FlexContainer, webkitFlexFooterKeepsColumnsAndVerticalLists ) {
Engine::instance()->createWindow( WindowSettings( 800, 600, "WebKit Flex Footer Test",
WindowStyle::Default, WindowBackend::Default,
32, {}, 1, false, true ),
ContextSettings( false, 0, 0, GLv_default, true, false ) );
init_flex_test();
UISceneNode* sceneNode = SceneManager::instance()->getUISceneNode();
sceneNode->loadLayoutFromString( Tools::HTMLFormatter::HTMLtoXML( R"html(
<html><head><style>
.footer { display: flex; display: -webkit-flex; width: 600px; }
.footer .col {
display: inline-block; flex: 0 0 25%; padding: 0 15px;
box-sizing: border-box;
}
.footer ul { display: block; }
.footer li { display: list-item; }
</style></head><body>
<div id="footer" class="footer">
<div class="col"><ul><li>about</li><li>blog</li><li>careers</li></ul></div>
<div class="col"><ul><li>help</li><li>rules</li><li>contact</li></ul></div>
<div class="col"><ul><li>apps</li><li>iPhone</li><li>Android</li></ul></div>
<div class="col"><ul><li>premium</li><li>buy</li></ul></div>
</div>
</body></html>
)html" ) );
sceneNode->updateDirtyLayouts();
auto* footer = sceneNode->getRoot()->find( "footer" )->asType<UIHTMLWidget>();
ASSERT_TRUE( footer != nullptr );
EXPECT_EQ( footer->getDisplay(), CSSDisplay::Flex );
auto columns = footer->findAllByClass( "col" );
ASSERT_EQ( columns.size(), (size_t)4 );
Float previousColumnRight = 0.f;
for ( auto* column : columns ) {
EXPECT_GE( column->getPixelsPosition().x, previousColumnRight );
previousColumnRight = column->getPixelsPosition().x + column->getPixelsSize().getWidth();
auto items = column->findAllByTag( "li" );
ASSERT_FALSE( items.empty() );
Float previousItemBottom = 0.f;
for ( auto* item : items ) {
EXPECT_GE( item->getPixelsPosition().y, previousItemBottom );
previousItemBottom = item->getPixelsPosition().y + item->getPixelsSize().getHeight();
}
}
Engine::destroySingleton();
}
// ─────────────────────────────────────────────────────────────────────────────
// Phase 1: Item Collection
// ─────────────────────────────────────────────────────────────────────────────
+13
View File
@@ -314,6 +314,7 @@ UTEST( UIHTML, redditOldThreadWebViewSmoke ) {
auto flairCheckbox = documentRoot->find( "flair_enabled" );
auto commentButtons =
documentRoot->querySelector( "#thing_t1_on791mh > .entry > .flat-list.buttons" );
auto redditFooter = documentRoot->querySelector( ".footer-parent > .footer" );
ASSERT_TRUE( side != nullptr );
ASSERT_TRUE( siteTable != nullptr );
@@ -345,6 +346,18 @@ UTEST( UIHTML, redditOldThreadWebViewSmoke ) {
ASSERT_TRUE( commentContentPolicy != nullptr );
ASSERT_TRUE( flairCheckbox != nullptr );
ASSERT_TRUE( commentButtons != nullptr );
ASSERT_TRUE( redditFooter != nullptr );
EXPECT_EQ( redditFooter->asType<UIHTMLWidget>()->getDisplay(), CSSDisplay::Flex );
Float footerColumnRight = 0.f;
for ( auto* col : redditFooter->findAllByClass( "col" ) ) {
EXPECT_GE( col->getPixelsPosition().x, footerColumnRight );
footerColumnRight = col->getPixelsPosition().x + col->getPixelsSize().getWidth();
Float footerItemBottom = 0.f;
for ( auto* li : col->querySelectorAll( "li" ) ) {
EXPECT_GE( li->getPixelsPosition().y, footerItemBottom );
footerItemBottom = li->getPixelsPosition().y + li->getPixelsSize().getHeight();
}
}
Float commentButtonRight = 0.f;
for ( auto* li : commentButtons->findAllByTag( "li" ) ) {
ASSERT_TRUE( li->findByTag( "a" ) != nullptr );