|
libhtmlpp 1.0.0
|
#include <css.h>
Public Member Functions | |
| CSSStyleSheet () | |
| CSSStyleSheet (const CSSStyleSheet &sheet) | |
| ~CSSStyleSheet () | |
| CSSStyleSheet & | operator= (const CSSStyleSheet &sheet) |
| void | parse (const std::string &input) |
| void | addRule (const CSSRule &rule) |
| void | removeRule (size_t index) |
| const CSSRule * | getRule (size_t index) const |
| size_t | getRuleCount () const |
| const std::vector< CSSRule > & | getRules () const |
| std::string | serialize (bool formatted=false) const |
| void | clear () |
| void | collectApproximateMatches (const std::string &tag, const std::string &cssClass, const std::string &id, std::map< std::string, std::string > &props, std::string &mediaRules, std::set< std::string > &seenMediaBlocks, const std::vector< AncestorFrame > *ancestors=nullptr, const std::map< std::string, std::string > *targetAttributes=nullptr) const |
Runs every rule in this sheet through approximateSelectorMatch against the element identified by tag/(a whitespace-separated class list)/id, folding matching declarations into props under an approximation of the real CSS cascade: a property already present in props when this is called (e.g. | |
Static Public Member Functions | |
| static CSSDeclaration | parseInlineStyle (const std::string &style) |
| static bool | approximateSelectorMatch (const std::string &selector, const std::string &tag, const std::vector< std::string > &classes, const std::string &id, const std::vector< AncestorFrame > *ancestors=nullptr) |
Conservative, NOT spec-complete selector match: selector (a single selector, or a comma-separated list of them – matches if ANY branch matches) is matched against a single element identified by tag/ with ancestors (see AncestorFrame) checked against any compound(s) left of the trailing/target one. | |
| libhtmlpp::CSSStyleSheet::CSSStyleSheet | ( | const CSSStyleSheet & | sheet | ) |
| void libhtmlpp::CSSStyleSheet::addRule | ( | const CSSRule & | rule | ) |
|
static |
Conservative, NOT spec-complete selector match: selector (a single selector, or a comma-separated list of them – matches if ANY branch matches) is matched against a single element identified by tag/ with classes/ optionallyid,ancestors (see AncestorFrame) checked against any compound(s) left of the trailing/target one.
Passing ancestors as nullptr (the default) means "verify the target compound only, same as if
no ancestor/parent context were available" – every leading compound of a combinator selector is then ignored, not verified, matching this function's original behavior exactly (existing callers that can't supply ancestor context are unaffected). When ancestors is non-null, each leading compound must be found somewhere in it, in left-to-right order (see AncestorFrame) – same all-classes-listed/tag/id rule as the target compound (plus its own attribute conditions, see AncestorFrame::attributes). Rejected outright for the target compound: pseudo-classes and pseudo-elements (":hover", "::before") and the universal selector ("*") – guessing their state is worse than not matching at all. A bare tag left with no class/id/attribute qualifier of its own after a combinator (space/">"/"+"/"~") is stripped off (e.g. "[data-x]>div" reduces to a bare "div") is ALWAYS rejected for the target compound, even when ancestors is supplied and its own ancestor requirement is genuinely verified: on a real component-library/page-builder site a generic ancestor condition (e.g. "[data-atom][data-atom=header]") can be common enough to make a bare-tag child of it a near-blanket match in practice, and combined with this file's specificity ordering (see computeSpecificity) that let one real page-builder's own layout plumbing rule silently outrank much more specific, content-driven rules – confirmed by an actual regression this guard's removal caused, not just theoretical risk. A qualified compound like "div.foo" is always specific enough to check on its own and never triggers this rejection. An attribute-selector condition ("[href=...]") on the target compound is checked against collectApproximateMatches's targetAttributes when supplied – otherwise (or for an ancestor compound with no attributes supplied on its AncestorFrame) it's ignored rather than guessed, same "not proven to not match" bias as everywhere else here. A compound selector like "div.card.featured#hero" matches only if the tag (when given), every class listed (all of them, not just one), and the id (when given) are all present on the element being checked against it. This is intentionally an approximation of real CSS selector matching, not an implementation of it – ancestor verification (when requested) doesn't distinguish child/descendant/sibling combinators or require adjacency – built to be safe against false positives on real-world scraped markup rather than complete; treat a false result as "not proven to
match", not "definitely doesn't". Approximate CSS specificity (see computeSpecificity, used by collectApproximateMatches) is computed separately from this function's own true/false verdict.
| void libhtmlpp::CSSStyleSheet::collectApproximateMatches | ( | const std::string & | tag, |
| const std::string & | cssClass, | ||
| const std::string & | id, | ||
| std::map< std::string, std::string > & | props, | ||
| std::string & | mediaRules, | ||
| std::set< std::string > & | seenMediaBlocks, | ||
| const std::vector< AncestorFrame > * | ancestors = nullptr, |
||
| const std::map< std::string, std::string > * | targetAttributes = nullptr |
||
| ) | const |
Runs every rule in this sheet through approximateSelectorMatch against the element identified by tag/(a whitespace-separated class list)/cssClass id, folding matching declarations into props under an approximation of the real CSS cascade: a property already present in props when this is called (e.g.
the element's own inline style, set by the caller before calling this) outranks a later plain rule unless that rule's value carries "!important" (stripped from the stored value either way); within each of those two precedence tiers, a rule with higher approximate specificity (id/class-attribute- pseudo-class/type-pseudo-element counts, compared the same way a real cascade does) wins regardless of source order, and only falls back to "later rule wins" when two matching rules are exactly as specific as each other – see computeSpecificity in css.cpp. Each matching @media/other at-rule block's raw text is appended to mediaRules, skipped if its exact text is already present in seenMediaBlocks (both are caller-owned, so a caller processing many elements from one document/sheet can share one instance of each across all of them and avoid repeating an identical block once per matching element). ancestors is forwarded to approximateSelectorMatch's underlying per-compound check exactly as described there – nullptr (the default) preserves this function's original behavior (leading compounds of a combinator selector are never verified), a non-null chain makes leading compounds required to be found in it, in order. Exception: if a match only went through because one of its ancestor compounds was unverifiable (an attribute selector or unsupported pseudo-class stripped down to nothing – see approximateSelectorMatch's own doc comment), that rule's display:none/visibility:hidden values are dropped rather than folded into props, since an ordinary wrong guess mis-styles an element but a wrong guess on those two properties makes it (and its subtree) disappear outright; every other property from the same rule is unaffected and still applies normally. targetAttributes, when non-null, is the target element's own attribute map (name -> value) – unlike ancestors, the target element's attributes ARE available to this function's caller (see getCSSRules), so an attribute-selector condition on the TARGET compound itself (e.g. ".fade-box[data-fit=fill]", as opposed to one on an ancestor compound, which still can't be verified) is checked against it instead of being ignored – nullptr (the default) preserves the old ignore-it behavior for any existing caller that doesn't have an attribute map handy.
| const libhtmlpp::CSSRule * libhtmlpp::CSSStyleSheet::getRule | ( | size_t | index | ) | const |
| const std::vector< libhtmlpp::CSSRule > & libhtmlpp::CSSStyleSheet::getRules | ( | ) | const |
| libhtmlpp::CSSStyleSheet & libhtmlpp::CSSStyleSheet::operator= | ( | const CSSStyleSheet & | sheet | ) |
| void libhtmlpp::CSSStyleSheet::parse | ( | const std::string & | input | ) |
|
static |
| std::string libhtmlpp::CSSStyleSheet::serialize | ( | bool | formatted = false | ) | const |