Commit 05c63408 authored by jan.koester's avatar jan.koester
Browse files

test

parent 58d982d1
Loading
Loading
Loading
Loading
+97 −5
Changes for editor/src/webedit_api.cpp: 97 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -3421,16 +3421,18 @@ void webedit::Api::handlePublishToConnection(libhttppp::HttpRequest &curreq,
        return;
    }

    std::string docXml = exportTreeXml(doc);

    // Auto-publish surveys embedded in this document to the target blogi first,
    // so they exist server-side before the rendered HTML references them.
    {
        std::string domain;
        _session.getData(sessionid, "domain", domain);
        std::string docXml = exportTreeXml(doc);
        autoPublishSurveysForDocument(docXml, authid, blogUrl, domain);
    }

    std::string html = renderTree(doc.root);
    std::string llmsTxt = generateLlmsTxt(docXml);

    // Build the publish command:
    // [{"authid":"..."}, {"command":"publish","target":"template","html":"...","params":{...}}]
@@ -3440,14 +3442,19 @@ void webedit::Api::handlePublishToConnection(libhttppp::HttpRequest &curreq,
    json_object_object_add(authCmd, "authid", json_object_new_string(authid.c_str()));
    json_object_array_add(publishArr, authCmd);

    bool ownsParams = false;
    if (!paramsObj) {
        paramsObj = json_object_new_object();
        ownsParams = true;
    }
    if (!llmsTxt.empty())
        json_object_object_add(paramsObj, "llms_txt", json_object_new_string(llmsTxt.c_str()));

    json_object *publishCmd = json_object_new_object();
    json_object_object_add(publishCmd, "command", json_object_new_string("publish"));
    json_object_object_add(publishCmd, "target", json_object_new_string(target.c_str()));
    json_object_object_add(publishCmd, "html", json_object_new_string(html.c_str()));
    if (paramsObj)
        json_object_object_add(publishCmd, "params", json_object_get(paramsObj));
    else
        json_object_object_add(publishCmd, "params", json_object_new_object());
    json_object_object_add(publishCmd, "params", ownsParams ? paramsObj : json_object_get(paramsObj));
    json_object_array_add(publishArr, publishCmd);

    try {
@@ -3890,6 +3897,91 @@ std::string webedit::Api::exportTreeXml(DocumentState &doc) {
    return printer.CStr();
}

namespace {
    // Widget attributes that carry human-readable content (button/faq/image labels etc.)
    // rather than styling. Element text (tinyxml2 GetText()) is picked up separately —
    // that's how content-heavy widgets (Textbox, Article, List items, Table cells) store
    // their body text.
    const std::set<std::string> kLlmsTextAttributes = {
        "label", "title", "question", "answer", "alt"
    };

    void appendLlmsText(std::string &out, const std::string &text) {
        std::string trimmed = text;
        size_t start = trimmed.find_first_not_of(" \t\r\n");
        size_t end = trimmed.find_last_not_of(" \t\r\n");
        if (start == std::string::npos) return;
        trimmed = trimmed.substr(start, end - start + 1);
        if (trimmed.empty()) return;
        if (!out.empty()) out += "\n\n";
        out += trimmed;
    }

    // Strips HTML markup from a fragment by parsing it and concatenating text nodes,
    // falling back to the raw string if it isn't valid HTML.
    std::string stripHtml(const std::string &html) {
        if (html.find('<') == std::string::npos) return html;
        try {
            libhtmlpp::HtmlString parsed(html);
            libhtmlpp::Element &root = parsed.parse();
            std::string out;
            std::vector<libhtmlpp::Element*> stack;
            stack.push_back(&root);
            while (!stack.empty()) {
                libhtmlpp::Element *el = stack.back();
                stack.pop_back();
                for (libhtmlpp::Element *cur = el; cur; cur = cur->nextElement()) {
                    if (cur->getType() == libhtmlpp::TextEl) {
                        if (!out.empty()) out += " ";
                        out += static_cast<libhtmlpp::TextElement*>(cur)->getText();
                    } else if (cur->getType() == libhtmlpp::HtmlEl) {
                        libhtmlpp::HtmlElement *hel = static_cast<libhtmlpp::HtmlElement*>(cur);
                        std::string tag = hel->getTagname();
                        if (tag != "style" && tag != "script" && hel->firstChild())
                            stack.push_back(hel->firstChild());
                    }
                }
            }
            return out;
        } catch (...) {
            return html;
        }
    }

    void walkLlmsXml(const tinyxml2::XMLElement *el, std::string &out) {
        for (const tinyxml2::XMLElement *cur = el; cur; cur = cur->NextSiblingElement()) {
            std::string tag = cur->Name() ? cur->Name() : "";
            if (tag == "CustomCss") continue;

            for (const tinyxml2::XMLAttribute *attr = cur->FirstAttribute(); attr; attr = attr->Next()) {
                if (kLlmsTextAttributes.count(attr->Name()) && attr->Value() && attr->Value()[0])
                    appendLlmsText(out, attr->Value());
            }

            const char *text = cur->GetText();
            if (text && text[0])
                appendLlmsText(out, stripHtml(text));

            if (const tinyxml2::XMLElement *child = cur->FirstChildElement())
                walkLlmsXml(child, out);
        }
    }
}

std::string webedit::Api::generateLlmsTxt(const std::string &xml) {
    tinyxml2::XMLDocument xmlDoc;
    if (xmlDoc.Parse(xml.c_str(), xml.size()) != tinyxml2::XML_SUCCESS)
        return "";

    const tinyxml2::XMLElement *root = xmlDoc.RootElement();
    if (!root) return "";

    std::string out;
    if (const tinyxml2::XMLElement *child = root->FirstChildElement())
        walkLlmsXml(child, out);
    return out;
}

std::string webedit::Api::serializeElementXml(blogi::webedit::EditPlugin *node) {
    tinyxml2::XMLDocument xmlDoc;
    auto *root = xmlDoc.NewElement("WebEditor");
+1 −0
Changes for editor/src/webedit_api.h: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -181,6 +181,7 @@ namespace webedit {
        std::string renderTree(const blogi::webedit::EditPlugin *node);
        std::string exportTreeXml(DocumentState &doc);
        std::string serializeElementXml(blogi::webedit::EditPlugin *node);
        std::string generateLlmsTxt(const std::string &xml);
        void persistDocumentStateToSession(const std::string &sessionid, DocumentState &doc);
        void restoreDocumentStateFromSession(const std::string &sessionid, DocumentState &doc);
        void loadDocumentTreeFromXml(DocumentState &doc, const std::string &xml);