← All changes
|
includes/page-form-builder/_src/export/builder-exporter.js
+120
-36
11.0
→
11.9
View file →
| @@ -1,4 +1,4 @@ | ||
| 1 | 1 | /** |
| 2 | 2 | * @file: ../includes/page-form-builder/_out/export/builder-exporter.js |
| 3 | 3 | */ |
| 4 | 4 | (function () { |
| @@ -47,16 +47,64 @@ | ||
| 47 | 47 | } |
| 48 | 48 | return out; |
| 49 | 49 | } |
| 50 | 50 | |
| 51 | - // == Helpers – column styles parsing & CSS vars builder =========================================================== | |
| 52 | - | |
| 53 | - // Known keys we treat as real per-column style overrides. | |
| 51 | + // == Helpers – column styles parsing & CSS vars builder =========================================================== | |
| 52 | + var wpbc_column_overflow_values = [ 'visible', 'auto', 'hidden' ]; | |
| 53 | + | |
| 54 | + /** | |
| 55 | + * Constrain a column spacing length to units supported by the Inspector. | |
| 56 | + * | |
| 57 | + * @param {*} candidate_value Saved column-style value. | |
| 58 | + * @returns {string} Valid non-negative CSS length or `0px`. | |
| 59 | + */ | |
| 60 | + function normalize_column_length( candidate_value ) { | |
| 61 | + var normalized_value = String( candidate_value == null ? '' : candidate_value ).trim(); | |
| 62 | + if ( /^\d+(\.\d+)?$/.test( normalized_value ) ) { | |
| 63 | + return normalized_value + 'px'; | |
| 64 | + } | |
| 65 | + return /^\d+(\.\d+)?(px|rem|em|%)$/.test( normalized_value ) ? normalized_value : '0px'; | |
| 66 | + } | |
| 67 | + | |
| 68 | + /** | |
| 69 | + * Constrain an optional column maximum dimension. | |
| 70 | + * | |
| 71 | + * @param {*} candidate_value Saved column-style value. | |
| 72 | + * @returns {string} Valid maximum dimension or `none`. | |
| 73 | + */ | |
| 74 | + function normalize_column_maximum( candidate_value ) { | |
| 75 | + var normalized_value = String( candidate_value == null ? '' : candidate_value ).trim(); | |
| 76 | + if ( ! normalized_value || 'none' === normalized_value ) { | |
| 77 | + return 'none'; | |
| 78 | + } | |
| 79 | + if ( /^\d+(\.\d+)?$/.test( normalized_value ) ) { | |
| 80 | + return normalized_value + 'px'; | |
| 81 | + } | |
| 82 | + return /^\d+(\.\d+)?(px|rem|em|%|vh|vw)$/.test( normalized_value ) ? normalized_value : 'none'; | |
| 83 | + } | |
| 84 | + | |
| 85 | + /** | |
| 86 | + * Constrain column overflow to the Inspector allowlist. | |
| 87 | + * | |
| 88 | + * @param {*} candidate_value Saved column-style value. | |
| 89 | + * @returns {string} Allowlisted overflow value. | |
| 90 | + */ | |
| 91 | + function normalize_column_overflow( candidate_value ) { | |
| 92 | + var normalized_value = String( candidate_value || '' ); | |
| 93 | + return wpbc_column_overflow_values.indexOf( normalized_value ) !== -1 ? normalized_value : wpbc_column_overflow_values[0]; | |
| 94 | + } | |
| 95 | + | |
| 96 | + // Known keys we treat as real per-column style overrides. | |
| 54 | 97 | function has_non_default_col_styles(obj) { |
| 55 | 98 | if ( !obj || typeof obj !== 'object' ) { |
| 56 | 99 | return false; |
| 57 | 100 | } |
| 58 | - var keys = [ 'dir', 'wrap', 'jc', 'ai', 'gap', 'aself', 'ac' ]; | |
| 101 | + var keys = [ | |
| 102 | + 'dir', 'wrap', 'jc', 'ai', 'gap', 'padding', 'margin', | |
| 103 | + 'padding_top', 'padding_right', 'padding_bottom', 'padding_left', | |
| 104 | + 'margin_top', 'margin_right', 'margin_bottom', 'margin_left', | |
| 105 | + 'max_width', 'max_height', 'overflow', 'overflow_x', 'overflow_y', 'aself', 'ac' | |
| 106 | + ]; | |
| 59 | 107 | for ( var i = 0; i < keys.length; i++ ) { |
| 60 | 108 | var k = keys[i]; |
| 61 | 109 | if ( obj[k] != null && String( obj[k] ).trim() !== '' ) { |
| 62 | 110 | return true; |
| @@ -97,10 +145,19 @@ | ||
| 97 | 145 | * - dir -> --wpbc-bfb-col-dir |
| 98 | 146 | * - wrap -> --wpbc-bfb-col-wrap |
| 99 | 147 | * - jc -> --wpbc-bfb-col-jc |
| 100 | 148 | * - ai -> --wpbc-bfb-col-ai |
| 101 | - * - gap -> --wpbc-bfb-col-gap | |
| 102 | - * - ac -> --wpbc-bfb-col-ac | |
| 149 | + * - gap -> --wpbc-bfb-col-gap | |
| 150 | + * - padding -> --wpbc-bfb-col-padding | |
| 151 | + * - margin -> --wpbc-bfb-col-margin | |
| 152 | + * - padding_top/right/bottom/left -> --wpbc-bfb-col-padding-* | |
| 153 | + * - margin_top/right/bottom/left -> --wpbc-bfb-col-margin-* | |
| 154 | + * - max_width -> --wpbc-bfb-col-max-width | |
| 155 | + * - max_height -> --wpbc-bfb-col-max-height | |
| 156 | + * - overflow -> --wpbc-bfb-col-overflow | |
| 157 | + * - overflow_x -> --wpbc-bfb-col-overflow-x | |
| 158 | + * - overflow_y -> --wpbc-bfb-col-overflow-y | |
| 159 | + * - ac -> --wpbc-bfb-col-ac | |
| 103 | 160 | * - aself-> --wpbc-bfb-col-aself |
| 104 | 161 | * |
| 105 | 162 | * Unknown keys are exported as `--wpbc-bfb-col-${key}`. |
| 106 | 163 | * |
| @@ -114,21 +171,45 @@ | ||
| 114 | 171 | dir : '--wpbc-bfb-col-dir', |
| 115 | 172 | wrap : '--wpbc-bfb-col-wrap', |
| 116 | 173 | jc : '--wpbc-bfb-col-jc', |
| 117 | 174 | ai : '--wpbc-bfb-col-ai', |
| 118 | - gap : '--wpbc-bfb-col-gap', | |
| 119 | - ac : '--wpbc-bfb-col-ac', | |
| 175 | + gap : '--wpbc-bfb-col-gap', | |
| 176 | + padding: '--wpbc-bfb-col-padding', | |
| 177 | + margin : '--wpbc-bfb-col-margin', | |
| 178 | + padding_top : '--wpbc-bfb-col-padding-top', | |
| 179 | + padding_right : '--wpbc-bfb-col-padding-right', | |
| 180 | + padding_bottom: '--wpbc-bfb-col-padding-bottom', | |
| 181 | + padding_left : '--wpbc-bfb-col-padding-left', | |
| 182 | + margin_top : '--wpbc-bfb-col-margin-top', | |
| 183 | + margin_right : '--wpbc-bfb-col-margin-right', | |
| 184 | + margin_bottom : '--wpbc-bfb-col-margin-bottom', | |
| 185 | + margin_left : '--wpbc-bfb-col-margin-left', | |
| 186 | + max_width : '--wpbc-bfb-col-max-width', | |
| 187 | + max_height : '--wpbc-bfb-col-max-height', | |
| 188 | + overflow : '--wpbc-bfb-col-overflow', | |
| 189 | + overflow_x : '--wpbc-bfb-col-overflow-x', | |
| 190 | + overflow_y : '--wpbc-bfb-col-overflow-y', | |
| 191 | + ac : '--wpbc-bfb-col-ac', | |
| 120 | 192 | aself: '--wpbc-bfb-col-aself' |
| 121 | 193 | }; |
| 122 | 194 | |
| 123 | 195 | var parts = []; |
| 124 | 196 | |
| 125 | - for ( var k in obj ) { | |
| 126 | - if ( !Object.prototype.hasOwnProperty.call( obj, k ) ) continue; | |
| 127 | - var v = obj[k]; | |
| 128 | - if ( v == null || v === '' ) continue; | |
| 129 | - | |
| 130 | - var var_name = map[k] || ('--wpbc-bfb-col-' + String( k ).replace( /[^a-z0-9_-]/gi, '' ).toLowerCase()); | |
| 197 | + for ( var k in obj ) { | |
| 198 | + if ( !Object.prototype.hasOwnProperty.call( obj, k ) ) continue; | |
| 199 | + // Ignore the removed experimental child-flex setting in previously saved Builder JSON. | |
| 200 | + if ( 'item_flex' === k ) continue; | |
| 201 | + var v = obj[k]; | |
| 202 | + if ( v == null || v === '' ) continue; | |
| 203 | + if ( [ 'padding_top', 'padding_right', 'padding_bottom', 'padding_left', 'margin_top', 'margin_right', 'margin_bottom', 'margin_left' ].indexOf( k ) !== -1 ) { | |
| 204 | + v = normalize_column_length( v ); | |
| 205 | + } else if ( 'max_width' === k || 'max_height' === k ) { | |
| 206 | + v = normalize_column_maximum( v ); | |
| 207 | + } else if ( [ 'overflow', 'overflow_x', 'overflow_y' ].indexOf( k ) !== -1 ) { | |
| 208 | + v = normalize_column_overflow( v ); | |
| 209 | + } | |
| 210 | + | |
| 211 | + var var_name = map[k] || ('--wpbc-bfb-col-' + String( k ).replace( /[^a-z0-9_-]/gi, '' ).toLowerCase()); | |
| 131 | 212 | parts.push( var_name + ': ' + String( v ) ); |
| 132 | 213 | } |
| 133 | 214 | |
| 134 | 215 | // Always include explicit min guard (requested): --wpbc-col-min: 0px; |
| @@ -216,11 +297,13 @@ | ||
| 216 | 297 | // ================================================================================================= |
| 217 | 298 | const walk_section = (sec) => { |
| 218 | 299 | const section_col_styles = parse_col_styles_json( sec && sec.col_styles ); |
| 219 | 300 | |
| 220 | - return { | |
| 221 | - id : sec?.id, | |
| 222 | - columns: (sec?.columns || []).map( (col, col_index) => { | |
| 301 | + return { | |
| 302 | + id : sec?.id, | |
| 303 | + html_id : sec?.html_id || '', | |
| 304 | + cssclass : sec?.cssclass || '', | |
| 305 | + columns : (sec?.columns || []).map( (col, col_index) => { | |
| 223 | 306 | const items = Array.isArray( col?.items ) |
| 224 | 307 | ? col.items |
| 225 | 308 | : [ |
| 226 | 309 | ...(col?.fields || []).map( (f) => ({ type: 'field', data: f }) ), |
| @@ -460,13 +543,14 @@ | ||
| 460 | 543 | ? section.columns |
| 461 | 544 | : [ { width: '100%', fields: [], sections: [] } ]; |
| 462 | 545 | |
| 463 | 546 | // Row is active if ANY column carries styles. |
| 464 | - var row_is_active = cols.some( function (col) { return has_non_default_col_styles( col && col.col_styles ); } ); | |
| 465 | - var row_attr_active = row_is_active ? ' data-colstyles-active="1"' : ''; | |
| 547 | + var row_is_active = cols.some( function (col) { return has_non_default_col_styles( col && col.col_styles ); } ); | |
| 548 | + var row_attr_active = row_is_active ? ' data-colstyles-active="1"' : ''; | |
| 549 | + var row_custom_attrs = WPBC_BFB_Exporter.item_wrapper_attrs( section, ctx ); | |
| 550 | + | |
| 551 | + open( `<r${row_custom_attrs}${row_attr_active}>` ); | |
| 466 | 552 | |
| 467 | - open( `<r${row_attr_active}>` ); | |
| 468 | - | |
| 469 | 553 | const bases = compute_effective_bases( cols, cfg.gapPercent ); |
| 470 | 554 | const esc_attr = core.WPBC_BFB_Sanitize.escape_html; |
| 471 | 555 | |
| 472 | 556 | cols.forEach( (col, idx) => { |
| @@ -511,20 +595,20 @@ | ||
| 511 | 595 | } |
| 512 | 596 | |
| 513 | 597 | |
| 514 | 598 | /** |
| 515 | - * Build attribute string for the <item> wrapper. | |
| 516 | - * Currently only used for CAPTCHA: pushes css classes and html_id to the wrapper. | |
| 517 | - * Also ensures uniqueness of the html_id across the export (uses ctx.usedIds). | |
| 518 | - * | |
| 519 | - * @param {Object} field | |
| 520 | - * @param {{usedIds:Set<string>}} ctx | |
| 521 | - * @returns {string} e.g. ' class="x y" id="myId"' | |
| 522 | - */ | |
| 523 | - static item_wrapper_attrs(field, ctx) { | |
| 524 | - if ( ! field ) { | |
| 525 | - return ''; | |
| 526 | - } | |
| 599 | + * Build a sanitized custom CSS class and HTML ID attribute string for an exported wrapper. | |
| 600 | + * Used by section row wrappers and fields whose attributes belong on the <item> wrapper. | |
| 601 | + * Also ensures uniqueness of the html_id across the export (uses ctx.usedIds). | |
| 602 | + * | |
| 603 | + * @param {Object} wrapper_data Object containing optional cssclass and html_id properties. | |
| 604 | + * @param {{usedIds:Set<string>}} ctx | |
| 605 | + * @returns {string} e.g. ' class="x y" id="myId"' | |
| 606 | + */ | |
| 607 | + static item_wrapper_attrs(wrapper_data, ctx) { | |
| 608 | + if ( ! wrapper_data ) { | |
| 609 | + return ''; | |
| 610 | + } | |
| 527 | 611 | const esc_html = core.WPBC_BFB_Sanitize.escape_html; |
| 528 | 612 | const cls_sanit = core.WPBC_BFB_Sanitize.sanitize_css_classlist; |
| 529 | 613 | const sid = core.WPBC_BFB_Sanitize.sanitize_html_id; |
| 530 | 614 | |
| @@ -529,11 +613,11 @@ | ||
| 529 | 613 | const sid = core.WPBC_BFB_Sanitize.sanitize_html_id; |
| 530 | 614 | |
| 531 | 615 | let out = ''; |
| 532 | 616 | |
| 533 | - const cls_raw = String( field.cssclass_extra || field.cssclass || field.class || '' ); | |
| 534 | - const cls = cls_sanit( cls_raw ); | |
| 535 | - let html_id = field.html_id ? sid( String( field.html_id ) ) : ''; | |
| 617 | + const cls_raw = String( wrapper_data.cssclass_extra || wrapper_data.cssclass || wrapper_data.class || '' ); | |
| 618 | + const cls = cls_sanit( cls_raw ); | |
| 619 | + let html_id = wrapper_data.html_id ? sid( String( wrapper_data.html_id ) ) : ''; | |
| 536 | 620 | if ( html_id && ctx?.usedIds ) { |
| 537 | 621 | let unique = html_id, i = 2; |
| 538 | 622 | while ( ctx.usedIds.has( unique ) ) { |
| 539 | 623 | unique = `${html_id}_${i++}`; |