Commit 4e96ac0e authored by Jan Koester's avatar Jan Koester
Browse files

new import

parent dd28e880
Loading
Loading
Loading
Loading
+75 −14
Original line number Diff line number Diff line
@@ -829,15 +829,18 @@ std::string blogi::htmlimport::extractCustomCss(
    std::map<std::string,std::string> &props,
    const std::vector<std::string> &knownKeys,
    const std::string &mediaRules,
    std::string &outInstanceId)
    std::string &outInstanceId,
    const std::set<std::string> &inlineKeys)
{
    std::string plainDecls;
    std::vector<std::string> toRemove;
    for (auto &[k, v] : props) {
        bool known = false;
        if (!inlineKeys.count(k)) {
            for (auto &kk : knownKeys) {
                if (k == kk) { known = true; break; }
            }
        }
        if (!known) {
            toRemove.push_back(k);

@@ -1173,6 +1176,50 @@ void blogi::htmlimport::htmlElementToWidgetXml(
            std::map<std::string,std::string> elementEnv =
                resolveCustomProperties(cssProps, frame.customPropertyEnv);

            // Inline style="..." declarations must never be structurally
            // mapped onto a widget field (background_color, padding, ...)
            // below -- only cascade-matched stylesheet rules should be.
            // libhtmlpp::getCSSRules() already merged both into one cascaded
            // cssProps map above, so this re-parses the same raw `style`
            // text independently just to know WHICH keys are inline-origin,
            // then removes them from cssProps before any of the
            // per-widget-tag mapping below runs -- every "if
            // (cssProps.count(...))" check from here on simply can't see
            // them. Each branch's own extractCustomCss() call further down
            // puts them back into cssProps right before sweeping (see
            // inlineOnlyDecls below), so they still end up in that widget's
            // Custom CSS, verbatim, instead of vanishing.
            std::set<std::string> inlineKeys;
            for (const auto &prop : libhtmlpp::CSSStyleSheet::parseInlineStyle(style).getProperties()) {
                inlineKeys.insert(prop.getName());
            }
            // The shorthand-combining helpers just above fold several
            // longhand declarations into one shorthand cssProps key -- if
            // any piece that fed a given shorthand was inline, treat the
            // resulting shorthand as inline too, so it isn't structurally
            // mapped either.
            if (inlineKeys.count("background") && cssProps.count("background-color"))
                inlineKeys.insert("background-color");
            if ((inlineKeys.count("border-width") || inlineKeys.count("border-style") ||
                 inlineKeys.count("border-color")) && cssProps.count("border"))
                inlineKeys.insert("border");
            if ((inlineKeys.count("padding-top") || inlineKeys.count("padding-right") ||
                 inlineKeys.count("padding-bottom") || inlineKeys.count("padding-left")) &&
                cssProps.count("padding"))
                inlineKeys.insert("padding");
            if ((inlineKeys.count("margin-top") || inlineKeys.count("margin-right") ||
                 inlineKeys.count("margin-bottom") || inlineKeys.count("margin-left")) &&
                cssProps.count("margin"))
                inlineKeys.insert("margin");
            std::map<std::string,std::string> inlineOnlyDecls;
            for (const auto &k : inlineKeys) {
                auto it = cssProps.find(k);
                if (it != cssProps.end()) {
                    inlineOnlyDecls[k] = it->second;
                    cssProps.erase(it);
                }
            }

            // This element's own attributes, so a descendant's matched rule
            // can verify an attribute-selector condition on THIS ancestor
            // (e.g. the "[data-fit=fill]" in ".fade-box[data-fit=fill] img")
@@ -1237,7 +1284,8 @@ void blogi::htmlimport::htmlElementToWidgetXml(
                }
                applyFlexLayoutAttributes(w, cssProps, knownCss);
                std::string newInstanceId;
                std::string custom = extractCustomCss(cssProps, knownCss, mediaRules, newInstanceId);
                for (auto &kv : inlineOnlyDecls) cssProps[kv.first] = kv.second;
                std::string custom = extractCustomCss(cssProps, knownCss, mediaRules, newInstanceId, inlineKeys);
                std::string dataAttrs = extractReferencedDataAttrs(mediaRules, elemAttrs);
                if (!dataAttrs.empty()) w->SetAttribute("data_attrs", dataAttrs.c_str());
                finalizeInstanceId(w, elemId, newInstanceId, idToInstanceId);
@@ -1268,6 +1316,8 @@ void blogi::htmlimport::htmlElementToWidgetXml(
                    w->SetAttribute("margin", cssProps["margin"].c_str());
                if (!cssClass.empty())
                    w->SetAttribute("css_class", cssClass.c_str());
                if (!elemId.empty())
                    w->SetAttribute("css_id", elemId.c_str());
                if (cssMeansHidden(cssProps))
                    w->SetAttribute("hidden", "true");

@@ -1284,7 +1334,8 @@ void blogi::htmlimport::htmlElementToWidgetXml(
                }
                applyFlexLayoutAttributes(w, cssProps, knownCss);
                std::string newInstanceId;
                std::string custom = extractCustomCss(cssProps, knownCss, mediaRules, newInstanceId);
                for (auto &kv : inlineOnlyDecls) cssProps[kv.first] = kv.second;
                std::string custom = extractCustomCss(cssProps, knownCss, mediaRules, newInstanceId, inlineKeys);
                std::string dataAttrs = extractReferencedDataAttrs(mediaRules, elemAttrs);
                if (!dataAttrs.empty()) w->SetAttribute("data_attrs", dataAttrs.c_str());
                finalizeInstanceId(w, elemId, newInstanceId, idToInstanceId);
@@ -1363,7 +1414,8 @@ void blogi::htmlimport::htmlElementToWidgetXml(
                        }
                    }
                    std::string newInstanceId;
                    std::string custom = extractCustomCss(cssProps, knownCss, mediaRules, newInstanceId);
                    for (auto &kv : inlineOnlyDecls) cssProps[kv.first] = kv.second;
                    std::string custom = extractCustomCss(cssProps, knownCss, mediaRules, newInstanceId, inlineKeys);
                    std::string dataAttrs = extractReferencedDataAttrs(mediaRules, elemAttrs);
                    if (!dataAttrs.empty()) w->SetAttribute("data_attrs", dataAttrs.c_str());
                    finalizeInstanceId(w, elemId, newInstanceId, idToInstanceId);
@@ -1385,7 +1437,8 @@ void blogi::htmlimport::htmlElementToWidgetXml(
                    }
                    applyFlexLayoutAttributes(w, cssProps, knownCss);
                    std::string newInstanceId;
                    std::string custom = extractCustomCss(cssProps, knownCss, mediaRules, newInstanceId);
                    for (auto &kv : inlineOnlyDecls) cssProps[kv.first] = kv.second;
                    std::string custom = extractCustomCss(cssProps, knownCss, mediaRules, newInstanceId, inlineKeys);
                    std::string dataAttrs = extractReferencedDataAttrs(mediaRules, elemAttrs);
                    if (!dataAttrs.empty()) w->SetAttribute("data_attrs", dataAttrs.c_str());
                    finalizeInstanceId(w, elemId, newInstanceId, idToInstanceId);
@@ -1422,7 +1475,8 @@ void blogi::htmlimport::htmlElementToWidgetXml(
                    "width","height","object-fit","border-radius","border",
                    "display","visibility"};
                std::string newInstanceId;
                std::string custom = extractCustomCss(cssProps, knownCss, mediaRules, newInstanceId);
                for (auto &kv : inlineOnlyDecls) cssProps[kv.first] = kv.second;
                std::string custom = extractCustomCss(cssProps, knownCss, mediaRules, newInstanceId, inlineKeys);
                std::string dataAttrs = extractReferencedDataAttrs(mediaRules, elemAttrs);
                if (!dataAttrs.empty()) w->SetAttribute("data_attrs", dataAttrs.c_str());
                finalizeInstanceId(w, elemId, newInstanceId, idToInstanceId);
@@ -1446,7 +1500,8 @@ void blogi::htmlimport::htmlElementToWidgetXml(

                std::vector<std::string> knownCss = {"width","height","display"};
                std::string newInstanceId;
                std::string custom = extractCustomCss(cssProps, knownCss, mediaRules, newInstanceId);
                for (auto &kv : inlineOnlyDecls) cssProps[kv.first] = kv.second;
                std::string custom = extractCustomCss(cssProps, knownCss, mediaRules, newInstanceId, inlineKeys);
                std::string dataAttrs = extractReferencedDataAttrs(mediaRules, elemAttrs);
                if (!dataAttrs.empty()) w->SetAttribute("data_attrs", dataAttrs.c_str());
                finalizeInstanceId(w, elemId, newInstanceId, idToInstanceId);
@@ -1593,7 +1648,8 @@ void blogi::htmlimport::htmlElementToWidgetXml(
                    "border","background-color","border-collapse","width","height",
                    "display","visibility"};
                std::string newInstanceId;
                std::string custom = extractCustomCss(cssProps, knownCss, mediaRules, newInstanceId);
                for (auto &kv : inlineOnlyDecls) cssProps[kv.first] = kv.second;
                std::string custom = extractCustomCss(cssProps, knownCss, mediaRules, newInstanceId, inlineKeys);
                std::string dataAttrs = extractReferencedDataAttrs(mediaRules, elemAttrs);
                if (!dataAttrs.empty()) w->SetAttribute("data_attrs", dataAttrs.c_str());
                finalizeInstanceId(w, elemId, newInstanceId, idToInstanceId);
@@ -1684,7 +1740,8 @@ void blogi::htmlimport::htmlElementToWidgetXml(
                    "padding","margin","width","height","display","visibility","gap"};
                applyFlexLayoutAttributes(w, cssProps, knownCss);
                std::string newInstanceId;
                std::string custom = extractCustomCss(cssProps, knownCss, mediaRules, newInstanceId);
                for (auto &kv : inlineOnlyDecls) cssProps[kv.first] = kv.second;
                std::string custom = extractCustomCss(cssProps, knownCss, mediaRules, newInstanceId, inlineKeys);
                std::string dataAttrs = extractReferencedDataAttrs(mediaRules, elemAttrs);
                if (!dataAttrs.empty()) w->SetAttribute("data_attrs", dataAttrs.c_str());
                finalizeInstanceId(w, elemId, newInstanceId, idToInstanceId);
@@ -1752,7 +1809,8 @@ void blogi::htmlimport::htmlElementToWidgetXml(
                        "border-radius","border","width","height","display",
                        "visibility","text-decoration","cursor","text-align"};
                    std::string newInstanceId;
                    std::string custom = extractCustomCss(cssProps, knownCss, mediaRules, newInstanceId);
                    for (auto &kv : inlineOnlyDecls) cssProps[kv.first] = kv.second;
                    std::string custom = extractCustomCss(cssProps, knownCss, mediaRules, newInstanceId, inlineKeys);
                    std::string dataAttrs = extractReferencedDataAttrs(mediaRules, elemAttrs);
                    if (!dataAttrs.empty()) w->SetAttribute("data_attrs", dataAttrs.c_str());
                    finalizeInstanceId(w, elemId, newInstanceId, idToInstanceId);
@@ -1816,7 +1874,8 @@ void blogi::htmlimport::htmlElementToWidgetXml(
                    }
                    applyFlexLayoutAttributes(w, cssProps, knownCss);
                    std::string newInstanceId;
                    std::string custom = extractCustomCss(cssProps, knownCss, mediaRules, newInstanceId);
                    for (auto &kv : inlineOnlyDecls) cssProps[kv.first] = kv.second;
                    std::string custom = extractCustomCss(cssProps, knownCss, mediaRules, newInstanceId, inlineKeys);
                    std::string dataAttrs = extractReferencedDataAttrs(mediaRules, elemAttrs);
                    if (!dataAttrs.empty()) w->SetAttribute("data_attrs", dataAttrs.c_str());
                    finalizeInstanceId(w, elemId, newInstanceId, idToInstanceId);
@@ -1918,15 +1977,17 @@ void blogi::htmlimport::htmlElementToWidgetXml(
                    w->SetAttribute("font_style", cssProps["font-style"].c_str());
                if (!cssClass.empty())
                    w->SetAttribute("css_class", cssClass.c_str());
                if (!elemId.empty())
                    w->SetAttribute("css_id", elemId.c_str());
                // No css_id write here: TextBox has no css_id property to
                // consume it (unlike Section/Article/Container/Grid), so
                // writing it would just be a dead XML attribute.

                std::vector<std::string> knownCss = {
                    "font-family","font-size","color","text-align",
                    "font-weight","font-style","width","height",
                    "padding","margin","line-height"};
                std::string newInstanceId;
                std::string custom = extractCustomCss(cssProps, knownCss, mediaRules, newInstanceId);
                for (auto &kv : inlineOnlyDecls) cssProps[kv.first] = kv.second;
                std::string custom = extractCustomCss(cssProps, knownCss, mediaRules, newInstanceId, inlineKeys);
                std::string dataAttrs = extractReferencedDataAttrs(mediaRules, elemAttrs);
                if (!dataAttrs.empty()) w->SetAttribute("data_attrs", dataAttrs.c_str());
                finalizeInstanceId(w, elemId, newInstanceId, idToInstanceId);
+10 −2
Original line number Diff line number Diff line
@@ -96,12 +96,20 @@ namespace htmlimport {
     *  loadDocumentTreeFromXml, and handleImportHtml's own top-level loop)
     *  assigns exactly this id to the resulting widget instance instead of
     *  generating a random one, which is what makes the selector chosen
     *  here still correct once rendered. */
     *  here still correct once rendered.
     *
     *  @p inlineKeys names properties that came from the source element's
     *  own inline style="..." attribute (as opposed to a matched stylesheet
     *  rule) -- these are always treated as unknown/leftover regardless of
     *  @p knownKeys, so inline declarations are never structurally mapped
     *  onto a widget field, only ever passed through into this Custom CSS
     *  text verbatim. */
    std::string extractCustomCss(
        std::map<std::string,std::string> &props,
        const std::vector<std::string> &knownKeys,
        const std::string &mediaRules,
        std::string &outInstanceId);
        std::string &outInstanceId,
        const std::set<std::string> &inlineKeys);

    std::string serializeElement(const libhtmlpp::Element *el);
    std::string serializeInnerHtml(libhtmlpp::HtmlElement *el);