Commit 03b5afad authored by Jan Koester's avatar Jan Koester
Browse files

test

parent 71bed53b
Loading
Loading
Loading
Loading
+68 −5
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "plugin.h"
#include "translations.h"
#include "llms_text.h"
#include "../common/svg_markup.h"

extern "C" {
    namespace blogi::webedit {
@@ -54,6 +55,9 @@ extern "C" {
            std::string fontColor       = "var(--blogi-text)";
            std::string lineHeight      = "1.6";
            std::string listStyleType   = "";  // disc, circle, square, decimal, etc. (empty = browser default)
            // Resolved when list_style_type == "svg" (picked via the Icon Library)
            std::string svgMarkerIconId = "";
            std::string svgMarkerSvg    = "";
            std::string direction       = "vertical"; // "vertical" or "horizontal"
            std::string gap             = "";
            std::string alignItems      = "";
@@ -205,7 +209,8 @@ extern "C" {
                json_object *arr = json_object_new_array();
                auto addField = [&](const char *key, const char *label, const char *type,
                                    const char *placeholder = nullptr, const char *target = "all",
                                    json_object *options = nullptr, const char *level = "expert") {
                                    json_object *options = nullptr, const char *level = "expert",
                                    json_object *visibleWhen = nullptr) {
                    json_object *f = json_object_new_object();
                    json_object_object_add(f, "key", json_object_new_string(key));
                    json_object_object_add(f, "label", json_object_new_string(label));
@@ -213,6 +218,7 @@ extern "C" {
                    if (placeholder) json_object_object_add(f, "placeholder", json_object_new_string(placeholder));
                    json_object_object_add(f, "target", json_object_new_string(target));
                    if (options) json_object_object_add(f, "options", options);
                    if (visibleWhen) json_object_object_add(f, "visibleWhen", visibleWhen);
                    json_object_object_add(f, "level", json_object_new_string(level));
                    json_object_array_add(arr, f);
                };
@@ -221,6 +227,12 @@ extern "C" {
                    for (auto v : vals) json_object_array_add(a, json_object_new_string(v));
                    return a;
                };
                auto mkVisible = [](const char *key, const char *value) {
                    json_object *v = json_object_new_object();
                    json_object_object_add(v, "key", json_object_new_string(key));
                    json_object_object_add(v, "value", json_object_new_string(value));
                    return v;
                };
                // Renders as four linked top/right/bottom/left inputs with a lock
                // toggle in the properties panel (see properties.js _renderSpacingBox)
                // instead of a single raw CSS shorthand string.
@@ -244,7 +256,16 @@ extern "C" {
                         mkOpts({"ul", "ol"}), "simple");
                addField("list_style_type", "List Style", "select", nullptr, "all",
                         mkOpts({"", "disc", "circle", "square", "decimal", "decimal-leading-zero",
                                 "lower-alpha", "upper-alpha", "lower-roman", "upper-roman", "none", "emoji_circle"}), "simple");
                                 "lower-alpha", "upper-alpha", "lower-roman", "upper-roman", "none", "emoji_circle", "arrow", "svg"}), "simple");
                addField("svg_marker_icon_id", "Marker Icon (from Library)", "icon_browse", nullptr, "all",
                          nullptr, "simple", mkVisible("list_style_type", "svg"));
                {
                    // Tells the icon_browse picker (properties.js) which sibling field
                    // holds the resolved SVG source — Render() only ever reads svgMarkerSvg.
                    json_object *f = json_object_array_get_idx(arr, json_object_array_length(arr) - 1);
                    json_object_object_add(f, "svgTargetKey", json_object_new_string("svg_marker_svg"));
                }
                addField("svg_marker_svg", "", "hidden");
                addField("direction", "Direction", "select", nullptr, "desktop",
                         mkOpts({"vertical", "horizontal"}));
                addField("gap", "Gap", "text", "8px");
@@ -301,6 +322,7 @@ extern "C" {
                element->SetAttribute("type_id", getTypeId().c_str());
                element->SetAttribute("list_type", listType.c_str());
                element->SetAttribute("list_style_type", listStyleType.c_str());
                element->SetAttribute("svg_marker_icon_id", svgMarkerIconId.c_str());
                element->SetAttribute("direction", direction.c_str());
                element->SetAttribute("gap", gap.c_str());
                element->SetAttribute("align_items", alignItems.c_str());
@@ -342,6 +364,12 @@ extern "C" {
                if (!dataAttrs.empty())
                    element->SetAttribute("data_attrs", dataAttrs.c_str());

                if (!svgMarkerSvg.empty()) {
                    tinyxml2::XMLElement* svgEl = doc->NewElement("SvgMarkerSvg");
                    svgEl->SetText(svgMarkerSvg.c_str());
                    element->InsertEndChild(svgEl);
                }

                // Store items as child <Item> elements
                for (const auto &item : items) {
                    tinyxml2::XMLElement *li = doc->NewElement("Item");
@@ -357,6 +385,7 @@ extern "C" {

                val = xml_data->Attribute("list_type");       if (val) listType = val;
                val = xml_data->Attribute("list_style_type"); if (val) listStyleType = val;
                val = xml_data->Attribute("svg_marker_icon_id"); if (val) svgMarkerIconId = val;
                val = xml_data->Attribute("direction");       if (val) direction = val;
                val = xml_data->Attribute("gap");              if (val) gap = val;
                val = xml_data->Attribute("align_items");     if (val) alignItems = val;
@@ -425,6 +454,12 @@ extern "C" {
                val = xml_data->Attribute("data_attrs");
                if (val) dataAttrs = val;

                tinyxml2::XMLElement* svgEl = xml_data->FirstChildElement("SvgMarkerSvg");
                if (svgEl) {
                    const char* svgVal = svgEl->GetText();
                    if (svgVal) svgMarkerSvg = svgVal;
                }

                // Read items from child <Item> elements
                items.clear();
                for (tinyxml2::XMLElement *li = xml_data->FirstChildElement("Item"); li; li = li->NextSiblingElement("Item")) {
@@ -450,6 +485,8 @@ extern "C" {
                json_object *obj = json_object_new_object();
                json_object_object_add(obj, "list_type", json_object_new_string(listType.c_str()));
                json_object_object_add(obj, "list_style_type", json_object_new_string(listStyleType.c_str()));
                json_object_object_add(obj, "svg_marker_icon_id", json_object_new_string(svgMarkerIconId.c_str()));
                json_object_object_add(obj, "svg_marker_svg", json_object_new_string(svgMarkerSvg.c_str()));
                json_object_object_add(obj, "direction", json_object_new_string(direction.c_str()));
                json_object_object_add(obj, "gap", json_object_new_string(gap.c_str()));
                json_object_object_add(obj, "align_items", json_object_new_string(alignItems.c_str()));
@@ -507,6 +544,12 @@ extern "C" {
                if (json_object_object_get_ex(obj, "list_style_type", &val_obj)) {
                    val = json_object_get_string(val_obj); if (val) listStyleType = val;
                }
                if (json_object_object_get_ex(obj, "svg_marker_icon_id", &val_obj)) {
                    val = json_object_get_string(val_obj); if (val) svgMarkerIconId = val;
                }
                if (json_object_object_get_ex(obj, "svg_marker_svg", &val_obj)) {
                    val = json_object_get_string(val_obj); if (val) svgMarkerSvg = val;
                }
                if (json_object_object_get_ex(obj, "direction", &val_obj)) {
                    val = json_object_get_string(val_obj); if (val && val[0]) direction = val;
                }
@@ -652,7 +695,9 @@ extern "C" {
                if (!fontColor.empty())  style += " color: " + fontColor + ";";
                if (!lineHeight.empty()) style += " line-height: " + lineHeight + ";";
                bool useEmojiMarker = (listStyleType == "emoji_circle");
                if (useEmojiMarker) style += " list-style-type: none;";
                bool useArrowMarker = (listStyleType == "arrow");
                bool useSvgMarker   = (listStyleType == "svg" && !svgMarkerSvg.empty());
                if (useEmojiMarker || useArrowMarker || useSvgMarker) style += " list-style-type: none;";
                else if (!listStyleType.empty()) style += " list-style-type: " + listStyleType + ";";
                std::string paddingShorthand = joinSpacingShorthand(paddingTop, paddingRight, paddingBottom, paddingLeft);
                if (!paddingShorthand.empty()) style += " padding: " + paddingShorthand + ";";
@@ -668,11 +713,29 @@ extern "C" {

                for (const auto &item : items) {
                    libhtmlpp::HtmlElement li("li");
                    if (useEmojiMarker) {
                    if (useEmojiMarker || useArrowMarker || useSvgMarker) {
                        li.setAttribute("style", "display: flex; align-items: center; gap: 0.5em;");
                        libhtmlpp::HtmlElement marker("span");
                        marker.setAttribute("style", "flex: none;");
                        marker.appendChild(libhtmlpp::TextElement("❗"));
                        if (useSvgMarker) {
                            // Re-wrap the picked Icon Library SVG at a fixed "1em"
                            // slot size, following currentColor so the marker
                            // inherits the list's font_color (mirrors Textbox's
                            // custom-icon Render()).
                            std::string viewBox, inner;
                            svgmarkup::parse(svgMarkerSvg, viewBox, inner);
                            std::string vb = viewBox.empty() ? "0 0 24 24" : viewBox;
                            std::string svgHtml = "<svg width=\"1em\" height=\"1em\" viewBox=\"" +
                                                   vb + "\" fill=\"currentColor\" xmlns=\"http://www.w3.org/2000/svg\">" +
                                                   inner + "</svg>";
                            try {
                                libhtmlpp::HtmlString svgBuf(svgHtml);
                                libhtmlpp::Element &parsedSvg = svgBuf.parse();
                                marker.appendChild(parsedSvg);
                            } catch (...) {}
                        } else {
                            marker.appendChild(libhtmlpp::TextElement(useArrowMarker ? "➤" : "❗"));
                        }
                        li.appendChild(marker);
                    }
                    if (!item.empty()) {