Commit f351efa7 authored by Jan Köster's avatar Jan Köster
Browse files

test

parent 4822230f
Loading
Loading
Loading
Loading
+20 −6
Original line number Diff line number Diff line
@@ -199,10 +199,18 @@ namespace {
    // Substitutes every var(...) occurrence in `value`, recursively --
    // `resolving` (the set of custom-property names currently being
    // expanded on this call stack) provides cycle detection: a name already
    // in it resolves to "" instead of recursing forever.
    // in it resolves to "" instead of recursing forever. `sawUnresolved` is
    // set to true (never reset to false) whenever a var() reference turns
    // out invalid per spec (cyclic, or absent with no fallback) -- callers
    // use this to tell "resolved cleanly" apart from "silently substituted
    // an empty string", since the latter, left in a still-live declaration
    // like `calc( * 1px + ...)`, is worse than dropping the declaration:
    // it's syntactically-broken-but-not-obviously-invalid text rather than
    // a clean absence.
    std::string substituteVars(const std::string &value,
                                const std::map<std::string,std::string> &customProperties,
                                std::set<std::string> &resolving)
                                std::set<std::string> &resolving,
                                bool &sawUnresolved)
    {
        if (value.find("var(") == std::string::npos) return value;

@@ -226,16 +234,18 @@ namespace {
                std::string substitution;
                if (resolving.count(name)) {
                    substitution = ""; // cyclic reference -- invalid per spec
                    sawUnresolved = true;
                } else {
                    auto it = customProperties.find(name);
                    if (it != customProperties.end()) {
                        resolving.insert(name);
                        substitution = substituteVars(it->second, customProperties, resolving);
                        substitution = substituteVars(it->second, customProperties, resolving, sawUnresolved);
                        resolving.erase(name);
                    } else if (!fallback.empty()) {
                        substitution = substituteVars(fallback, customProperties, resolving);
                        substitution = substituteVars(fallback, customProperties, resolving, sawUnresolved);
                    } else {
                        substitution = ""; // unresolvable, no fallback -- invalid per spec
                        sawUnresolved = true;
                    }
                }
                out += substitution;
@@ -755,9 +765,13 @@ void libhtmlpp::CSSStyleSheet::collectApproximateMatches(
}

std::string libhtmlpp::resolveCSSVariables(const std::string &value,
                                             const std::map<std::string,std::string> &customProperties)
                                             const std::map<std::string,std::string> &customProperties,
                                             bool *unresolved)
{
    std::set<std::string> resolving;
    return substituteVars(value, customProperties, resolving);
    bool sawUnresolved = false;
    std::string result = substituteVars(value, customProperties, resolving, sawUnresolved);
    if (unresolved) *unresolved = sawUnresolved;
    return result;
}
+12 −2
Original line number Diff line number Diff line
@@ -198,9 +198,19 @@ namespace libhtmlpp {
     *  stored value of a custom property is inserted verbatim at the
     *  `var(...)` call's position, exactly as a browser's cascade would;
     *  no CSS value-type awareness (color/length/etc.) is needed or
     *  applied. */
     *  applied.
     *
     *  If @p unresolved is non-null, it's set to true when any var()
     *  reference turned out invalid (cyclic, or absent with no fallback) --
     *  i.e. when the "" substitution happened at least once. A caller that
     *  needs real CSS semantics (an invalid var() invalidates the whole
     *  declaration, not just that one reference) should drop the property
     *  entirely in that case instead of keeping this partially-substituted
     *  text, since e.g. `calc(var(--missing) * 1px)` resolving to
     *  `calc( * 1px)` is syntactically broken rather than cleanly absent. */
    std::string resolveCSSVariables(const std::string &value,
                                     const std::map<std::string,std::string> &customProperties);
                                     const std::map<std::string,std::string> &customProperties,
                                     bool *unresolved = nullptr);

}