Change NodeToString.cpp to output JSON not html #1563

Closed
joevilches wants to merge 3 commits from export-D52929268 into main
20 changed files with 25071 additions and 445 deletions
Showing only changes of commit 292e2f3944 - Show all commits

View File

@@ -17,3 +17,7 @@ file(GLOB SOURCES CONFIGURE_DEPENDS
add_library(capture STATIC ${SOURCES}) add_library(capture STATIC ${SOURCES})
target_link_libraries(capture yogacore) target_link_libraries(capture yogacore)
target_include_directories(capture
PUBLIC
$<BUILD_INTERFACE:${YOGA_ROOT}/lib>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_PREFIX}/include/yoga/lib>)

View File

@@ -5,224 +5,255 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
#include <stdarg.h>
#include <capture/NodeToString.h> #include <capture/NodeToString.h>
#include <algorithm> #include <nlohmann/json.hpp>
namespace facebook::yoga { namespace facebook::yoga {
static void indent(std::string& base, uint32_t level) { using namespace nlohmann;
for (uint32_t i = 0; i < level; ++i) {
base.append(" "); static void appendFloatIfNotDefault(
json& j,
std::string_view key,
float num,
float defaultNum) {
if (num != defaultNum && !YGFloatIsUndefined(num)) {
j["style"][key] = num;
} }
} }
static void appendFormattedString(std::string& str, const char* fmt, ...) { static void appendYGValueIfNotDefault(
va_list args; json& j,
va_start(args, fmt); std::string_view key,
va_list argsCopy; const YGValue& value,
va_copy(argsCopy, args); const YGValue& defaultValue) {
std::vector<char> buf(1 + static_cast<size_t>(vsnprintf(NULL, 0, fmt, args))); if (value != defaultValue) {
va_end(args); if (value.unit == YGUnitAuto) {
vsnprintf(buf.data(), buf.size(), fmt, argsCopy); j["style"][key]["unit"] = "auto";
va_end(argsCopy); } else if (value.unit == YGUnitUndefined) {
std::string result = std::string(buf.begin(), buf.end() - 1); j["style"][key]["unit"] = "undefined";
str.append(result);
}
static void appendFloatOptionalIfDefined(
std::string& base,
const std::string key,
const float num) {
if (num != YGUndefined) {
appendFormattedString(base, "%s: %g; ", key.c_str(), num);
}
}
static void appendNumberIfNotUndefined(
std::string& base,
const std::string key,
const YGValue& number) {
if (number.unit != YGUnitUndefined) {
if (number.unit == YGUnitAuto) {
base.append(key + ": auto; ");
} else { } else {
std::string unit = number.unit == YGUnitPoint ? "px" : "%%"; std::string unit = value.unit == YGUnitPoint ? "px" : "%%";
appendFormattedString( j["style"][key]["value"] = value.value;
base, "%s: %g%s; ", key.c_str(), number.value, unit.c_str()); j["style"][key]["unit"] = unit;
} }
} }
} }
static void appendNumberIfNotAuto( static void appendEnumValueIfNotDefault(
std::string& base, json& j,
const std::string& key, std::string_view key,
const YGValue& number) { std::string_view value,
if (number.unit != YGUnitAuto) { std::string_view defaultValue) {
appendNumberIfNotUndefined(base, key, number); if (value != defaultValue) {
} j["style"][key] = value;
}
static void appendNumberIfNotZero(
std::string& base,
const std::string& str,
const YGValue& number) {
if (number.unit == YGUnitAuto) {
base.append(str + ": auto; ");
} else if (number.value != 0) {
appendNumberIfNotUndefined(base, str, number);
} }
} }
template <auto Field> template <auto Field>
static void static void appendEdges(
appendEdges(std::string& base, const std::string& key, YGNodeRef node) { json& j,
appendNumberIfNotZero(base, key + "-left", (*Field)(node, YGEdgeLeft)); const std::string& key,
appendNumberIfNotZero(base, key + "-right", (*Field)(node, YGEdgeRight)); YGNodeRef node,
appendNumberIfNotZero(base, key + "-top", (*Field)(node, YGEdgeTop)); YGNodeRef defaultNode) {
appendNumberIfNotZero(base, key + "-bottom", (*Field)(node, YGEdgeBottom)); appendYGValueIfNotDefault(
appendNumberIfNotZero(base, key + "-all", (*Field)(node, YGEdgeAll)); j,
appendNumberIfNotZero(base, key + "-start", (*Field)(node, YGEdgeStart)); key + "-left",
appendNumberIfNotZero(base, key + "-end", (*Field)(node, YGEdgeEnd)); (*Field)(node, YGEdgeLeft),
appendNumberIfNotZero( (*Field)(defaultNode, YGEdgeLeft));
base, key + "-horizontal", (*Field)(node, YGEdgeHorizontal)); appendYGValueIfNotDefault(
appendNumberIfNotZero( j,
base, key + "-vertical", (*Field)(node, YGEdgeVertical)); key + "-right",
(*Field)(node, YGEdgeRight),
(*Field)(defaultNode, YGEdgeRight));
appendYGValueIfNotDefault(
j,
key + "-top",
(*Field)(node, YGEdgeTop),
(*Field)(defaultNode, YGEdgeTop));
appendYGValueIfNotDefault(
j,
key + "-bottom",
(*Field)(node, YGEdgeBottom),
(*Field)(defaultNode, YGEdgeBottom));
appendYGValueIfNotDefault(
j,
key + "-all",
(*Field)(node, YGEdgeAll),
(*Field)(defaultNode, YGEdgeAll));
appendYGValueIfNotDefault(
j,
key + "-start",
(*Field)(node, YGEdgeStart),
(*Field)(defaultNode, YGEdgeStart));
appendYGValueIfNotDefault(
j,
key + "-end",
(*Field)(node, YGEdgeEnd),
(*Field)(defaultNode, YGEdgeEnd));
appendYGValueIfNotDefault(
j,
key + "-vertical",
(*Field)(node, YGEdgeVertical),
(*Field)(defaultNode, YGEdgeVertical));
appendYGValueIfNotDefault(
j,
key + "-horizontal",
(*Field)(node, YGEdgeHorizontal),
(*Field)(defaultNode, YGEdgeHorizontal));
} }
YGValue borderFloatToYGValue(YGNodeRef node, YGEdge edge) { YGValue borderFloatToYGValue(YGNodeRef node, YGEdge edge) {
float val = YGNodeStyleGetBorder(node, edge); float val = YGNodeStyleGetBorder(node, edge);
YGUnit unit = val == YGUndefined ? YGUnitUndefined : YGUnitPoint; YGUnit unit = YGFloatIsUndefined(val) ? YGUnitUndefined : YGUnitPoint;
return YGValue{val, unit}; return YGValue{val, unit};
} }
void nodeToString( static void nodeToStringImpl(json& j, YGNodeRef node, YGPrintOptions options) {
std::string& str,
YGNodeRef node,
YGPrintOptions options,
uint32_t level) {
indent(str, level);
appendFormattedString(str, "<div ");
if ((options & YGPrintOptionsLayout) == YGPrintOptionsLayout) { if ((options & YGPrintOptionsLayout) == YGPrintOptionsLayout) {
appendFormattedString(str, "layout=\""); j["layout"]["width"] = YGNodeStyleGetWidth(node).value;
appendFormattedString(str, "width: %g; ", YGNodeLayoutGetWidth(node)); j["layout"]["height"] = YGNodeStyleGetHeight(node).value;
appendFormattedString(str, "height: %g; ", YGNodeLayoutGetHeight(node)); j["layout"]["top"] = YGNodeStyleGetPosition(node, YGEdgeTop).value;
appendFormattedString(str, "top: %g; ", YGNodeLayoutGetTop(node)); j["layout"]["left"] = YGNodeStyleGetPosition(node, YGEdgeLeft).value;
appendFormattedString(str, "left: %g;", YGNodeLayoutGetLeft(node));
appendFormattedString(str, "\" ");
} }
if ((options & YGPrintOptionsStyle) == YGPrintOptionsStyle) { if ((options & YGPrintOptionsStyle) == YGPrintOptionsStyle) {
const YGNodeRef defaultNode = YGNodeNew(); const YGNodeRef defaultNode = YGNodeNew();
appendFormattedString(str, "style=\""); appendEnumValueIfNotDefault(
if (YGNodeStyleGetFlexDirection(node) != j,
YGNodeStyleGetFlexDirection(defaultNode)) { "flex-direction",
appendFormattedString( YGFlexDirectionToString(YGNodeStyleGetFlexDirection(node)),
str, YGFlexDirectionToString(YGNodeStyleGetFlexDirection(defaultNode)));
"flex-direction: %s; ", appendEnumValueIfNotDefault(
YGFlexDirectionToString(YGNodeStyleGetFlexDirection(node))); j,
} "justify-content",
if (YGNodeStyleGetJustifyContent(node) != YGJustifyToString(YGNodeStyleGetJustifyContent(node)),
YGNodeStyleGetJustifyContent(defaultNode)) { YGJustifyToString(YGNodeStyleGetJustifyContent(defaultNode)));
appendFormattedString( appendEnumValueIfNotDefault(
str, j,
"justify-content: %s; ", "align-items",
YGJustifyToString(YGNodeStyleGetJustifyContent(node))); YGAlignToString(YGNodeStyleGetAlignItems(node)),
} YGAlignToString(YGNodeStyleGetAlignItems(defaultNode)));
if (YGNodeStyleGetAlignItems(node) != appendEnumValueIfNotDefault(
YGNodeStyleGetAlignItems(defaultNode)) { j,
appendFormattedString( "align-content",
str, YGAlignToString(YGNodeStyleGetAlignContent(node)),
"align-items: %s; ", YGAlignToString(YGNodeStyleGetAlignContent(defaultNode)));
YGAlignToString(YGNodeStyleGetAlignItems(node))); appendEnumValueIfNotDefault(
} j,
if (YGNodeStyleGetAlignContent(node) != "align-self",
YGNodeStyleGetAlignContent(defaultNode)) { YGAlignToString(YGNodeStyleGetAlignSelf(node)),
appendFormattedString( YGAlignToString(YGNodeStyleGetAlignSelf(defaultNode)));
str, appendEnumValueIfNotDefault(
"align-content: %s; ", j,
YGAlignToString(YGNodeStyleGetAlignContent(node))); "flex-wrap",
} YGWrapToString(YGNodeStyleGetFlexWrap(node)),
if (YGNodeStyleGetAlignSelf(node) != YGNodeStyleGetAlignSelf(defaultNode)) { YGWrapToString(YGNodeStyleGetFlexWrap(defaultNode)));
appendFormattedString( appendEnumValueIfNotDefault(
str, j,
"align-self: %s; ", "overflow",
YGAlignToString(YGNodeStyleGetAlignSelf(node))); YGOverflowToString(YGNodeStyleGetOverflow(node)),
} YGOverflowToString(YGNodeStyleGetOverflow(defaultNode)));
appendFloatOptionalIfDefined( appendEnumValueIfNotDefault(
str, "flex-grow", YGNodeStyleGetFlexGrow(node)); j,
appendFloatOptionalIfDefined( "display",
str, "flex-shrink", YGNodeStyleGetFlexShrink(node)); YGDisplayToString(YGNodeStyleGetDisplay(node)),
appendNumberIfNotAuto(str, "flex-basis", YGNodeStyleGetFlexBasis(node)); YGDisplayToString(YGNodeStyleGetDisplay(defaultNode)));
appendFloatOptionalIfDefined(str, "flex", YGNodeStyleGetFlex(node)); appendEnumValueIfNotDefault(
j,
"position-type",
YGPositionTypeToString(YGNodeStyleGetPositionType(node)),
YGPositionTypeToString(YGNodeStyleGetPositionType(defaultNode)));
if (YGNodeStyleGetFlexWrap(node) != YGNodeStyleGetFlexWrap(defaultNode)) { appendFloatIfNotDefault(
appendFormattedString( j,
str, "flex-wrap: %s; ", YGWrapToString(YGNodeStyleGetFlexWrap(node))); "flex-grow",
} YGNodeStyleGetFlexGrow(node),
YGNodeStyleGetFlexGrow(defaultNode));
appendFloatIfNotDefault(
j,
"flex-shrink",
YGNodeStyleGetFlexShrink(node),
YGNodeStyleGetFlexShrink(defaultNode));
appendFloatIfNotDefault(
j, "flex", YGNodeStyleGetFlex(node), YGNodeStyleGetFlex(defaultNode));
appendYGValueIfNotDefault(
j,
"flex-basis",
YGNodeStyleGetFlexBasis(node),
YGNodeStyleGetFlexBasis(defaultNode));
if (YGNodeStyleGetOverflow(node) != YGNodeStyleGetOverflow(defaultNode)) { appendEdges<&YGNodeStyleGetMargin>(j, "margin", node, defaultNode);
appendFormattedString( appendEdges<&YGNodeStyleGetPadding>(j, "padding", node, defaultNode);
str, appendEdges<&borderFloatToYGValue>(j, "border", node, defaultNode);
"overflow: %s; ", appendEdges<&YGNodeStyleGetPosition>(j, "position", node, defaultNode);
YGOverflowToString(YGNodeStyleGetOverflow(node)));
}
if (YGNodeStyleGetDisplay(node) != YGNodeStyleGetDisplay(defaultNode)) { appendFloatIfNotDefault(
appendFormattedString( j,
str, "display: %s; ", YGDisplayToString(YGNodeStyleGetDisplay(node))); "gap",
} YGNodeStyleGetGap(node, YGGutterAll),
appendEdges<&YGNodeStyleGetMargin>(str, "margin", node); YGNodeStyleGetGap(defaultNode, YGGutterAll));
appendEdges<&YGNodeStyleGetPadding>(str, "padding", node); appendFloatIfNotDefault(
appendEdges<&borderFloatToYGValue>(str, "border", node); j,
"column-gap",
YGNodeStyleGetGap(node, YGGutterColumn),
YGNodeStyleGetGap(defaultNode, YGGutterColumn));
appendFloatIfNotDefault(
j,
"row-gap",
YGNodeStyleGetGap(node, YGGutterRow),
YGNodeStyleGetGap(defaultNode, YGGutterRow));
if (YGNodeStyleGetGap(node, YGGutterAll) != YGUndefined) { appendYGValueIfNotDefault(
appendFloatOptionalIfDefined( j,
str, "gap", YGNodeStyleGetGap(node, YGGutterAll)); "width",
} else { YGNodeStyleGetWidth(node),
appendFloatOptionalIfDefined( YGNodeStyleGetWidth(defaultNode));
str, "column-gap", YGNodeStyleGetGap(node, YGGutterColumn)); appendYGValueIfNotDefault(
appendFloatOptionalIfDefined( j,
str, "row-gap", YGNodeStyleGetGap(node, YGGutterRow)); "height",
} YGNodeStyleGetHeight(node),
YGNodeStyleGetHeight(defaultNode));
appendNumberIfNotAuto(str, "width", YGNodeStyleGetWidth(node)); appendYGValueIfNotDefault(
appendNumberIfNotAuto(str, "height", YGNodeStyleGetHeight(node)); j,
appendNumberIfNotAuto(str, "max-width", YGNodeStyleGetMaxWidth(node)); "max-width",
appendNumberIfNotAuto(str, "max-height", YGNodeStyleGetMaxHeight(node)); YGNodeStyleGetMaxWidth(node),
appendNumberIfNotAuto(str, "min-width", YGNodeStyleGetMinWidth(node)); YGNodeStyleGetMaxWidth(defaultNode));
appendNumberIfNotAuto(str, "min-height", YGNodeStyleGetMinHeight(node)); appendYGValueIfNotDefault(
j,
if (YGNodeStyleGetPositionType(node) != "max-height",
YGNodeStyleGetPositionType(defaultNode)) { YGNodeStyleGetMaxHeight(node),
appendFormattedString( YGNodeStyleGetMaxHeight(defaultNode));
str, appendYGValueIfNotDefault(
"position: %s; ", j,
YGPositionTypeToString(YGNodeStyleGetPositionType(node))); "min-width",
} YGNodeStyleGetMinWidth(node),
YGNodeStyleGetMinWidth(defaultNode));
appendEdges<&YGNodeStyleGetPosition>(str, "position", node); appendYGValueIfNotDefault(
appendFormattedString(str, "\" "); j,
"min-height",
YGNodeStyleGetMinHeight(node),
YGNodeStyleGetMinHeight(defaultNode));
if (YGNodeHasMeasureFunc(node)) { if (YGNodeHasMeasureFunc(node)) {
appendFormattedString(str, "has-custom-measure=\"true\""); j["style"]["has-custom-measure"] = true;
} }
} }
appendFormattedString(str, ">");
const size_t childCount = YGNodeGetChildCount(node); const size_t childCount = YGNodeGetChildCount(node);
if ((options & YGPrintOptionsChildren) == YGPrintOptionsChildren && if ((options & YGPrintOptionsChildren) == YGPrintOptionsChildren &&
childCount > 0) { childCount > 0) {
for (size_t i = 0; i < childCount; i++) { for (size_t i = 0; i < childCount; i++) {
appendFormattedString(str, "\n"); j["children"].push_back({});
nodeToString(str, YGNodeGetChild(node, i), options, level + 1); nodeToStringImpl(j["children"][i], YGNodeGetChild(node, i), options);
} }
appendFormattedString(str, "\n");
indent(str, level);
} }
appendFormattedString(str, "</div>"); }
void nodeToString(std::string& str, YGNodeRef node, YGPrintOptions options) {
json j;
nodeToStringImpl(j, node, options);
str = j.dump(2);
} }
} // namespace facebook::yoga } // namespace facebook::yoga

View File

@@ -13,10 +13,6 @@
namespace facebook::yoga { namespace facebook::yoga {
void nodeToString( void nodeToString(std::string& str, YGNodeRef node, YGPrintOptions options);
std::string& str,
YGNodeRef node,
YGPrintOptions options,
uint32_t level);
} // namespace facebook::yoga } // namespace facebook::yoga

24766
lib/nlohmann/json.hpp Normal file

File diff suppressed because it is too large Load Diff