diff --git a/lib/Epub/Epub/css/CssParser.cpp b/lib/Epub/Epub/css/CssParser.cpp index 8bdd0f1a..9415f155 100644 --- a/lib/Epub/Epub/css/CssParser.cpp +++ b/lib/Epub/Epub/css/CssParser.cpp @@ -74,7 +74,7 @@ std::string CssParser::normalized(const std::string& s) { } // Remove trailing space - if (!result.empty() && result.back() == ' ') { + while (!result.empty() && (result.back() == ' ' || result.back() == '\n')) { result.pop_back(); } return result; @@ -365,6 +365,56 @@ void CssParser::processRuleBlockWithStyle(const std::string& selectorGroup, cons std::string key = normalized(sel); if (key.empty()) continue; + // TODO: Consider adding support for sibling css selectors in the future + // Ensure no + in selector as we don't support adjacent CSS selectors for now + if (key.find('+') != std::string_view::npos) { + continue; + } + + // TODO: Consider adding support for direct nested css selectors in the future + // Ensure no > in selector as we don't support nested CSS selectors for now + if (key.find('>') != std::string_view::npos) { + continue; + } + + // TODO: Consider adding support for attribute css selectors in the future + // Ensure no [ in selector as we don't support attribute CSS selectors for now + if (key.find('[') != std::string_view::npos) { + continue; + } + + // TODO: Consider adding support for pseudo selectors in the future + // Ensure no : in selector as we don't support pseudo CSS selectors for now + if (key.find(':') != std::string_view::npos) { + continue; + } + + // TODO: Consider adding support for ID css selectors in the future + // Ensure no # in selector as we don't support ID CSS selectors for now + if (key.find('#') != std::string_view::npos) { + continue; + } + + // TODO: Consider adding support for general sibling combinator selectors in the future + // Ensure no ~ in selector as we don't support general sibling combinator CSS selectors for now + if (key.find('~') != std::string_view::npos) { + continue; + } + + // TODO: Consider adding support for wildcard css selectors in the future + // Ensure no * in selector as we don't support wildcard CSS selectors for now + if (key.find('*') != std::string_view::npos) { + continue; + } + + // TODO: Add support for more complex selectors in the future + // At the moment, we only ever check for `tag`, `tag.class1` or `.class1` + // If the selector has whitespace in it, then it's either a CSS selector for a descendant element (e.g. `tag1 tag2`) + // or some other slightly more advanced CSS selector which we don't support yet + if (key.find(' ') != std::string_view::npos) { + continue; + } + // Skip if this would exceed the rule limit if (rulesBySelector_.size() >= MAX_RULES) { LOG_DBG("CSS", "Reached max rules limit, stopping selector processing"); @@ -550,6 +600,7 @@ CssStyle CssParser::resolveStyle(const std::string& tagName, const std::string& result.applyOver(tagIt->second); } + // TODO: Support combinations of classes (e.g. style on .class1.class2) // 2. Apply class styles (medium priority) if (!classAttr.empty()) { const auto classes = splitWhitespace(classAttr); @@ -563,6 +614,7 @@ CssStyle CssParser::resolveStyle(const std::string& tagName, const std::string& } } + // TODO: Support combinations of classes (e.g. style on p.class1.class2) // 3. Apply element.class styles (higher priority) for (const auto& cls : classes) { std::string combinedKey = tag + "." + normalized(cls);