Commit d11231ea authored by jan.koester's avatar jan.koester
Browse files

test anestor

parent 0a9e6460
Loading
Loading
Loading
Loading
+48 −9
Original line number Diff line number Diff line
@@ -290,6 +290,21 @@ std::string neutralizeFixedStickyPosition(const std::string &css)
    return std::regex_replace(css, re, "position: static");
}

// Splits a whitespace-separated `class` attribute value into its individual
// tokens, for building this element's own libhtmlpp::AncestorFrame entry
// (see htmlElementToWidgetXml's Frame::ancestorChain) -- getCSSRules/
// collectApproximateMatches do this same split internally for the *target*
// element already, but an ancestor frame is built here, once per element,
// to hand to its own children's matching later.
std::vector<std::string> splitClassList(const std::string &cssClass)
{
    std::vector<std::string> classes;
    std::istringstream iss(cssClass);
    std::string cls;
    while (iss >> cls) classes.push_back(cls);
    return classes;
}

// Best-effort extraction of just the color component from a `background`
// shorthand value (e.g. "background: url(x.png) no-repeat center red;") --
// every widget's known-CSS mapping only ever looks for the longhand
@@ -986,6 +1001,15 @@ void blogi::htmlimport::htmlElementToWidgetXml(
        tinyxml2::XMLElement *pXml;
        libhtmlpp::Element *stop = nullptr;
        std::map<std::string,std::string> customPropertyEnv = {};
        // Outermost-ancestor-first, immediate-parent-last (see
        // libhtmlpp::AncestorFrame's own doc comment) -- passed to
        // getCSSRules below so a descendant selector like ".header .frame"
        // only matches an element that's actually inside something with
        // class "header", instead of leaking onto every ".frame" in the
        // document regardless of where it lives (the bautenschutz-wetzlar.de
        // bug: a header-only padding rule was silently zeroing out every
        // section's own padding because this chain didn't exist yet).
        std::vector<libhtmlpp::AncestorFrame> ancestorChain = {};
    };
    std::stack<Frame> workStack;
    workStack.push({htmlEl, parentXml, stopBefore, rootCustomProperties});
@@ -1039,8 +1063,11 @@ void blogi::htmlimport::htmlElementToWidgetXml(
                libhtmlpp::Element *child = el->firstChild();
                if (child) {
                    // No cssProps computed for these structural tags -- just
                    // pass the inherited environment through unchanged.
                    childFrames.push_back({child, pXml, nullptr, frame.customPropertyEnv});
                    // pass the inherited environment/ancestor chain through
                    // unchanged (dropping the chain here would make every
                    // element under <body> think it has no ancestors at all).
                    childFrames.push_back(
                        {child, pXml, nullptr, frame.customPropertyEnv, frame.ancestorChain});
                }
                cur = cur->nextElement();
                continue;
@@ -1056,8 +1083,12 @@ void blogi::htmlimport::htmlElementToWidgetXml(

            // Every matching rule for this element -- its own inline style,
            // every <style> block, and any externally fetched stylesheet
            // already folded into `sheet` below -- fully cascaded.
            auto cssRules = libhtmlpp::getCSSRules(*el, sheet, seenMediaBlocks);
            // already folded into `sheet` below -- fully cascaded, with
            // frame.ancestorChain (this element's OWN ancestors, not
            // including itself) verifying any descendant-combinator selector
            // instead of letting it match regardless of where the element
            // actually lives.
            auto cssRules = libhtmlpp::getCSSRules(*el, sheet, seenMediaBlocks, &frame.ancestorChain);
            auto cssProps = cssRules.properties;
            std::string mediaRules = cssRules.mediaRules;
            applyBackgroundColorShorthand(cssProps);
@@ -1065,6 +1096,13 @@ void blogi::htmlimport::htmlElementToWidgetXml(
            std::map<std::string,std::string> elementEnv =
                resolveCustomProperties(cssProps, frame.customPropertyEnv);

            // This element's own ancestor chain, for its children's matching
            // (see Frame::ancestorChain) -- appended once here and reused at
            // every childFrames.push_back below, rather than re-splitting
            // cssClass per push site.
            std::vector<libhtmlpp::AncestorFrame> childAncestorChain = frame.ancestorChain;
            childAncestorChain.push_back({tag, splitClassList(cssClass), elemId});

            // ---- Map HTML tags to widget types ----

            // Shared by "section" and the semantic wrapper tags below --
@@ -1119,7 +1157,7 @@ void blogi::htmlimport::htmlElementToWidgetXml(
                }
                pXml->InsertEndChild(w);
                libhtmlpp::Element *child = el->firstChild();
                if (child) childFrames.push_back({child, w, nullptr, elementEnv});
                if (child) childFrames.push_back({child, w, nullptr, elementEnv, childAncestorChain});
            };

            if (tag == "section") {
@@ -1164,7 +1202,7 @@ void blogi::htmlimport::htmlElementToWidgetXml(
                }
                pXml->InsertEndChild(w);
                libhtmlpp::Element *child = el->firstChild();
                if (child) childFrames.push_back({child, w, nullptr, elementEnv});
                if (child) childFrames.push_back({child, w, nullptr, elementEnv, childAncestorChain});

            } else if (tag == "div" || tag == "label" || tag == "figure" ||
                       tag == "figcaption" || tag == "picture" || tag == "li") {
@@ -1262,7 +1300,7 @@ void blogi::htmlimport::htmlElementToWidgetXml(
                }
                pXml->InsertEndChild(w);
                libhtmlpp::Element *child = el->firstChild();
                if (child) childFrames.push_back({child, w, nullptr, elementEnv});
                if (child) childFrames.push_back({child, w, nullptr, elementEnv, childAncestorChain});

            } else if (tag == "img") {
                tinyxml2::XMLElement *w = doc.NewElement("Image");
@@ -1530,7 +1568,8 @@ void blogi::htmlimport::htmlElementToWidgetXml(
                                // the workStack would walk straight through
                                // them too, reprocessing (and duplicating)
                                // every later sibling <li>.
                                childFrames.push_back({liEl, w, liEl->nextElement(), elementEnv});
                                childFrames.push_back(
                                    {liEl, w, liEl->nextElement(), elementEnv, childAncestorChain});
                            }
                        }
                    }
@@ -1679,7 +1718,7 @@ void blogi::htmlimport::htmlElementToWidgetXml(
                    }
                    pXml->InsertEndChild(w);
                    libhtmlpp::Element *child = el->firstChild();
                    if (child) childFrames.push_back({child, w, nullptr, elementEnv});
                    if (child) childFrames.push_back({child, w, nullptr, elementEnv, childAncestorChain});
                }

            } else if (tag == "h1" || tag == "h2" || tag == "h3" || tag == "h4" ||