mirror of
https://github.com/daveallie/crosspoint-reader.git
synced 2026-02-04 06:37:38 +03:00
- TextAlign enum → CssTextAlign (reordered to match settings: Justify=0, Left=1, Center=2, Right=3) - alignment → textAlign - indent → textIndent - decoration → textDecoration - Update CssPropertyFlags field names to match - Remove TextAlign::None; default to CssTextAlign::Left This aligns internal naming with actual CSS property names for clarity.
100 lines
3.2 KiB
C++
100 lines
3.2 KiB
C++
#pragma once
|
|
|
|
#include <SdFat.h>
|
|
|
|
#include <string>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
#include "CssStyle.h"
|
|
|
|
/**
|
|
* Lightweight CSS parser for EPUB stylesheets
|
|
*
|
|
* Parses CSS files and extracts styling information relevant for e-ink display.
|
|
* Uses a two-phase approach: first tokenizes the CSS content, then builds
|
|
* a rule database that can be queried during HTML parsing.
|
|
*
|
|
* Supported selectors:
|
|
* - Element selectors: p, div, h1, etc.
|
|
* - Class selectors: .classname
|
|
* - Combined: element.classname
|
|
* - Grouped: selector1, selector2 { }
|
|
*
|
|
* Not supported (silently ignored):
|
|
* - Descendant/child selectors
|
|
* - Pseudo-classes and pseudo-elements
|
|
* - Media queries (content is skipped)
|
|
* - @import, @font-face, etc.
|
|
*/
|
|
class CssParser {
|
|
public:
|
|
CssParser() = default;
|
|
~CssParser() = default;
|
|
|
|
// Non-copyable
|
|
CssParser(const CssParser&) = delete;
|
|
CssParser& operator=(const CssParser&) = delete;
|
|
|
|
/**
|
|
* Load and parse CSS from a file stream.
|
|
* Can be called multiple times to accumulate rules from multiple stylesheets.
|
|
* @param source Open file handle to read from
|
|
* @return true if parsing completed (even if no rules found)
|
|
*/
|
|
bool loadFromStream(FsFile& source);
|
|
|
|
/**
|
|
* Look up the style for an HTML element, considering tag name and class attributes.
|
|
* Applies CSS cascade: element style < class style < element.class style
|
|
*
|
|
* @param tagName The HTML element name (e.g., "p", "div")
|
|
* @param classAttr The class attribute value (may contain multiple space-separated classes)
|
|
* @return Combined style with all applicable rules merged
|
|
*/
|
|
[[nodiscard]] CssStyle resolveStyle(const std::string& tagName, const std::string& classAttr) const;
|
|
|
|
/**
|
|
* Parse an inline style attribute string.
|
|
* @param styleValue The value of a style="" attribute
|
|
* @return Parsed style properties
|
|
*/
|
|
[[nodiscard]] static CssStyle parseInlineStyle(const std::string& styleValue);
|
|
|
|
/**
|
|
* Check if any rules have been loaded
|
|
*/
|
|
[[nodiscard]] bool empty() const { return rulesBySelector_.empty(); }
|
|
|
|
/**
|
|
* Get count of loaded rule sets
|
|
*/
|
|
[[nodiscard]] size_t ruleCount() const { return rulesBySelector_.size(); }
|
|
|
|
/**
|
|
* Clear all loaded rules
|
|
*/
|
|
void clear() { rulesBySelector_.clear(); }
|
|
|
|
private:
|
|
// Storage: maps normalized selector -> style properties
|
|
std::unordered_map<std::string, CssStyle> rulesBySelector_;
|
|
|
|
// Internal parsing helpers
|
|
void processRuleBlock(const std::string& selectorGroup, const std::string& declarations);
|
|
static CssStyle parseDeclarations(const std::string& declBlock);
|
|
|
|
// Individual property value parsers
|
|
static CssTextAlign interpretAlignment(const std::string& val);
|
|
static CssFontStyle interpretFontStyle(const std::string& val);
|
|
static CssFontWeight interpretFontWeight(const std::string& val);
|
|
static CssTextDecoration interpretDecoration(const std::string& val);
|
|
static CssLength interpretLength(const std::string& val);
|
|
static int8_t interpretSpacing(const std::string& val);
|
|
|
|
// String utilities
|
|
static std::string normalized(const std::string& s);
|
|
static std::vector<std::string> splitOnChar(const std::string& s, char delimiter);
|
|
static std::vector<std::string> splitWhitespace(const std::string& s);
|
|
};
|