diff --git a/include/eepp/ui/css/stylesheetpropertiesparser.hpp b/include/eepp/ui/css/stylesheetpropertiesparser.hpp index 09801ead3..12da706f6 100644 --- a/include/eepp/ui/css/stylesheetpropertiesparser.hpp +++ b/include/eepp/ui/css/stylesheetpropertiesparser.hpp @@ -22,9 +22,7 @@ class EE_API StyleSheetPropertiesParser { const StyleSheetVariables& getVariables() const; protected: - enum ReadState { ReadingPropertyName, ReadingPropertyValue, ReadingComment }; - - ReadState mPrevRs{ ReadingPropertyName }; + enum ReadState { ReadingPropertyName, ReadingPropertyValue }; StyleSheetProperties mProperties; StyleSheetVariables mVariables; @@ -35,8 +33,6 @@ class EE_API StyleSheetPropertiesParser { int readPropertyValue( ReadState& rs, std::size_t pos, std::string& buffer, std::string_view str ); - int readComment( ReadState& rs, std::size_t pos, std::string& buffer, std::string_view str ); - void addProperty( std::string name, std::string value ); }; diff --git a/src/eepp/ui/css/stylesheetpropertiesparser.cpp b/src/eepp/ui/css/stylesheetpropertiesparser.cpp index 83c72fe52..c0fa7c5b9 100644 --- a/src/eepp/ui/css/stylesheetpropertiesparser.cpp +++ b/src/eepp/ui/css/stylesheetpropertiesparser.cpp @@ -6,6 +6,21 @@ using namespace EE::UI; namespace EE { namespace UI { namespace CSS { +static std::size_t skipComment( std::string_view str, std::size_t pos ) { + pos += 2; + while ( pos + 1 < str.size() ) { + if ( str[pos] == '*' && str[pos + 1] == '/' ) + return pos + 2; + pos++; + } + return str.size(); +} + +static void appendCommentWhitespace( std::string& buffer ) { + if ( !buffer.empty() && buffer.back() != ' ' ) + buffer += ' '; +} + StyleSheetPropertiesParser::StyleSheetPropertiesParser( std::string_view propsstr ) { parse( propsstr ); } @@ -22,7 +37,6 @@ void StyleSheetPropertiesParser::parse( std::string_view propsstr ) { mProperties.clear(); mVariables.clear(); ReadState rs = ReadingPropertyName; - mPrevRs = rs; std::size_t pos = 0; std::string buffer; @@ -36,9 +50,6 @@ void StyleSheetPropertiesParser::parse( std::string_view propsstr ) { pos = readPropertyValue( rs, pos, buffer, propsstr ); break; } - case ReadingComment: { - pos = readComment( rs, pos, buffer, propsstr ); - } default: break; } @@ -48,13 +59,13 @@ void StyleSheetPropertiesParser::parse( std::string_view propsstr ) { int StyleSheetPropertiesParser::readPropertyName( StyleSheetPropertiesParser::ReadState& rs, std::size_t pos, std::string& buffer, std::string_view str ) { - mPrevRs = rs; buffer.clear(); while ( pos < str.size() ) { if ( str[pos] == '/' && str.size() > pos + 1 && str[pos + 1] == '*' ) { - rs = ReadingComment; - return pos; + appendCommentWhitespace( buffer ); + pos = skipComment( str, pos ); + continue; } if ( str[pos] == ':' ) { @@ -78,8 +89,6 @@ int StyleSheetPropertiesParser::readPropertyValue( StyleSheetPropertiesParser::R buffer.clear(); - mPrevRs = rs; - bool inDoubleQuote = false; bool inSingleQuote = false; int nestedParenthesis = 0; @@ -89,8 +98,9 @@ int StyleSheetPropertiesParser::readPropertyValue( StyleSheetPropertiesParser::R // Ensure we aren't parsing comments inside strings if ( str[pos] == '/' && str.size() > pos + 1 && str[pos + 1] == '*' && !inDoubleQuote && !inSingleQuote ) { - rs = ReadingComment; - return pos; + appendCommentWhitespace( buffer ); + pos = skipComment( str, pos ); + continue; } // Only terminate property parsing on ';' if we are outside of quotes and parentheses @@ -118,36 +128,11 @@ int StyleSheetPropertiesParser::readPropertyValue( StyleSheetPropertiesParser::R pos++; - if ( pos == str.size() ) { - rs = ReadingPropertyName; - - addProperty( propName, buffer ); - - return pos + 1; - } - prevChar = str[pos - 1]; } - return pos; -} - -int StyleSheetPropertiesParser::readComment( StyleSheetPropertiesParser::ReadState& rs, - std::size_t pos, std::string& buffer, - std::string_view str ) { - buffer.clear(); - - while ( pos < str.size() ) { - if ( str[pos] == '*' && str.size() > pos + 1 && str[pos + 1] == '/' ) { - rs = mPrevRs; - return pos + 2; - } - - buffer += str[pos]; - - pos++; - } - + rs = ReadingPropertyName; + addProperty( propName, buffer ); return pos; } diff --git a/src/tests/unit_tests/uicss_inheritance_tests.cpp b/src/tests/unit_tests/uicss_inheritance_tests.cpp index f6141424b..de5f5e815 100644 --- a/src/tests/unit_tests/uicss_inheritance_tests.cpp +++ b/src/tests/unit_tests/uicss_inheritance_tests.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -29,6 +30,37 @@ using namespace EE::UI::CSS; using namespace EE::Scene; using namespace EE::Graphics; +UTEST( CSSParser, CommentsPreserveDeclarationContext ) { + StyleSheetPropertiesParser parser( R"css( + color /* before colon */ : red; + margin: 1px /* between values */ 2px; + font-family: "A/* literal */B"; + /* between declarations */ width: 140px; + line-height: 40px !important /* final declaration without semicolon */ + )css" ); + const auto& properties = parser.getProperties(); + + auto lineHeight = properties.find( static_cast( PropertyId::LineHeight ) ); + auto color = properties.find( static_cast( PropertyId::Color ) ); + auto marginTop = properties.find( static_cast( PropertyId::MarginTop ) ); + auto marginRight = properties.find( static_cast( PropertyId::MarginRight ) ); + auto fontFamily = properties.find( static_cast( PropertyId::FontFamily ) ); + auto width = properties.find( static_cast( PropertyId::Width ) ); + + ASSERT_TRUE( lineHeight != properties.end() ); + ASSERT_TRUE( color != properties.end() ); + ASSERT_TRUE( marginTop != properties.end() ); + ASSERT_TRUE( marginRight != properties.end() ); + ASSERT_TRUE( fontFamily != properties.end() ); + ASSERT_TRUE( width != properties.end() ); + EXPECT_TRUE( lineHeight->second.getValue() == "40px" ); + EXPECT_TRUE( color->second.getValue() == "red" ); + EXPECT_TRUE( marginTop->second.getValue() == "1px" ); + EXPECT_TRUE( marginRight->second.getValue() == "2px" ); + EXPECT_TRUE( fontFamily->second.getValue().find( "/* literal */" ) != std::string::npos ); + EXPECT_TRUE( width->second.getValue() == "140px" ); +} + UTEST( CSSInheritance, HtmlXmlLoadingInheritance ) { UIApplication app( WindowSettings( 800, 600, "eepp - CSS Inheritance Test", WindowStyle::Default,