diff --git a/config/current.ver b/config/current.ver index a88dc16..234ef7d 100644 --- a/config/current.ver +++ b/config/current.ver @@ -1 +1 @@ -1.2.60 \ No newline at end of file +1.2.61 \ No newline at end of file diff --git a/public/assets/js/bridge/blocks-api.js b/public/assets/js/bridge/blocks-api.js index d3afc33..212044d 100644 --- a/public/assets/js/bridge/blocks-api.js +++ b/public/assets/js/bridge/blocks-api.js @@ -543,12 +543,102 @@ } return rawHtml; }; - const htmlBody = serializeHtml(); - const htmlContent = htmlBody + ''; + const cleanEmptyDefaultPsHtml = (html) => { + try { + const wrap = document.createElement('div'); + wrap.innerHTML = html || ''; + const nodes = wrap.querySelectorAll('p[data-gjs-type="default"]'); + nodes.forEach((p) => { + const inner = (p.innerHTML || '').trim(); + // Remove only truly empty default paragraphs (no content, no
, no  ) + if (!inner) p.remove(); + }); + return wrap.innerHTML || ''; + } catch { + return html || ''; + } + }; + const htmlBody = cleanEmptyDefaultPsHtml(serializeHtml()); + const extractIdsFromHtml = (html) => { + try { + const wrap = document.createElement('div'); + wrap.innerHTML = html || ''; + const ids = new Set(); + wrap.querySelectorAll('[id]').forEach((el) => { + const id = el.getAttribute('id'); + if (id) ids.add(id); + }); + return ids; + } catch { + return new Set(); + } + }; + const idsInHtml = extractIdsFromHtml(htmlBody); + const stripUnusedIdCss = (css, ids) => { + if (!css || !ids || !ids.size) return css || ''; + return String(css).replace(/#([A-Za-z0-9_-]+)\s*\{[^}]*\}/g, (m, id) => (ids.has(id) ? m : '')); + }; + const cssPayloadClean = stripUnusedIdCss(cssPayload, idsInHtml); + const htmlContent = htmlBody + ''; // 2. KRITISCH: Holt die JSON-Repräsentation des Editors let jsonProjectDataRaw = ''; try { const jsonProjectData = editor.getProjectData(); + const cleanEmptyDefaultPsJson = (node) => { + if (!node || typeof node !== 'object') return; + const walkArray = (arr, assignTo) => { + if (!Array.isArray(arr)) return; + const cleaned = []; + for (const child of arr) { + let remove = false; + if (child && child.type === 'default' && child.tagName === 'p') { + const attrs = child.attributes || {}; + const attrKeys = Object.keys(attrs); + const allowedAttrs = new Set(['id', 'draggable']); + const onlyAllowedAttrs = attrKeys.every((k) => allowedAttrs.has(k)); + const hasContent = (child.content && String(child.content).trim()) || (child.components && child.components.length); + const hasStyle = child.style && Object.keys(child.style).length > 0; + if (!hasContent && !hasStyle && onlyAllowedAttrs) { + remove = true; + } + } + if (!remove) { + cleanEmptyDefaultPsJson(child); + cleaned.push(child); + } + } + assignTo(cleaned); + }; + if (Array.isArray(node.pages)) { + walkArray(node.pages, (v) => { node.pages = v; }); + } + if (Array.isArray(node.frames)) { + walkArray(node.frames, (v) => { node.frames = v; }); + } + if (node.component && Array.isArray(node.component.components)) { + walkArray(node.component.components, (v) => { node.component.components = v; }); + } + if (Array.isArray(node.components)) { + walkArray(node.components, (v) => { node.components = v; }); + } + }; + cleanEmptyDefaultPsJson(jsonProjectData); + if (idsInHtml && idsInHtml.size && Array.isArray(jsonProjectData.styles)) { + jsonProjectData.styles = jsonProjectData.styles.filter((rule) => { + if (!rule || rule.atRuleType) return true; + const sels = Array.isArray(rule.selectors) ? rule.selectors : []; + const selAdd = rule.selectorsAdd || ''; + if (sels.length === 1 && typeof sels[0] === 'string' && sels[0].startsWith('#')) { + const id = sels[0].slice(1); + return idsInHtml.has(id); + } + if (!sels.length && typeof selAdd === 'string' && selAdd.startsWith('#')) { + const id = selAdd.slice(1); + return idsInHtml.has(id); + } + return true; + }); + } jsonProjectDataRaw = JSON.stringify(jsonProjectData); } catch (e) { console.error('[bridge-blocks-api] getProjectData stringify failed', e);