Loading editor/src/webedit_api.cpp +19 −1 Changes for editor/src/webedit_api.cpp: 19 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -4706,14 +4706,32 @@ namespace { if (!trimmed.empty()) blocks.push_back(trimmed); } // json_object_new_string() downstream (webedit_api.cpp publishToConnectionCore) // is strlen()-based and silently truncates at the first embedded NUL byte. // Log exactly which widget produced one and where, so the root cause in that // widget's toLlmsBlock() can be tracked down instead of just papering over // the truncation. void logEmbeddedNul(const blogi::webedit::EditPlugin *widget, const std::string &text) { size_t nulPos = text.find('\0'); if (nulPos == std::string::npos) return; size_t ctxStart = nulPos >= 20 ? nulPos - 20 : 0; size_t ctxLen = std::min<size_t>(40, text.size() - ctxStart); std::cerr << "[webedit] generateLlmsTxt: embedded NUL byte at offset " << nulPos << " of " << text.size() << " bytes in toLlmsBlock() output from widget '" << widget->getName() << "' (instance " << widget->getInstanceId().c_str() << "); context: \"" << text.substr(ctxStart, ctxLen) << "\"" << std::endl; } // Walks the live widget tree, asking each widget for its own text via // EditPlugin::toLlmsBlock() and always recursing into children — a widget // can contribute a block of its own (e.g. Accordion's header) AND still // have its children walked (e.g. Accordion's panel content). void collectLlmsBlocks(const blogi::webedit::EditPlugin *el, std::vector<std::string> &blocks) { for (const blogi::webedit::EditPlugin *cur = el; cur; cur = cur->nextElement()) { if (auto block = cur->toLlmsBlock()) if (auto block = cur->toLlmsBlock()) { logEmbeddedNul(cur, *block); appendBlock(blocks, *block); } if (const blogi::webedit::EditPlugin *child = cur->getChildElement()) collectLlmsBlocks(child, blocks); } Loading Loading
editor/src/webedit_api.cpp +19 −1 Changes for editor/src/webedit_api.cpp: 19 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -4706,14 +4706,32 @@ namespace { if (!trimmed.empty()) blocks.push_back(trimmed); } // json_object_new_string() downstream (webedit_api.cpp publishToConnectionCore) // is strlen()-based and silently truncates at the first embedded NUL byte. // Log exactly which widget produced one and where, so the root cause in that // widget's toLlmsBlock() can be tracked down instead of just papering over // the truncation. void logEmbeddedNul(const blogi::webedit::EditPlugin *widget, const std::string &text) { size_t nulPos = text.find('\0'); if (nulPos == std::string::npos) return; size_t ctxStart = nulPos >= 20 ? nulPos - 20 : 0; size_t ctxLen = std::min<size_t>(40, text.size() - ctxStart); std::cerr << "[webedit] generateLlmsTxt: embedded NUL byte at offset " << nulPos << " of " << text.size() << " bytes in toLlmsBlock() output from widget '" << widget->getName() << "' (instance " << widget->getInstanceId().c_str() << "); context: \"" << text.substr(ctxStart, ctxLen) << "\"" << std::endl; } // Walks the live widget tree, asking each widget for its own text via // EditPlugin::toLlmsBlock() and always recursing into children — a widget // can contribute a block of its own (e.g. Accordion's header) AND still // have its children walked (e.g. Accordion's panel content). void collectLlmsBlocks(const blogi::webedit::EditPlugin *el, std::vector<std::string> &blocks) { for (const blogi::webedit::EditPlugin *cur = el; cur; cur = cur->nextElement()) { if (auto block = cur->toLlmsBlock()) if (auto block = cur->toLlmsBlock()) { logEmbeddedNul(cur, *block); appendBlock(blocks, *block); } if (const blogi::webedit::EditPlugin *child = cur->getChildElement()) collectLlmsBlocks(child, blocks); } Loading