Loading editor/src/htmlimport.cpp +82 −6 Changes for editor/src/htmlimport.cpp: 82 added lines, 6 removed lines. Original line number Diff line number Diff line Loading @@ -1123,7 +1123,18 @@ void blogi::htmlimport::htmlElementToWidgetXml( libhtmlpp::Element *child = el->firstChild(); if (child) childFrames.push_back({child, w, nullptr, elementEnv}); } else if (tag == "div") { } else if (tag == "div" || tag == "label") { // <label> (e.g. a clickable selectable-option "card" wrapping // an icon/image and its caption -- common in multi-step forms) // has no dedicated widget type, but unlike <a>/<button> its // own semantics (associating with a form control) aren't // visually significant for import purposes -- it's just // another styled box. Treating it exactly like a <div> // (rather than falling through to the generic CustomHtml // fallback below, which serializes the whole subtree as // opaque HTML) keeps its own background/padding/etc AND lets // its children -- e.g. an <img> card icon -- become their own // proper widgets instead of being lost inside that blob. bool isGrid = cssProps.count("display") && cssProps["display"] == "grid"; tinyxml2::XMLElement *w = doc.NewElement(isGrid ? "Grid" : "Container"); Loading Loading @@ -1450,7 +1461,14 @@ void blogi::htmlimport::htmlElementToWidgetXml( } pXml->InsertEndChild(w); } else if (tag == "a") { } else if (tag == "a" || tag == "button") { // <button> reuses this exact branch: it has no href/target of // its own, but getAtributte() on an attribute a <button> never // has is just an empty string, so the Button-widget path below // naturally comes out with no link_url/open_new_tab set -- // which is the correct, valid state for a plain non-link // trigger button. Everything else (plain-text label vs. rich // nested content) is the identical concern for both tags. bool hasChildElements = false; libhtmlpp::Element *aChild = el->firstChild(); while (aChild) { Loading Loading @@ -1509,11 +1527,69 @@ void blogi::htmlimport::htmlElementToWidgetXml( } pXml->InsertEndChild(w); } else { tinyxml2::XMLElement *w = doc.NewElement("CustomHtml"); tinyxml2::XMLElement *htmlContent = doc.NewElement("HtmlContent"); htmlContent->SetText(serializeElement(cur).c_str()); w->InsertEndChild(htmlContent); // An <a> wrapping rich content (e.g. a linked logo image, // or a card with its own heading/text/image) rather than // plain text has no single-attribute widget equivalent // like Button's "label" -- Container/Section have no // link_url of their own to hang the href on. Between // dropping the link and decomposing the children (Image/ // TextBox/...) or keeping the link and losing those // children to an opaque, unstyled, unlisted-in-any-import- // stat CustomHtml blob, this takes the same choice // <label> above does: treat it like a <div> so an <img> // inside (a linked logo being the common case) still // becomes a real, editable Image widget with its // lazy-loading placeholder resolved to the real src (see // preferLazyImageSrc) instead of silently staying the // source page's untouched, never-hydrated markup. The // href itself is dropped -- there is nowhere left to put // it once this element becomes a Container. bool isGrid = cssProps.count("display") && cssProps["display"] == "grid"; tinyxml2::XMLElement *w = doc.NewElement(isGrid ? "Grid" : "Container"); if (cssProps.count("background-color")) w->SetAttribute("background_color", cssProps["background-color"].c_str()); if (cssProps.count("border-radius")) w->SetAttribute("border_radius", cssProps["border-radius"].c_str()); if (cssProps.count("border")) w->SetAttribute("border_style", cssProps["border"].c_str()); if (cssProps.count("padding")) w->SetAttribute("padding", cssProps["padding"].c_str()); if (cssProps.count("margin")) w->SetAttribute("margin", cssProps["margin"].c_str()); if (cssProps.count("width")) w->SetAttribute("width", cssProps["width"].c_str()); if (cssProps.count("height")) w->SetAttribute("height", cssProps["height"].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"); std::vector<std::string> knownCss = { "background-color","border-radius","border","opacity", "padding","margin","width","height","display","visibility"}; if (cssProps.count("justify-content")) { std::string va = mapToVerticalAlign(cssProps["justify-content"], false); if (!va.empty()) { w->SetAttribute("vertical_align", va.c_str()); knownCss.push_back("justify-content"); } } applyFlexLayoutAttributes(w, cssProps, knownCss); std::string newInstanceId; std::string custom = extractCustomCss(cssProps, knownCss, mediaRules, newInstanceId); finalizeInstanceId(w, elemId, newInstanceId, idToInstanceId); if (!custom.empty()) { tinyxml2::XMLElement *ccEl = doc.NewElement("CustomCss"); ccEl->SetText(custom.c_str()); w->InsertEndChild(ccEl); } pXml->InsertEndChild(w); libhtmlpp::Element *child = el->firstChild(); if (child) childFrames.push_back({child, w, nullptr, elementEnv}); } } else if (tag == "h1" || tag == "h2" || tag == "h3" || tag == "h4" || Loading Loading
editor/src/htmlimport.cpp +82 −6 Changes for editor/src/htmlimport.cpp: 82 added lines, 6 removed lines. Original line number Diff line number Diff line Loading @@ -1123,7 +1123,18 @@ void blogi::htmlimport::htmlElementToWidgetXml( libhtmlpp::Element *child = el->firstChild(); if (child) childFrames.push_back({child, w, nullptr, elementEnv}); } else if (tag == "div") { } else if (tag == "div" || tag == "label") { // <label> (e.g. a clickable selectable-option "card" wrapping // an icon/image and its caption -- common in multi-step forms) // has no dedicated widget type, but unlike <a>/<button> its // own semantics (associating with a form control) aren't // visually significant for import purposes -- it's just // another styled box. Treating it exactly like a <div> // (rather than falling through to the generic CustomHtml // fallback below, which serializes the whole subtree as // opaque HTML) keeps its own background/padding/etc AND lets // its children -- e.g. an <img> card icon -- become their own // proper widgets instead of being lost inside that blob. bool isGrid = cssProps.count("display") && cssProps["display"] == "grid"; tinyxml2::XMLElement *w = doc.NewElement(isGrid ? "Grid" : "Container"); Loading Loading @@ -1450,7 +1461,14 @@ void blogi::htmlimport::htmlElementToWidgetXml( } pXml->InsertEndChild(w); } else if (tag == "a") { } else if (tag == "a" || tag == "button") { // <button> reuses this exact branch: it has no href/target of // its own, but getAtributte() on an attribute a <button> never // has is just an empty string, so the Button-widget path below // naturally comes out with no link_url/open_new_tab set -- // which is the correct, valid state for a plain non-link // trigger button. Everything else (plain-text label vs. rich // nested content) is the identical concern for both tags. bool hasChildElements = false; libhtmlpp::Element *aChild = el->firstChild(); while (aChild) { Loading Loading @@ -1509,11 +1527,69 @@ void blogi::htmlimport::htmlElementToWidgetXml( } pXml->InsertEndChild(w); } else { tinyxml2::XMLElement *w = doc.NewElement("CustomHtml"); tinyxml2::XMLElement *htmlContent = doc.NewElement("HtmlContent"); htmlContent->SetText(serializeElement(cur).c_str()); w->InsertEndChild(htmlContent); // An <a> wrapping rich content (e.g. a linked logo image, // or a card with its own heading/text/image) rather than // plain text has no single-attribute widget equivalent // like Button's "label" -- Container/Section have no // link_url of their own to hang the href on. Between // dropping the link and decomposing the children (Image/ // TextBox/...) or keeping the link and losing those // children to an opaque, unstyled, unlisted-in-any-import- // stat CustomHtml blob, this takes the same choice // <label> above does: treat it like a <div> so an <img> // inside (a linked logo being the common case) still // becomes a real, editable Image widget with its // lazy-loading placeholder resolved to the real src (see // preferLazyImageSrc) instead of silently staying the // source page's untouched, never-hydrated markup. The // href itself is dropped -- there is nowhere left to put // it once this element becomes a Container. bool isGrid = cssProps.count("display") && cssProps["display"] == "grid"; tinyxml2::XMLElement *w = doc.NewElement(isGrid ? "Grid" : "Container"); if (cssProps.count("background-color")) w->SetAttribute("background_color", cssProps["background-color"].c_str()); if (cssProps.count("border-radius")) w->SetAttribute("border_radius", cssProps["border-radius"].c_str()); if (cssProps.count("border")) w->SetAttribute("border_style", cssProps["border"].c_str()); if (cssProps.count("padding")) w->SetAttribute("padding", cssProps["padding"].c_str()); if (cssProps.count("margin")) w->SetAttribute("margin", cssProps["margin"].c_str()); if (cssProps.count("width")) w->SetAttribute("width", cssProps["width"].c_str()); if (cssProps.count("height")) w->SetAttribute("height", cssProps["height"].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"); std::vector<std::string> knownCss = { "background-color","border-radius","border","opacity", "padding","margin","width","height","display","visibility"}; if (cssProps.count("justify-content")) { std::string va = mapToVerticalAlign(cssProps["justify-content"], false); if (!va.empty()) { w->SetAttribute("vertical_align", va.c_str()); knownCss.push_back("justify-content"); } } applyFlexLayoutAttributes(w, cssProps, knownCss); std::string newInstanceId; std::string custom = extractCustomCss(cssProps, knownCss, mediaRules, newInstanceId); finalizeInstanceId(w, elemId, newInstanceId, idToInstanceId); if (!custom.empty()) { tinyxml2::XMLElement *ccEl = doc.NewElement("CustomCss"); ccEl->SetText(custom.c_str()); w->InsertEndChild(ccEl); } pXml->InsertEndChild(w); libhtmlpp::Element *child = el->firstChild(); if (child) childFrames.push_back({child, w, nullptr, elementEnv}); } } else if (tag == "h1" || tag == "h2" || tag == "h3" || tag == "h4" || Loading