diff --git a/bin/assets/ui/breeze.css b/bin/assets/ui/breeze.css
index 48c6b0385..240c59a3d 100644
--- a/bin/assets/ui/breeze.css
+++ b/bin/assets/ui/breeze.css
@@ -148,52 +148,12 @@ ol > li {
padding-left: 2em;
}
-ol > li {
- background-tint: var(--font);
- background-position: 0.6em 0.3em;
+ul {
+ list-style-type: disc;
}
-ol > li:nth-child(1) {
- background-image: glyph("monospace", 1em, "1");
-}
-
-ol > li:nth-child(2) {
- background-image: glyph("monospace", 1em, "2");
-}
-
-ol > li:nth-child(3) {
- background-image: glyph("monospace", 1em, "3");
-}
-
-ol > li:nth-child(4) {
- background-image: glyph("monospace", 1em, "4");
-}
-
-ol > li:nth-child(5) {
- background-image: glyph("monospace", 1em, "5");
-}
-
-ol > li:nth-child(6) {
- background-image: glyph("monospace", 1em, "6");
-}
-
-ol > li:nth-child(7) {
- background-image: glyph("monospace", 1em, "7");
-}
-
-ol > li:nth-child(8) {
- background-image: glyph("monospace", 1em, "8");
-}
-
-ol > li:nth-child(9) {
- background-image: glyph("monospace", 1em, "9");
-}
-
-ul > li {
- background-image: url("data:image/svg,");
- background-tint: var(--font);
- background-position: 0.6em 0.45em;
- background-size: 0.5em 0.5em;
+ol {
+ list-style-type: decimal;
}
a {
diff --git a/include/eepp/ui/css/propertydefinition.hpp b/include/eepp/ui/css/propertydefinition.hpp
index 8205dee39..9e24f1282 100644
--- a/include/eepp/ui/css/propertydefinition.hpp
+++ b/include/eepp/ui/css/propertydefinition.hpp
@@ -247,6 +247,9 @@ enum class PropertyId : Uint32 {
Bottom = String::hash( "bottom" ),
Left = String::hash( "left" ),
ZIndex = String::hash( "z-index" ),
+ ListStyleType = String::hash( "list-style-type" ),
+ ListStylePosition = String::hash( "list-style-position" ),
+ ListStyleImage = String::hash( "list-style-image" ),
DataLanguage = String::hash( "data-language" ), // Minor hack
};
diff --git a/include/eepp/ui/csslayouttypes.hpp b/include/eepp/ui/csslayouttypes.hpp
index 743865f60..e7860a0a9 100644
--- a/include/eepp/ui/csslayouttypes.hpp
+++ b/include/eepp/ui/csslayouttypes.hpp
@@ -34,6 +34,32 @@ struct CSSPositionHelper {
static CSSPosition fromString( std::string_view val );
};
+enum class CSSListStyleType {
+ None,
+ Disc,
+ Circle,
+ Square,
+ Decimal,
+ LowerAlpha,
+ UpperAlpha,
+ LowerRoman,
+ UpperRoman
+};
+
+struct CSSListStyleTypeHelper {
+ static std::string toString( CSSListStyleType type );
+
+ static CSSListStyleType fromString( std::string_view val );
+};
+
+enum class CSSListStylePosition { Outside, Inside };
+
+struct CSSListStylePositionHelper {
+ static std::string toString( CSSListStylePosition pos );
+
+ static CSSListStylePosition fromString( std::string_view val );
+};
+
}} // namespace EE::UI
#endif
diff --git a/include/eepp/ui/uihelper.hpp b/include/eepp/ui/uihelper.hpp
index 23f3bfdf0..9c2ff2ae3 100644
--- a/include/eepp/ui/uihelper.hpp
+++ b/include/eepp/ui/uihelper.hpp
@@ -128,6 +128,7 @@ enum UINodeType {
UI_TYPE_BR,
UI_TYPE_HTML_HTML,
UI_TYPE_HTML_BODY,
+ UI_TYPE_HTML_LIST_ITEM,
UI_TYPE_MODULES = 10000,
UI_TYPE_TERMINAL = 10001,
UI_TYPE_USER = 200000,
diff --git a/include/eepp/ui/uihtmllistitem.hpp b/include/eepp/ui/uihtmllistitem.hpp
new file mode 100644
index 000000000..c25a0c22c
--- /dev/null
+++ b/include/eepp/ui/uihtmllistitem.hpp
@@ -0,0 +1,51 @@
+#ifndef EE_UI_UIHTMLLISTITEM_HPP
+#define EE_UI_UIHTMLLISTITEM_HPP
+
+#include
+#include
+#include
+
+namespace EE { namespace UI {
+
+class EE_API UIHTMLListItem : public UIRichText {
+ public:
+ static UIHTMLListItem* New();
+
+ virtual Uint32 getType() const;
+
+ virtual bool isType( const Uint32& type ) const;
+
+ virtual void draw();
+
+ virtual bool applyProperty( const StyleSheetProperty& attribute );
+
+ virtual std::string getPropertyString( const PropertyDefinition* propertyDef,
+ const Uint32& propertyIndex = 0 ) const;
+
+ virtual std::vector getPropertiesImplemented() const;
+
+ CSSListStyleType getListStyleType() const { return mListStyleType; }
+
+ void setListStyleType( CSSListStyleType type );
+
+ CSSListStylePosition getListStylePosition() const { return mListStylePosition; }
+
+ void setListStylePosition( CSSListStylePosition pos );
+
+ protected:
+ UIHTMLListItem();
+
+ CSSListStyleType mListStyleType{ CSSListStyleType::None };
+ CSSListStylePosition mListStylePosition{ CSSListStylePosition::Outside };
+ std::unique_ptr mListMarkerText;
+
+ int countPrecedingLiSiblings() const;
+
+ String::View getListMarkerString() const;
+
+ void invalidateList();
+};
+
+}} // namespace EE::UI
+
+#endif
diff --git a/include/eepp/ui/uirichtext.hpp b/include/eepp/ui/uirichtext.hpp
index ad265075e..f87b92f1a 100644
--- a/include/eepp/ui/uirichtext.hpp
+++ b/include/eepp/ui/uirichtext.hpp
@@ -44,8 +44,6 @@ class EE_API UIRichText : public UIHTMLWidget {
static UIRichText* NewPre() { return UIRichText::NewWithTag( "pre" ); };
- static UIRichText* NewListItem() { return UIRichText::NewWithTag( "li" ); };
-
static UIRichText* NewBlockquote() { return UIRichText::NewWithTag( "blockquote" ); };
virtual Uint32 getType() const;
diff --git a/src/eepp/graphics/csslayouttypes.cpp b/src/eepp/graphics/csslayouttypes.cpp
index a50e58a7b..995ca39d6 100644
--- a/src/eepp/graphics/csslayouttypes.cpp
+++ b/src/eepp/graphics/csslayouttypes.cpp
@@ -85,4 +85,58 @@ CSSPosition CSSPositionHelper::fromString( std::string_view val ) {
return position;
}
+std::string CSSListStyleTypeHelper::toString( CSSListStyleType type ) {
+ switch ( type ) {
+ case CSSListStyleType::Disc:
+ return "disc";
+ case CSSListStyleType::Circle:
+ return "circle";
+ case CSSListStyleType::Square:
+ return "square";
+ case CSSListStyleType::Decimal:
+ return "decimal";
+ case CSSListStyleType::LowerAlpha:
+ return "lower-alpha";
+ case CSSListStyleType::UpperAlpha:
+ return "upper-alpha";
+ case CSSListStyleType::LowerRoman:
+ return "lower-roman";
+ case CSSListStyleType::UpperRoman:
+ return "upper-roman";
+ case CSSListStyleType::None:
+ default:
+ return "none";
+ }
+}
+
+CSSListStyleType CSSListStyleTypeHelper::fromString( std::string_view val ) {
+ if ( val == "disc" )
+ return CSSListStyleType::Disc;
+ if ( val == "circle" )
+ return CSSListStyleType::Circle;
+ if ( val == "square" )
+ return CSSListStyleType::Square;
+ if ( val == "decimal" )
+ return CSSListStyleType::Decimal;
+ if ( val == "lower-alpha" )
+ return CSSListStyleType::LowerAlpha;
+ if ( val == "upper-alpha" )
+ return CSSListStyleType::UpperAlpha;
+ if ( val == "lower-roman" )
+ return CSSListStyleType::LowerRoman;
+ if ( val == "upper-roman" )
+ return CSSListStyleType::UpperRoman;
+ return CSSListStyleType::None;
+}
+
+std::string CSSListStylePositionHelper::toString( CSSListStylePosition pos ) {
+ return pos == CSSListStylePosition::Inside ? "inside" : "outside";
+}
+
+CSSListStylePosition CSSListStylePositionHelper::fromString( std::string_view val ) {
+ if ( val == "inside" )
+ return CSSListStylePosition::Inside;
+ return CSSListStylePosition::Outside;
+}
+
}} // namespace EE::UI
diff --git a/src/eepp/ui/css/stylesheetspecification.cpp b/src/eepp/ui/css/stylesheetspecification.cpp
index e0b6f043c..5aec8e9ba 100644
--- a/src/eepp/ui/css/stylesheetspecification.cpp
+++ b/src/eepp/ui/css/stylesheetspecification.cpp
@@ -428,6 +428,9 @@ void StyleSheetSpecification::registerDefaultProperties() {
registerProperty( "hidden", "" ).setType( PropertyType::Bool );
registerProperty( "display", "inline" ).setType( PropertyType::String );
registerProperty( "position", "static" ).setType( PropertyType::String );
+ registerProperty( "list-style-type", "none", true ).setType( PropertyType::String );
+ registerProperty( "list-style-position", "outside", true ).setType( PropertyType::String );
+ registerProperty( "list-style-image", "none" ).setType( PropertyType::String );
registerProperty( "top", "auto" ).setType( PropertyType::NumberLength );
registerProperty( "right", "auto" ).setType( PropertyType::NumberLength );
registerProperty( "bottom", "auto" ).setType( PropertyType::NumberLength );
@@ -516,6 +519,9 @@ void StyleSheetSpecification::registerDefaultProperties() {
registerShorthand( "border-bottom",
{ "border-bottom-width", "border-bottom-style", "border-bottom-color" },
"border-side" );
+ registerShorthand( "list-style",
+ { "list-style-type", "list-style-position", "list-style-image" },
+ "list-style" );
}
void StyleSheetSpecification::registerNodeSelector( const std::string& name,
@@ -1135,6 +1141,40 @@ void StyleSheetSpecification::registerDefaultShorthandParsers() {
return properties;
};
+
+ mShorthandParsers["list-style"] = []( const ShorthandDefinition* shorthand,
+ std::string value ) -> std::vector {
+ value = String::trim( value );
+ if ( value.empty() )
+ return {};
+ std::vector properties;
+ const std::vector& propNames = shorthand->getProperties();
+ if ( propNames.empty() )
+ return {};
+ auto tokens = String::split( value, " ", "", "(" );
+ int typePos = getIndexEndingWith( propNames, "-type" );
+ int posPos = getIndexEndingWith( propNames, "-position" );
+ int imagePos = getIndexEndingWith( propNames, "-image" );
+ for ( auto& tok : tokens ) {
+ String::trimInPlace( tok );
+ if ( tok == "inside" || tok == "outside" ) {
+ if ( posPos != -1 )
+ properties.emplace_back( StyleSheetProperty( propNames[posPos], tok ) );
+ } else if ( String::startsWith( tok, "url(" ) ) {
+ if ( imagePos != -1 )
+ properties.emplace_back( StyleSheetProperty( propNames[imagePos], tok ) );
+ } else if ( tok == "none" ) {
+ if ( typePos != -1 )
+ properties.emplace_back( StyleSheetProperty( propNames[typePos], tok ) );
+ if ( imagePos != -1 )
+ properties.emplace_back( StyleSheetProperty( propNames[imagePos], tok ) );
+ } else {
+ if ( typePos != -1 )
+ properties.emplace_back( StyleSheetProperty( propNames[typePos], tok ) );
+ }
+ }
+ return properties;
+ };
}
}}} // namespace EE::UI::CSS
diff --git a/src/eepp/ui/uihtmllistitem.cpp b/src/eepp/ui/uihtmllistitem.cpp
new file mode 100644
index 000000000..914981bdf
--- /dev/null
+++ b/src/eepp/ui/uihtmllistitem.cpp
@@ -0,0 +1,198 @@
+#include
+#include
+#include
+#include
+
+namespace EE { namespace UI {
+
+UIHTMLListItem* UIHTMLListItem::New() {
+ return eeNew( UIHTMLListItem, () );
+}
+
+UIHTMLListItem::UIHTMLListItem() : UIRichText( "li" ) {}
+
+void UIHTMLListItem::setListStyleType( CSSListStyleType type ) {
+ if ( mListStyleType != type ) {
+ mListStyleType = type;
+ invalidateList();
+ }
+}
+
+void UIHTMLListItem::setListStylePosition( CSSListStylePosition pos ) {
+ if ( mListStylePosition != pos ) {
+ mListStylePosition = pos;
+ invalidateList();
+ }
+}
+
+Uint32 UIHTMLListItem::getType() const {
+ return UI_TYPE_HTML_LIST_ITEM;
+}
+
+bool UIHTMLListItem::isType( const Uint32& type ) const {
+ return UIHTMLListItem::getType() == type ? true : UIRichText::isType( type );
+}
+
+void UIHTMLListItem::draw() {
+ UIRichText::draw();
+ if ( mVisible && 0.f != mAlpha ) {
+ const FontStyleConfig& style = mRichText.getFontStyleConfig();
+ Float fontSize = style.CharacterSize;
+ Float offset = 0.25f * fontSize;
+ Float lineHeight =
+ style.Font ? style.Font->getLineSpacing( (unsigned int)fontSize ) : fontSize;
+ Float lineTop = mScreenPos.y + mPaddingPx.Top;
+
+ if ( mListStyleType == CSSListStyleType::Disc ) {
+ Float radius = fontSize * 0.22f;
+ Float markerX = std::floor( mScreenPos.x + mPaddingPx.Left - radius * 2.f - offset );
+ Float markerY = std::floor( lineTop + ( lineHeight - radius * 2.f ) * 0.5f + radius );
+ Primitives p;
+ p.setColor( style.FontColor );
+ p.setFillMode( PrimitiveFillMode::DRAW_FILL );
+ p.drawCircle( { markerX, markerY }, radius );
+ } else if ( mListStyleType == CSSListStyleType::Circle ) {
+ Float radius = fontSize * 0.2f;
+ Float lineWidth = fontSize * 0.04f;
+ Float markerX = std::floor( mScreenPos.x + mPaddingPx.Left - radius * 2.f - offset );
+ Float markerY = std::floor( lineTop + ( lineHeight - radius * 2.f ) * 0.5f + radius );
+ Primitives p;
+ p.setColor( style.FontColor );
+ p.setFillMode( PrimitiveFillMode::DRAW_LINE );
+ p.setLineWidth( lineWidth );
+ p.drawCircle( { markerX, markerY }, radius );
+ } else if ( mListStyleType == CSSListStyleType::Square ) {
+ Float size = fontSize * 0.38f;
+ Float markerX = std::floor( mScreenPos.x + mPaddingPx.Left - size - fontSize * 0.5 );
+ Float markerY = std::floor( lineTop + ( lineHeight - size ) * 0.5f );
+ Primitives p;
+ p.setColor( style.FontColor );
+ p.setFillMode( PrimitiveFillMode::DRAW_FILL );
+ p.drawRectangle( Rectf( markerX, markerY, markerX + size, markerY + size ) );
+ } else if ( mListMarkerText && !mListMarkerText->getString().empty() ) {
+ Float markerX =
+ mScreenPos.x + mPaddingPx.Left - mListMarkerText->getTextWidth() - offset;
+ mListMarkerText->draw( markerX, lineTop, Vector2f::One, 0.f, getBlendMode() );
+ }
+ }
+}
+
+bool UIHTMLListItem::applyProperty( const StyleSheetProperty& attribute ) {
+ if ( !checkPropertyDefinition( attribute ) )
+ return false;
+
+ switch ( attribute.getPropertyDefinition()->getPropertyId() ) {
+ case PropertyId::ListStyleType:
+ setListStyleType( CSSListStyleTypeHelper::fromString( attribute.value() ) );
+ return true;
+ case PropertyId::ListStylePosition:
+ setListStylePosition( CSSListStylePositionHelper::fromString( attribute.value() ) );
+ return true;
+ default:
+ return UIRichText::applyProperty( attribute );
+ }
+}
+
+std::string UIHTMLListItem::getPropertyString( const PropertyDefinition* propertyDef,
+ const Uint32& propertyIndex ) const {
+ if ( NULL == propertyDef )
+ return "";
+
+ switch ( propertyDef->getPropertyId() ) {
+ case PropertyId::ListStyleType:
+ return CSSListStyleTypeHelper::toString( mListStyleType );
+ case PropertyId::ListStylePosition:
+ return CSSListStylePositionHelper::toString( mListStylePosition );
+ default:
+ return UIRichText::getPropertyString( propertyDef, propertyIndex );
+ }
+}
+
+std::vector UIHTMLListItem::getPropertiesImplemented() const {
+ auto props = UIRichText::getPropertiesImplemented();
+ props.push_back( PropertyId::ListStyleType );
+ props.push_back( PropertyId::ListStylePosition );
+ return props;
+}
+
+void UIHTMLListItem::invalidateList() {
+ if ( mListStyleType == CSSListStyleType::None || mListStyleType == CSSListStyleType::Disc ||
+ mListStyleType == CSSListStyleType::Circle ||
+ mListStyleType == CSSListStyleType::Square ) {
+ mListMarkerText.reset();
+ } else {
+ String::View markerStr = getListMarkerString();
+ if ( !markerStr.empty() ) {
+ if ( !mListMarkerText )
+ mListMarkerText = std::make_unique();
+ mListMarkerText->setString( markerStr );
+ mListMarkerText->setStyleConfig( mRichText.getFontStyleConfig() );
+ } else {
+ mListMarkerText.reset();
+ }
+ }
+ invalidateDraw();
+}
+
+int UIHTMLListItem::countPrecedingLiSiblings() const {
+ int count = 0;
+ Node* prev = getPrevNode();
+ while ( prev ) {
+ if ( prev->isWidget() && prev->asType()->getElementTag() == "li" )
+ count++;
+ prev = prev->getPrevNode();
+ }
+ return count;
+}
+
+String::View UIHTMLListItem::getListMarkerString() const {
+ static String sBuf;
+
+ switch ( mListStyleType ) {
+ case CSSListStyleType::None:
+ case CSSListStyleType::Disc:
+ case CSSListStyleType::Circle:
+ case CSSListStyleType::Square:
+ return {};
+ case CSSListStyleType::Decimal: {
+ int idx = countPrecedingLiSiblings() + 1;
+ sBuf = String( String::toString( idx ) + ". " );
+ return sBuf.view();
+ }
+ case CSSListStyleType::LowerAlpha: {
+ int idx = countPrecedingLiSiblings();
+ char c = 'a' + ( idx % 26 );
+ sBuf = String( 1, (String::StringBaseType)c ) + ". ";
+ return sBuf.view();
+ }
+ case CSSListStyleType::UpperAlpha: {
+ int idx = countPrecedingLiSiblings();
+ char c = 'A' + ( idx % 26 );
+ sBuf = String( 1, (String::StringBaseType)c ) + ". ";
+ return sBuf.view();
+ }
+ case CSSListStyleType::LowerRoman: {
+ static const char* numerals[] = { "i", "ii", "iii", "iv", "v", "vi",
+ "vii", "viii", "ix", "x", "xi", "xii" };
+ int idx = countPrecedingLiSiblings();
+ if ( idx < 12 )
+ sBuf = String( numerals[idx] ) + ". ";
+ else
+ sBuf = String( String::toString( idx + 1 ) + ". " );
+ return sBuf.view();
+ }
+ case CSSListStyleType::UpperRoman: {
+ static const char* numerals[] = { "I", "II", "III", "IV", "V", "VI",
+ "VII", "VIII", "IX", "X", "XI", "XII" };
+ int idx = countPrecedingLiSiblings();
+ if ( idx < 12 )
+ sBuf = String( numerals[idx] ) + ". ";
+ else
+ sBuf = String( String::toString( idx + 1 ) + ". " );
+ return sBuf.view();
+ }
+ }
+ return {};
+}
+
+}} // namespace EE::UI
diff --git a/src/eepp/ui/uiwidgetcreator.cpp b/src/eepp/ui/uiwidgetcreator.cpp
index 202c6ba6a..b0afb6221 100644
--- a/src/eepp/ui/uiwidgetcreator.cpp
+++ b/src/eepp/ui/uiwidgetcreator.cpp
@@ -10,6 +10,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -158,7 +159,7 @@ void UIWidgetCreator::createBaseWidgetList() {
registeredWidget["hr"] = UIRichText::NewHr;
registeredWidget["ul"] = [] { return UILinearLayout::NewVerticalWidthMatchParent( "ul" ); };
registeredWidget["ol"] = [] { return UILinearLayout::NewVerticalWidthMatchParent( "ol" ); };
- registeredWidget["li"] = UIRichText::NewListItem;
+ registeredWidget["li"] = UIHTMLListItem::New;
registeredWidget["pre"] = UIRichText::NewPre;
registeredWidget["img"] = [] {
auto img = UIImage::NewWithTag( "img" );
diff --git a/src/tests/unit_tests/uihtml_tests.cpp b/src/tests/unit_tests/uihtml_tests.cpp
index 5b5443393..997d0629b 100644
--- a/src/tests/unit_tests/uihtml_tests.cpp
+++ b/src/tests/unit_tests/uihtml_tests.cpp
@@ -8,6 +8,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -570,3 +571,157 @@ UTEST( UILayout, marginAuto ) {
Engine::destroySingleton();
}
+
+UTEST( UILayout, listStyleTypeDecimal ) {
+ init_ui_test();
+ auto* sceneNode = SceneManager::instance()->getUISceneNode();
+ sceneNode->loadLayoutFromString( R"html(
+
+
+ - First item
+ - Second item
+ - Third item
+
+
+ )html" );
+
+ sceneNode->updateDirtyLayouts();
+
+ const auto* propDef =
+ StyleSheetSpecification::instance()->getProperty( "list-style-type" );
+ ASSERT_TRUE( propDef != nullptr );
+
+ auto* li1 = sceneNode->getRoot()->find( "li1" )->asType();
+ auto* li2 = sceneNode->getRoot()->find( "li2" )->asType();
+ auto* li3 = sceneNode->getRoot()->find( "li3" )->asType();
+
+ ASSERT_TRUE( li1 != nullptr );
+ ASSERT_TRUE( li2 != nullptr );
+ ASSERT_TRUE( li3 != nullptr );
+
+ EXPECT_TRUE( li1->getPropertyString( propDef ) == "decimal" );
+ EXPECT_TRUE( li2->getPropertyString( propDef ) == "decimal" );
+ EXPECT_TRUE( li3->getPropertyString( propDef ) == "decimal" );
+
+ Engine::destroySingleton();
+}
+
+UTEST( UILayout, listStyleTypeDisc ) {
+ init_ui_test();
+ auto* sceneNode = SceneManager::instance()->getUISceneNode();
+ sceneNode->loadLayoutFromString( R"html(
+
+
+
+ )html" );
+
+ sceneNode->updateDirtyLayouts();
+
+ const auto* propDef =
+ StyleSheetSpecification::instance()->getProperty( "list-style-type" );
+ ASSERT_TRUE( propDef != nullptr );
+
+ auto* li1 = sceneNode->getRoot()->find( "li1" )->asType();
+ ASSERT_TRUE( li1 != nullptr );
+
+ EXPECT_TRUE( li1->getPropertyString( propDef ) == "disc" );
+
+ Engine::destroySingleton();
+}
+
+UTEST( UILayout, listStyleShorthand ) {
+ init_ui_test();
+ auto* sceneNode = SceneManager::instance()->getUISceneNode();
+ sceneNode->loadLayoutFromString( R"html(
+
+
+ - First
+ - Second
+ - Third
+
+
+ - Bullet
+ - Square
+ - Circle
+
+
+ )html" );
+
+ sceneNode->updateDirtyLayouts();
+
+ const auto* typeDef =
+ StyleSheetSpecification::instance()->getProperty( "list-style-type" );
+ const auto* posDef =
+ StyleSheetSpecification::instance()->getProperty( "list-style-position" );
+
+ for ( const char* id : { "li1", "li2", "li3", "li4", "li5", "li6" } ) {
+ auto* li = sceneNode->getRoot()->find( id )->asType();
+ ASSERT_TRUE( li != nullptr );
+ EXPECT_TRUE( li->isType( UI_TYPE_HTML_LIST_ITEM ) );
+ }
+
+ EXPECT_TRUE( sceneNode->getRoot()->find( "li1" )->asType()->getPropertyString( typeDef ) == "decimal" );
+ EXPECT_TRUE( sceneNode->getRoot()->find( "li1" )->asType()->getPropertyString( posDef ) == "outside" );
+
+ EXPECT_TRUE( sceneNode->getRoot()->find( "li2" )->asType()->getPropertyString( typeDef ) == "lower-alpha" );
+ EXPECT_TRUE( sceneNode->getRoot()->find( "li2" )->asType()->getPropertyString( posDef ) == "inside" );
+
+ EXPECT_TRUE( sceneNode->getRoot()->find( "li3" )->asType()->getPropertyString( typeDef ) == "none" );
+
+ EXPECT_TRUE( sceneNode->getRoot()->find( "li4" )->asType()->getPropertyString( typeDef ) == "disc" );
+ EXPECT_TRUE( sceneNode->getRoot()->find( "li5" )->asType()->getPropertyString( typeDef ) == "square" );
+ EXPECT_TRUE( sceneNode->getRoot()->find( "li5" )->asType()->getPropertyString( posDef ) == "outside" );
+ EXPECT_TRUE( sceneNode->getRoot()->find( "li6" )->asType()->getPropertyString( typeDef ) == "circle" );
+
+ Engine::destroySingleton();
+}
+
+UTEST( UILayout, listStyleInheritanceFromUl ) {
+ init_ui_test();
+ auto* sceneNode = SceneManager::instance()->getUISceneNode();
+ sceneNode->loadLayoutFromString( R"html(
+
+
+
+
+
+
+ - Coffee
+
+
+
+
+
+ - Coffee
+
+
+
+ )html" );
+
+ sceneNode->updateDirtyLayouts();
+
+ const auto* typeDef =
+ StyleSheetSpecification::instance()->getProperty( "list-style-type" );
+
+ EXPECT_TRUE( sceneNode->getRoot()->find( "h1" )->asType()->getPropertyString( typeDef ) == "upper-roman" );
+ EXPECT_TRUE( sceneNode->getRoot()->find( "a1" )->asType()->getPropertyString( typeDef ) == "circle" );
+ EXPECT_TRUE( sceneNode->getRoot()->find( "b1" )->asType()->getPropertyString( typeDef ) == "disc" );
+ EXPECT_TRUE( sceneNode->getRoot()->find( "c1" )->asType()->getPropertyString( typeDef ) == "square" );
+ EXPECT_TRUE( sceneNode->getRoot()->find( "d1" )->asType()->getPropertyString( typeDef ) == "decimal" );
+
+ Engine::destroySingleton();
+}