Loading editor/html/css/editor.css +61 −0 Changes for editor/html/css/editor.css: 61 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -460,6 +460,67 @@ body { background: var(--accent-hover); } /* Spacing box (padding/margin: linked top/right/bottom/left inputs) */ .spacing-box { display: flex; align-items: flex-end; gap: 6px; } .spacing-box-side { flex: 1; min-width: 0; } .spacing-box-side-label { display: block; font-size: 10px; color: var(--text-secondary); margin-bottom: 2px; } .spacing-box-side input { width: 100%; padding: 6px 6px; background: var(--bg-tertiary); color: var(--text-primary); border: 1px solid var(--border); border-radius: 3px; font-size: 12px; font-family: inherit; } .spacing-box-side input:focus { outline: none; border-color: var(--accent); } .spacing-box-lock { flex: none; width: 28px; height: 28px; background: var(--bg-tertiary); border: 1px solid var(--border); border-radius: 3px; color: var(--text-secondary); cursor: pointer; font-size: 13px; display: flex; align-items: center; justify-content: center; line-height: 1; } .spacing-box-lock:hover { color: var(--text-primary); } .spacing-box-lock.active { color: var(--bg-primary); background: var(--accent); border-color: var(--accent); } /* Property panel tabs */ .prop-tabs { display: flex; Loading editor/html/js/canvas.js +9 −2 Changes for editor/html/js/canvas.js: 9 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -102,8 +102,15 @@ var Canvas = (function() { } else if (d.type === 'blogi-margin-change') { // The canvas already shows the dragged margin live; save it and // refresh so the properties sidebar (if open on this element) // picks up the new value. EditorApi.setProperties(d.uuid, { margin: d.value }).then(function() { // picks up the new value. Widgets model margin as four independent // fields (margin_top/right/bottom/left, see container.cpp's // addSpacingBox) rather than a single CSS shorthand string, so all // four sides are sent — widgets without a margin field just ignore // the unknown keys, same as before. EditorApi.setProperties(d.uuid, { margin_top: d.top, margin_right: d.right, margin_bottom: d.bottom, margin_left: d.left }).then(function() { if (onChangeCallback) onChangeCallback(); }).catch(function(err) { console.error('Margin change failed to save:', err); Loading editor/html/js/properties.js +68 −0 Changes for editor/html/js/properties.js: 68 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -372,6 +372,70 @@ var PropertiesPanel = (function() { group.appendChild(customPanel); } // Renders a padding/margin field as four top/right/bottom/left inputs plus // a lock toggle. Locking mirrors whatever side is being typed into across // the other three, so one value can drive all sides at once; unlocking // lets each side diverge again. Every side is a real named <input> so the // generic saveProperties() sweep (form.querySelectorAll('input,...')) // picks them up with no special-casing needed there. function _renderSpacingBox(group, field, properties) { var sides = ['top', 'right', 'bottom', 'left']; var sideLabels = { top: (typeof I18n !== 'undefined') ? I18n.t('I18N_SPACING_TOP', 'Oben') : 'Oben', right: (typeof I18n !== 'undefined') ? I18n.t('I18N_SPACING_RIGHT', 'Rechts') : 'Rechts', bottom: (typeof I18n !== 'undefined') ? I18n.t('I18N_SPACING_BOTTOM', 'Unten') : 'Unten', left: (typeof I18n !== 'undefined') ? I18n.t('I18N_SPACING_LEFT', 'Links') : 'Links' }; var wrap = document.createElement('div'); wrap.className = 'spacing-box'; var locked = false; var inputs = {}; var lockBtn = document.createElement('button'); lockBtn.type = 'button'; lockBtn.className = 'spacing-box-lock'; lockBtn.title = 'Alle Seiten gemeinsam ändern'; lockBtn.textContent = '🔓'; lockBtn.addEventListener('click', function() { locked = !locked; lockBtn.classList.toggle('active', locked); lockBtn.textContent = locked ? '🔒' : '🔓'; }); sides.forEach(function(side) { var sideWrap = document.createElement('div'); sideWrap.className = 'spacing-box-side spacing-box-side-' + side; var sideLabel = document.createElement('span'); sideLabel.className = 'spacing-box-side-label'; sideLabel.textContent = sideLabels[side]; var input = document.createElement('input'); input.type = 'text'; input.name = field.keys[side]; input.value = properties[field.keys[side]] || ''; if (field.placeholder) input.placeholder = field.placeholder; input.addEventListener('input', function() { if (!locked) return; sides.forEach(function(otherSide) { if (otherSide === side) return; inputs[otherSide].value = input.value; }); }); inputs[side] = input; sideWrap.appendChild(sideLabel); sideWrap.appendChild(input); wrap.appendChild(sideWrap); }); wrap.appendChild(lockBtn); group.appendChild(wrap); } function _renderFieldsInto(panel, fields, properties, form) { for (var i = 0; i < fields.length; i++) { var field = fields[i]; Loading Loading @@ -452,6 +516,10 @@ var PropertiesPanel = (function() { _renderColorField(group, field, value); panel.appendChild(group); continue; } else if (field.type === 'spacing_box') { _renderSpacingBox(group, field, properties); panel.appendChild(group); continue; } else if (field.type === 'html' || field.type === 'richtext') { var rteWrap = document.createElement('div'); rteWrap.className = 'rte-wrap'; Loading editor/src/webedit_api.cpp +1 −1 Changes for editor/src/webedit_api.cpp: 1 added line, 1 removed line. Original line number Diff line number Diff line Loading @@ -1941,7 +1941,7 @@ std::string buildCanvasScript(const std::string &metaJson) { "var bottom=d.el.style.marginBottom||cs.marginBottom;" "var left=d.el.style.marginLeft||cs.marginLeft;" "window.parent.postMessage({type:'blogi-margin-change',uuid:d.uuid," "value:[top,right,bottom,left].join(' ')},'*');" "top:top,right:right,bottom:bottom,left:left},'*');" "});" "})();</script>"; } Loading editor/widgets/article/article.cpp +102 −22 Changes for editor/widgets/article/article.cpp: 102 added lines, 22 removed lines. Original line number Diff line number Diff line Loading @@ -47,8 +47,14 @@ extern "C" { std::string borderRadius = ""; std::string borderStyle = ""; std::string opacity = ""; std::string padding = ""; std::string margin = ""; std::string paddingTop = ""; std::string paddingRight = ""; std::string paddingBottom = ""; std::string paddingLeft = ""; std::string marginTop = ""; std::string marginRight = ""; std::string marginBottom = ""; std::string marginLeft = ""; std::string maxWidth = ""; std::string minHeight = ""; std::string width = ""; Loading Loading @@ -183,6 +189,25 @@ extern "C" { for (auto v : vals) json_object_array_add(a, json_object_new_string(v)); return a; }; // 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. auto addSpacingBox = [&](const char *key, const char *label, const char *target, const char *level = "expert") { 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)); json_object_object_add(f, "type", json_object_new_string("spacing_box")); json_object_object_add(f, "placeholder", json_object_new_string("e.g. 10px")); json_object_object_add(f, "target", json_object_new_string(target)); json_object_object_add(f, "level", json_object_new_string(level)); json_object *keys = json_object_new_object(); json_object_object_add(keys, "top", json_object_new_string((std::string(key) + "_top").c_str())); json_object_object_add(keys, "right", json_object_new_string((std::string(key) + "_right").c_str())); json_object_object_add(keys, "bottom", json_object_new_string((std::string(key) + "_bottom").c_str())); json_object_object_add(keys, "left", json_object_new_string((std::string(key) + "_left").c_str())); json_object_object_add(f, "keys", keys); json_object_array_add(arr, f); }; addField("background_color", "Background Color (Dark)", "color_var", nullptr, "desktop", nullptr, "simple"); addField("l_background_color", "Background Color (Light)", "color_var", nullptr, "light", nullptr, "simple"); addField("background_gradient_type", "Background Gradient", "select", nullptr, "desktop", mkOpts({"none","linear","radial"}), "simple"); Loading @@ -196,8 +221,8 @@ extern "C" { addField("m_background_gradient_angle", "Mobile Gradient Angle", "text", "e.g. 135deg", "mobile"); addField("m_background_gradient_custom", "Mobile Gradient Custom", "text", "e.g. linear-gradient(135deg, #ff0000, #0000ff)", "mobile"); addField("css_class", "CSS Class", "text", "e.g. card"); addField("padding", "Padding", "text", "e.g. 28px", "desktop"); addField("margin", "Margin", "text", "e.g. 0 auto", "desktop"); addSpacingBox("padding", "Padding", "desktop"); addSpacingBox("margin", "Margin", "desktop"); addField("max_width", "Max Width", "text", "e.g. 800px", "desktop"); addField("min_height", "Min Height", "text", "e.g. 200px", "desktop"); addField("width", "Width", "text", "e.g. 100%", "desktop"); Loading Loading @@ -240,8 +265,14 @@ extern "C" { element->SetAttribute("border_radius", borderRadius.c_str()); element->SetAttribute("border_style", borderStyle.c_str()); element->SetAttribute("opacity", opacity.c_str()); element->SetAttribute("padding", padding.c_str()); element->SetAttribute("margin", margin.c_str()); element->SetAttribute("padding_top", paddingTop.c_str()); element->SetAttribute("padding_right", paddingRight.c_str()); element->SetAttribute("padding_bottom", paddingBottom.c_str()); element->SetAttribute("padding_left", paddingLeft.c_str()); element->SetAttribute("margin_top", marginTop.c_str()); element->SetAttribute("margin_right", marginRight.c_str()); element->SetAttribute("margin_bottom", marginBottom.c_str()); element->SetAttribute("margin_left", marginLeft.c_str()); element->SetAttribute("max_width", maxWidth.c_str()); element->SetAttribute("min_height", minHeight.c_str()); element->SetAttribute("width", width.c_str()); Loading Loading @@ -315,10 +346,31 @@ extern "C" { if (val) borderStyle = val; val = xml_data->Attribute("opacity"); if (val) opacity = val; val = xml_data->Attribute("padding"); if (val) padding = val; val = xml_data->Attribute("margin"); if (val) margin = val; // Legacy migration: pre-split documents stored padding/margin as // a single CSS shorthand attribute. Split it into the per-side // fields below; the new per-side attributes (read next) take // precedence if the file was already saved in the new format. const char* legacy_padding = xml_data->Attribute("padding"); if (legacy_padding) splitSpacingShorthand(legacy_padding, paddingTop, paddingRight, paddingBottom, paddingLeft); const char* legacy_margin = xml_data->Attribute("margin"); if (legacy_margin) splitSpacingShorthand(legacy_margin, marginTop, marginRight, marginBottom, marginLeft); val = xml_data->Attribute("padding_top"); if (val) paddingTop = val; val = xml_data->Attribute("padding_right"); if (val) paddingRight = val; val = xml_data->Attribute("padding_bottom"); if (val) paddingBottom = val; val = xml_data->Attribute("padding_left"); if (val) paddingLeft = val; val = xml_data->Attribute("margin_top"); if (val) marginTop = val; val = xml_data->Attribute("margin_right"); if (val) marginRight = val; val = xml_data->Attribute("margin_bottom"); if (val) marginBottom = val; val = xml_data->Attribute("margin_left"); if (val) marginLeft = val; val = xml_data->Attribute("max_width"); if (val) maxWidth = val; val = xml_data->Attribute("min_height"); Loading Loading @@ -405,8 +457,14 @@ extern "C" { json_object_object_add(obj, "border_radius", json_object_new_string(borderRadius.c_str())); json_object_object_add(obj, "border_style", json_object_new_string(borderStyle.c_str())); json_object_object_add(obj, "opacity", json_object_new_string(opacity.c_str())); json_object_object_add(obj, "padding", json_object_new_string(padding.c_str())); json_object_object_add(obj, "margin", json_object_new_string(margin.c_str())); json_object_object_add(obj, "padding_top", json_object_new_string(paddingTop.c_str())); json_object_object_add(obj, "padding_right", json_object_new_string(paddingRight.c_str())); json_object_object_add(obj, "padding_bottom", json_object_new_string(paddingBottom.c_str())); json_object_object_add(obj, "padding_left", json_object_new_string(paddingLeft.c_str())); json_object_object_add(obj, "margin_top", json_object_new_string(marginTop.c_str())); json_object_object_add(obj, "margin_right", json_object_new_string(marginRight.c_str())); json_object_object_add(obj, "margin_bottom", json_object_new_string(marginBottom.c_str())); json_object_object_add(obj, "margin_left", json_object_new_string(marginLeft.c_str())); json_object_object_add(obj, "max_width", json_object_new_string(maxWidth.c_str())); json_object_object_add(obj, "min_height", json_object_new_string(minHeight.c_str())); json_object_object_add(obj, "width", json_object_new_string(width.c_str())); Loading Loading @@ -469,13 +527,37 @@ extern "C" { val = json_object_get_string(val_obj); if (val) opacity = val; } if (json_object_object_get_ex(obj, "padding", &val_obj)) { if (json_object_object_get_ex(obj, "padding_top", &val_obj)) { val = json_object_get_string(val_obj); if (val) paddingTop = val; } if (json_object_object_get_ex(obj, "padding_right", &val_obj)) { val = json_object_get_string(val_obj); if (val) paddingRight = val; } if (json_object_object_get_ex(obj, "padding_bottom", &val_obj)) { val = json_object_get_string(val_obj); if (val) padding = val; if (val) paddingBottom = val; } if (json_object_object_get_ex(obj, "margin", &val_obj)) { if (json_object_object_get_ex(obj, "padding_left", &val_obj)) { val = json_object_get_string(val_obj); if (val) margin = val; if (val) paddingLeft = val; } if (json_object_object_get_ex(obj, "margin_top", &val_obj)) { val = json_object_get_string(val_obj); if (val) marginTop = val; } if (json_object_object_get_ex(obj, "margin_right", &val_obj)) { val = json_object_get_string(val_obj); if (val) marginRight = val; } if (json_object_object_get_ex(obj, "margin_bottom", &val_obj)) { val = json_object_get_string(val_obj); if (val) marginBottom = val; } if (json_object_object_get_ex(obj, "margin_left", &val_obj)) { val = json_object_get_string(val_obj); if (val) marginLeft = val; } if (json_object_object_get_ex(obj, "max_width", &val_obj)) { val = json_object_get_string(val_obj); Loading Loading @@ -647,12 +729,10 @@ extern "C" { if (!opacity.empty()) { style += " opacity: " + opacity + ";"; } if (!padding.empty()) { style += " padding: " + padding + ";"; } if (!margin.empty()) { style += " margin: " + margin + ";"; } std::string paddingShorthand = joinSpacingShorthand(paddingTop, paddingRight, paddingBottom, paddingLeft); if (!paddingShorthand.empty()) style += " padding: " + paddingShorthand + ";"; std::string marginShorthand = joinSpacingShorthand(marginTop, marginRight, marginBottom, marginLeft); if (!marginShorthand.empty()) style += " margin: " + marginShorthand + ";"; if (!maxWidth.empty()) { style += " max-width: " + maxWidth + ";"; } Loading Loading
editor/html/css/editor.css +61 −0 Changes for editor/html/css/editor.css: 61 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -460,6 +460,67 @@ body { background: var(--accent-hover); } /* Spacing box (padding/margin: linked top/right/bottom/left inputs) */ .spacing-box { display: flex; align-items: flex-end; gap: 6px; } .spacing-box-side { flex: 1; min-width: 0; } .spacing-box-side-label { display: block; font-size: 10px; color: var(--text-secondary); margin-bottom: 2px; } .spacing-box-side input { width: 100%; padding: 6px 6px; background: var(--bg-tertiary); color: var(--text-primary); border: 1px solid var(--border); border-radius: 3px; font-size: 12px; font-family: inherit; } .spacing-box-side input:focus { outline: none; border-color: var(--accent); } .spacing-box-lock { flex: none; width: 28px; height: 28px; background: var(--bg-tertiary); border: 1px solid var(--border); border-radius: 3px; color: var(--text-secondary); cursor: pointer; font-size: 13px; display: flex; align-items: center; justify-content: center; line-height: 1; } .spacing-box-lock:hover { color: var(--text-primary); } .spacing-box-lock.active { color: var(--bg-primary); background: var(--accent); border-color: var(--accent); } /* Property panel tabs */ .prop-tabs { display: flex; Loading
editor/html/js/canvas.js +9 −2 Changes for editor/html/js/canvas.js: 9 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -102,8 +102,15 @@ var Canvas = (function() { } else if (d.type === 'blogi-margin-change') { // The canvas already shows the dragged margin live; save it and // refresh so the properties sidebar (if open on this element) // picks up the new value. EditorApi.setProperties(d.uuid, { margin: d.value }).then(function() { // picks up the new value. Widgets model margin as four independent // fields (margin_top/right/bottom/left, see container.cpp's // addSpacingBox) rather than a single CSS shorthand string, so all // four sides are sent — widgets without a margin field just ignore // the unknown keys, same as before. EditorApi.setProperties(d.uuid, { margin_top: d.top, margin_right: d.right, margin_bottom: d.bottom, margin_left: d.left }).then(function() { if (onChangeCallback) onChangeCallback(); }).catch(function(err) { console.error('Margin change failed to save:', err); Loading
editor/html/js/properties.js +68 −0 Changes for editor/html/js/properties.js: 68 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -372,6 +372,70 @@ var PropertiesPanel = (function() { group.appendChild(customPanel); } // Renders a padding/margin field as four top/right/bottom/left inputs plus // a lock toggle. Locking mirrors whatever side is being typed into across // the other three, so one value can drive all sides at once; unlocking // lets each side diverge again. Every side is a real named <input> so the // generic saveProperties() sweep (form.querySelectorAll('input,...')) // picks them up with no special-casing needed there. function _renderSpacingBox(group, field, properties) { var sides = ['top', 'right', 'bottom', 'left']; var sideLabels = { top: (typeof I18n !== 'undefined') ? I18n.t('I18N_SPACING_TOP', 'Oben') : 'Oben', right: (typeof I18n !== 'undefined') ? I18n.t('I18N_SPACING_RIGHT', 'Rechts') : 'Rechts', bottom: (typeof I18n !== 'undefined') ? I18n.t('I18N_SPACING_BOTTOM', 'Unten') : 'Unten', left: (typeof I18n !== 'undefined') ? I18n.t('I18N_SPACING_LEFT', 'Links') : 'Links' }; var wrap = document.createElement('div'); wrap.className = 'spacing-box'; var locked = false; var inputs = {}; var lockBtn = document.createElement('button'); lockBtn.type = 'button'; lockBtn.className = 'spacing-box-lock'; lockBtn.title = 'Alle Seiten gemeinsam ändern'; lockBtn.textContent = '🔓'; lockBtn.addEventListener('click', function() { locked = !locked; lockBtn.classList.toggle('active', locked); lockBtn.textContent = locked ? '🔒' : '🔓'; }); sides.forEach(function(side) { var sideWrap = document.createElement('div'); sideWrap.className = 'spacing-box-side spacing-box-side-' + side; var sideLabel = document.createElement('span'); sideLabel.className = 'spacing-box-side-label'; sideLabel.textContent = sideLabels[side]; var input = document.createElement('input'); input.type = 'text'; input.name = field.keys[side]; input.value = properties[field.keys[side]] || ''; if (field.placeholder) input.placeholder = field.placeholder; input.addEventListener('input', function() { if (!locked) return; sides.forEach(function(otherSide) { if (otherSide === side) return; inputs[otherSide].value = input.value; }); }); inputs[side] = input; sideWrap.appendChild(sideLabel); sideWrap.appendChild(input); wrap.appendChild(sideWrap); }); wrap.appendChild(lockBtn); group.appendChild(wrap); } function _renderFieldsInto(panel, fields, properties, form) { for (var i = 0; i < fields.length; i++) { var field = fields[i]; Loading Loading @@ -452,6 +516,10 @@ var PropertiesPanel = (function() { _renderColorField(group, field, value); panel.appendChild(group); continue; } else if (field.type === 'spacing_box') { _renderSpacingBox(group, field, properties); panel.appendChild(group); continue; } else if (field.type === 'html' || field.type === 'richtext') { var rteWrap = document.createElement('div'); rteWrap.className = 'rte-wrap'; Loading
editor/src/webedit_api.cpp +1 −1 Changes for editor/src/webedit_api.cpp: 1 added line, 1 removed line. Original line number Diff line number Diff line Loading @@ -1941,7 +1941,7 @@ std::string buildCanvasScript(const std::string &metaJson) { "var bottom=d.el.style.marginBottom||cs.marginBottom;" "var left=d.el.style.marginLeft||cs.marginLeft;" "window.parent.postMessage({type:'blogi-margin-change',uuid:d.uuid," "value:[top,right,bottom,left].join(' ')},'*');" "top:top,right:right,bottom:bottom,left:left},'*');" "});" "})();</script>"; } Loading
editor/widgets/article/article.cpp +102 −22 Changes for editor/widgets/article/article.cpp: 102 added lines, 22 removed lines. Original line number Diff line number Diff line Loading @@ -47,8 +47,14 @@ extern "C" { std::string borderRadius = ""; std::string borderStyle = ""; std::string opacity = ""; std::string padding = ""; std::string margin = ""; std::string paddingTop = ""; std::string paddingRight = ""; std::string paddingBottom = ""; std::string paddingLeft = ""; std::string marginTop = ""; std::string marginRight = ""; std::string marginBottom = ""; std::string marginLeft = ""; std::string maxWidth = ""; std::string minHeight = ""; std::string width = ""; Loading Loading @@ -183,6 +189,25 @@ extern "C" { for (auto v : vals) json_object_array_add(a, json_object_new_string(v)); return a; }; // 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. auto addSpacingBox = [&](const char *key, const char *label, const char *target, const char *level = "expert") { 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)); json_object_object_add(f, "type", json_object_new_string("spacing_box")); json_object_object_add(f, "placeholder", json_object_new_string("e.g. 10px")); json_object_object_add(f, "target", json_object_new_string(target)); json_object_object_add(f, "level", json_object_new_string(level)); json_object *keys = json_object_new_object(); json_object_object_add(keys, "top", json_object_new_string((std::string(key) + "_top").c_str())); json_object_object_add(keys, "right", json_object_new_string((std::string(key) + "_right").c_str())); json_object_object_add(keys, "bottom", json_object_new_string((std::string(key) + "_bottom").c_str())); json_object_object_add(keys, "left", json_object_new_string((std::string(key) + "_left").c_str())); json_object_object_add(f, "keys", keys); json_object_array_add(arr, f); }; addField("background_color", "Background Color (Dark)", "color_var", nullptr, "desktop", nullptr, "simple"); addField("l_background_color", "Background Color (Light)", "color_var", nullptr, "light", nullptr, "simple"); addField("background_gradient_type", "Background Gradient", "select", nullptr, "desktop", mkOpts({"none","linear","radial"}), "simple"); Loading @@ -196,8 +221,8 @@ extern "C" { addField("m_background_gradient_angle", "Mobile Gradient Angle", "text", "e.g. 135deg", "mobile"); addField("m_background_gradient_custom", "Mobile Gradient Custom", "text", "e.g. linear-gradient(135deg, #ff0000, #0000ff)", "mobile"); addField("css_class", "CSS Class", "text", "e.g. card"); addField("padding", "Padding", "text", "e.g. 28px", "desktop"); addField("margin", "Margin", "text", "e.g. 0 auto", "desktop"); addSpacingBox("padding", "Padding", "desktop"); addSpacingBox("margin", "Margin", "desktop"); addField("max_width", "Max Width", "text", "e.g. 800px", "desktop"); addField("min_height", "Min Height", "text", "e.g. 200px", "desktop"); addField("width", "Width", "text", "e.g. 100%", "desktop"); Loading Loading @@ -240,8 +265,14 @@ extern "C" { element->SetAttribute("border_radius", borderRadius.c_str()); element->SetAttribute("border_style", borderStyle.c_str()); element->SetAttribute("opacity", opacity.c_str()); element->SetAttribute("padding", padding.c_str()); element->SetAttribute("margin", margin.c_str()); element->SetAttribute("padding_top", paddingTop.c_str()); element->SetAttribute("padding_right", paddingRight.c_str()); element->SetAttribute("padding_bottom", paddingBottom.c_str()); element->SetAttribute("padding_left", paddingLeft.c_str()); element->SetAttribute("margin_top", marginTop.c_str()); element->SetAttribute("margin_right", marginRight.c_str()); element->SetAttribute("margin_bottom", marginBottom.c_str()); element->SetAttribute("margin_left", marginLeft.c_str()); element->SetAttribute("max_width", maxWidth.c_str()); element->SetAttribute("min_height", minHeight.c_str()); element->SetAttribute("width", width.c_str()); Loading Loading @@ -315,10 +346,31 @@ extern "C" { if (val) borderStyle = val; val = xml_data->Attribute("opacity"); if (val) opacity = val; val = xml_data->Attribute("padding"); if (val) padding = val; val = xml_data->Attribute("margin"); if (val) margin = val; // Legacy migration: pre-split documents stored padding/margin as // a single CSS shorthand attribute. Split it into the per-side // fields below; the new per-side attributes (read next) take // precedence if the file was already saved in the new format. const char* legacy_padding = xml_data->Attribute("padding"); if (legacy_padding) splitSpacingShorthand(legacy_padding, paddingTop, paddingRight, paddingBottom, paddingLeft); const char* legacy_margin = xml_data->Attribute("margin"); if (legacy_margin) splitSpacingShorthand(legacy_margin, marginTop, marginRight, marginBottom, marginLeft); val = xml_data->Attribute("padding_top"); if (val) paddingTop = val; val = xml_data->Attribute("padding_right"); if (val) paddingRight = val; val = xml_data->Attribute("padding_bottom"); if (val) paddingBottom = val; val = xml_data->Attribute("padding_left"); if (val) paddingLeft = val; val = xml_data->Attribute("margin_top"); if (val) marginTop = val; val = xml_data->Attribute("margin_right"); if (val) marginRight = val; val = xml_data->Attribute("margin_bottom"); if (val) marginBottom = val; val = xml_data->Attribute("margin_left"); if (val) marginLeft = val; val = xml_data->Attribute("max_width"); if (val) maxWidth = val; val = xml_data->Attribute("min_height"); Loading Loading @@ -405,8 +457,14 @@ extern "C" { json_object_object_add(obj, "border_radius", json_object_new_string(borderRadius.c_str())); json_object_object_add(obj, "border_style", json_object_new_string(borderStyle.c_str())); json_object_object_add(obj, "opacity", json_object_new_string(opacity.c_str())); json_object_object_add(obj, "padding", json_object_new_string(padding.c_str())); json_object_object_add(obj, "margin", json_object_new_string(margin.c_str())); json_object_object_add(obj, "padding_top", json_object_new_string(paddingTop.c_str())); json_object_object_add(obj, "padding_right", json_object_new_string(paddingRight.c_str())); json_object_object_add(obj, "padding_bottom", json_object_new_string(paddingBottom.c_str())); json_object_object_add(obj, "padding_left", json_object_new_string(paddingLeft.c_str())); json_object_object_add(obj, "margin_top", json_object_new_string(marginTop.c_str())); json_object_object_add(obj, "margin_right", json_object_new_string(marginRight.c_str())); json_object_object_add(obj, "margin_bottom", json_object_new_string(marginBottom.c_str())); json_object_object_add(obj, "margin_left", json_object_new_string(marginLeft.c_str())); json_object_object_add(obj, "max_width", json_object_new_string(maxWidth.c_str())); json_object_object_add(obj, "min_height", json_object_new_string(minHeight.c_str())); json_object_object_add(obj, "width", json_object_new_string(width.c_str())); Loading Loading @@ -469,13 +527,37 @@ extern "C" { val = json_object_get_string(val_obj); if (val) opacity = val; } if (json_object_object_get_ex(obj, "padding", &val_obj)) { if (json_object_object_get_ex(obj, "padding_top", &val_obj)) { val = json_object_get_string(val_obj); if (val) paddingTop = val; } if (json_object_object_get_ex(obj, "padding_right", &val_obj)) { val = json_object_get_string(val_obj); if (val) paddingRight = val; } if (json_object_object_get_ex(obj, "padding_bottom", &val_obj)) { val = json_object_get_string(val_obj); if (val) padding = val; if (val) paddingBottom = val; } if (json_object_object_get_ex(obj, "margin", &val_obj)) { if (json_object_object_get_ex(obj, "padding_left", &val_obj)) { val = json_object_get_string(val_obj); if (val) margin = val; if (val) paddingLeft = val; } if (json_object_object_get_ex(obj, "margin_top", &val_obj)) { val = json_object_get_string(val_obj); if (val) marginTop = val; } if (json_object_object_get_ex(obj, "margin_right", &val_obj)) { val = json_object_get_string(val_obj); if (val) marginRight = val; } if (json_object_object_get_ex(obj, "margin_bottom", &val_obj)) { val = json_object_get_string(val_obj); if (val) marginBottom = val; } if (json_object_object_get_ex(obj, "margin_left", &val_obj)) { val = json_object_get_string(val_obj); if (val) marginLeft = val; } if (json_object_object_get_ex(obj, "max_width", &val_obj)) { val = json_object_get_string(val_obj); Loading Loading @@ -647,12 +729,10 @@ extern "C" { if (!opacity.empty()) { style += " opacity: " + opacity + ";"; } if (!padding.empty()) { style += " padding: " + padding + ";"; } if (!margin.empty()) { style += " margin: " + margin + ";"; } std::string paddingShorthand = joinSpacingShorthand(paddingTop, paddingRight, paddingBottom, paddingLeft); if (!paddingShorthand.empty()) style += " padding: " + paddingShorthand + ";"; std::string marginShorthand = joinSpacingShorthand(marginTop, marginRight, marginBottom, marginLeft); if (!marginShorthand.empty()) style += " margin: " + marginShorthand + ";"; if (!maxWidth.empty()) { style += " max-width: " + maxWidth + ";"; } Loading