Fix in CSS properties parser when comments were between and inside properties.

This commit is contained in:
Martín Lucas Golini
2026-07-30 13:11:33 -03:00
parent d61c8a7582
commit 4d644880d8
3 changed files with 56 additions and 43 deletions

View File

@@ -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 );
};

View File

@@ -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;
}

View File

@@ -6,6 +6,7 @@
#include <eepp/system/filesystem.hpp>
#include <eepp/ui/css/stylesheet.hpp>
#include <eepp/ui/css/stylesheetlength.hpp>
#include <eepp/ui/css/stylesheetpropertiesparser.hpp>
#include <eepp/ui/css/stylesheetproperty.hpp>
#include <eepp/ui/css/stylesheetpropertyanimation.hpp>
#include <eepp/ui/css/stylesheetspecification.hpp>
@@ -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<Uint32>( PropertyId::LineHeight ) );
auto color = properties.find( static_cast<Uint32>( PropertyId::Color ) );
auto marginTop = properties.find( static_cast<Uint32>( PropertyId::MarginTop ) );
auto marginRight = properties.find( static_cast<Uint32>( PropertyId::MarginRight ) );
auto fontFamily = properties.find( static_cast<Uint32>( PropertyId::FontFamily ) );
auto width = properties.find( static_cast<Uint32>( 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,