Loading editor/src/htmlimport.cpp +75 −14 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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") Loading Loading @@ -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); Loading Loading @@ -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"); Loading @@ -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); Loading Loading @@ -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); Loading @@ -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); Loading Loading @@ -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); Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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); Loading editor/src/htmlimport.h +10 −2 Original line number Diff line number Diff line Loading @@ -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); Loading Loading
editor/src/htmlimport.cpp +75 −14 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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") Loading Loading @@ -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); Loading Loading @@ -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"); Loading @@ -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); Loading Loading @@ -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); Loading @@ -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); Loading Loading @@ -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); Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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); Loading
editor/src/htmlimport.h +10 −2 Original line number Diff line number Diff line Loading @@ -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); Loading