// File: /includes/page-form-builder/field-packs/custom-shortcode/custom-shortcode.js
( function ( window, document ) {
'use strict';
var Core = window.WPBC_BFB_Core || {};
var registry = Core.WPBC_BFB_Field_Renderer_Registry;
var Base = Core.WPBC_BFB_Field_Base;
if ( ! registry || typeof registry.register !== 'function' || ! Base ) {
return;
}
/**
* Return translated field-pack strings with safe fallbacks.
*
* @returns {{example_shortcode:string, invalid_message:string}} Field-pack strings.
*/
function wpbc_bfb_custom_shortcode_get_boot() {
var boot = window.WPBC_BFB_Custom_Shortcode_Boot || {};
return {
example_shortcode : String( boot.example_shortcode || '[field_name_hint]' ),
invalid_message : String( boot.invalid_message || 'Enter one complete shortcode, for example [field_name_hint] or [coupon discount ""].' )
};
}
/**
* Normalize one bracketed Booking Calendar shortcode.
*
* The token may contain space-separated options and balanced single- or
* double-quoted values. Control characters, HTML delimiters, nested brackets,
* multiple tokens, unbalanced quotes, and excessive input are rejected before
* the value can reach the Advanced Booking Form exporter.
*
* @param {*} shortcode_value Candidate value from Builder field data.
*
* @returns {string} Trimmed token when valid, otherwise an empty string.
*/
function wpbc_bfb_custom_shortcode_normalize( shortcode_value ) {
var shortcode = String( shortcode_value == null ? '' : shortcode_value ).trim();
var shortcode_body;
var shortcode_name_end;
var shortcode_name;
var active_quote = '';
var character;
var index;
if (
shortcode.length < 3 ||
shortcode.length > 1000 ||
'[' !== shortcode.charAt( 0 ) ||
']' !== shortcode.charAt( shortcode.length - 1 )
) {
return '';
}
shortcode_body = shortcode.slice( 1, -1 ).trim();
if ( ! shortcode_body || /[\u0000-\u001F\u007F<>\[\]]/.test( shortcode_body ) ) {
return '';
}
shortcode_name_end = shortcode_body.indexOf( ' ' );
shortcode_name = -1 === shortcode_name_end
? shortcode_body
: shortcode_body.slice( 0, shortcode_name_end );
if ( ! /^[A-Za-z0-9_.*-]+$/.test( shortcode_name ) ) {
return '';
}
for ( index = shortcode_name.length; index < shortcode_body.length; index++ ) {
character = shortcode_body.charAt( index );
if ( active_quote ) {
if ( character === active_quote ) {
active_quote = '';
}
continue;
}
if ( '"' === character || "'" === character ) {
active_quote = character;
}
}
return active_quote ? '' : '[' + shortcode_body + ']';
}
/**
* Escape preview text when the shared sanitizer is unexpectedly unavailable.
*
* @param {*} raw_value Preview value.
*
* @returns {string} HTML-safe preview value.
*/
function wpbc_bfb_custom_shortcode_escape_html( raw_value ) {
return String( raw_value )
.replace( /&/g, '&' )
.replace( //g, '>' )
.replace( /"/g, '"' )
.replace( /'/g, ''' );
}
/**
* Render and export one validated custom shortcode token.
*/
class WPBC_BFB_Field_Custom_Shortcode extends Base {
/**
* Return defaults kept in sync with the PHP schema.
*
* @returns {{type:string, shortcode:string, usage_key:string}} Field defaults.
*/
static get_defaults() {
return {
type : 'custom_shortcode',
shortcode : '[field_name_hint]',
usage_key : 'custom_shortcode'
};
}
/**
* Render an inert and escaped Builder preview.
*
* The raw draft remains in `data-shortcode` while the preview and exporter
* use only a validated token. This lets the author finish typing without
* silently replacing an incomplete draft with the example value.
*
* @param {HTMLElement} el Builder field element.
* @param {Object} data Field properties.
* @param {Object} ctx Builder context.
*
* @returns {void}
*/
static render( el, data, ctx ) {
var field_data;
var raw_shortcode;
var shortcode;
var boot;
var display_shortcode;
var invalid_html;
var escape_html;
if ( ! el ) {
return;
}
field_data = this.normalize_data( data );
raw_shortcode = String( field_data.shortcode || '' ).trim();
shortcode = wpbc_bfb_custom_shortcode_normalize( raw_shortcode );
boot = wpbc_bfb_custom_shortcode_get_boot();
display_shortcode = raw_shortcode || boot.example_shortcode;
escape_html = Core.WPBC_BFB_Sanitize && Core.WPBC_BFB_Sanitize.escape_html
? Core.WPBC_BFB_Sanitize.escape_html
: wpbc_bfb_custom_shortcode_escape_html;
invalid_html = shortcode
? ''
: '' + escape_html( boot.invalid_message ) + '';
el.dataset.shortcode = raw_shortcode;
el.innerHTML =
'' +
'' + escape_html( display_shortcode ) + '' +
'' +
invalid_html;
if ( Core.UI && Core.UI.WPBC_BFB_Overlay && typeof Core.UI.WPBC_BFB_Overlay.ensure === 'function' ) {
Core.UI.WPBC_BFB_Overlay.ensure( ctx && ctx.builder, el );
}
}
/**
* Preserve the standard Builder post-drop behavior.
*
* @param {Object} data Field properties.
* @param {HTMLElement} el Builder field element.
* @param {Object} ctx Builder context.
*
* @returns {void}
*/
static on_field_drop( data, el, ctx ) {
if ( typeof super.on_field_drop === 'function' ) {
super.on_field_drop( data, el, ctx );
}
}
}
registry.register( 'custom_shortcode', WPBC_BFB_Field_Custom_Shortcode );
/**
* Export one validated token to the Advanced Booking Form.
*
* @param {Object} field Field data from the Builder structure.
* @param {Function} emit Exporter output callback.
*
* @returns {void}
*/
function wpbc_bfb_export_custom_shortcode_to_form( field, emit ) {
var shortcode = wpbc_bfb_custom_shortcode_normalize( field && field.shortcode );
if ( shortcode ) {
emit( shortcode );
}
}
/**
* Register the Advanced Booking Form exporter.
*
* @returns {void}
*/
function wpbc_bfb_register_custom_shortcode_form_exporter() {
var Exporter = window.WPBC_BFB_Exporter;
if ( ! Exporter || typeof Exporter.register !== 'function' ) {
return;
}
if ( typeof Exporter.has_exporter === 'function' && Exporter.has_exporter( 'custom_shortcode' ) ) {
return;
}
Exporter.register( 'custom_shortcode', wpbc_bfb_export_custom_shortcode_to_form );
}
if ( window.WPBC_BFB_Exporter && typeof window.WPBC_BFB_Exporter.register === 'function' ) {
wpbc_bfb_register_custom_shortcode_form_exporter();
} else if ( document && typeof document.addEventListener === 'function' ) {
document.addEventListener( 'wpbc:bfb:exporter-ready', wpbc_bfb_register_custom_shortcode_form_exporter, { once: true } );
}
/**
* Omit the custom token from submitted Booking Data output.
*
* @returns {void}
*/
function wpbc_bfb_omit_custom_shortcode_from_content() {
return;
}
/**
* Register an empty Booking Data exporter.
*
* The field pack modifies only the Advanced Booking Form. It cannot infer the
* correct Booking Data representation for arbitrary display or input tokens.
*
* @returns {void}
*/
function wpbc_bfb_register_custom_shortcode_content_exporter() {
var Exporter = window.WPBC_BFB_ContentExporter;
if ( ! Exporter || typeof Exporter.register !== 'function' ) {
return;
}
if ( typeof Exporter.has_exporter === 'function' && Exporter.has_exporter( 'custom_shortcode' ) ) {
return;
}
Exporter.register( 'custom_shortcode', wpbc_bfb_omit_custom_shortcode_from_content );
}
if ( window.WPBC_BFB_ContentExporter && typeof window.WPBC_BFB_ContentExporter.register === 'function' ) {
wpbc_bfb_register_custom_shortcode_content_exporter();
} else if ( document && typeof document.addEventListener === 'function' ) {
document.addEventListener( 'wpbc:bfb:content-exporter-ready', wpbc_bfb_register_custom_shortcode_content_exporter, { once: true } );
}
} )( window, document );