PluginProbe
Booking Calendar / 11.8.4
Booking Calendar v11.8.4
11.8.4 11.8.3 11.8.2 11.8.1 11.8 11.7 11.6.1 11.6 11.5 11.4.3 11.4.2 11.4.1 11.4 11.3 11.2.1 11.2 11.1 11.0 10.15.7 10.15.6 10.1.3 10.10 10.10.1 10.10.2 10.11 All 204 releases
booking / includes / page-form-builder / field-packs / custom-shortcode / _src / custom-shortcode.js

custom-shortcode.js in Booking Calendar 11.8.4, at includes/page-form-builder/field-packs/custom-shortcode/_src/custom-shortcode.js

268 lines 8.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 // File: /includes/page-form-builder/field-packs/custom-shortcode/custom-shortcode.js
2 ( function ( window, document ) {
3 'use strict';
4
5 var Core = window.WPBC_BFB_Core || {};
6 var registry = Core.WPBC_BFB_Field_Renderer_Registry;
7 var Base = Core.WPBC_BFB_Field_Base;
8
9 if ( ! registry || typeof registry.register !== 'function' || ! Base ) {
10 return;
11 }
12
13 /**
14 * Return translated field-pack strings with safe fallbacks.
15 *
16 * @returns {{example_shortcode:string, invalid_message:string}} Field-pack strings.
17 */
18 function wpbc_bfb_custom_shortcode_get_boot() {
19 var boot = window.WPBC_BFB_Custom_Shortcode_Boot || {};
20
21 return {
22 example_shortcode : String( boot.example_shortcode || '[field_name_hint]' ),
23 invalid_message : String( boot.invalid_message || 'Enter one complete shortcode, for example [field_name_hint] or [coupon discount ""].' )
24 };
25 }
26
27 /**
28 * Normalize one bracketed Booking Calendar shortcode.
29 *
30 * The token may contain space-separated options and balanced single- or
31 * double-quoted values. Control characters, HTML delimiters, nested brackets,
32 * multiple tokens, unbalanced quotes, and excessive input are rejected before
33 * the value can reach the Advanced Booking Form exporter.
34 *
35 * @param {*} shortcode_value Candidate value from Builder field data.
36 *
37 * @returns {string} Trimmed token when valid, otherwise an empty string.
38 */
39 function wpbc_bfb_custom_shortcode_normalize( shortcode_value ) {
40 var shortcode = String( shortcode_value == null ? '' : shortcode_value ).trim();
41 var shortcode_body;
42 var shortcode_name_end;
43 var shortcode_name;
44 var active_quote = '';
45 var character;
46 var index;
47
48 if (
49 shortcode.length < 3 ||
50 shortcode.length > 1000 ||
51 '[' !== shortcode.charAt( 0 ) ||
52 ']' !== shortcode.charAt( shortcode.length - 1 )
53 ) {
54 return '';
55 }
56
57 shortcode_body = shortcode.slice( 1, -1 ).trim();
58
59 if ( ! shortcode_body || /[\u0000-\u001F\u007F<>\[\]]/.test( shortcode_body ) ) {
60 return '';
61 }
62
63 shortcode_name_end = shortcode_body.indexOf( ' ' );
64 shortcode_name = -1 === shortcode_name_end
65 ? shortcode_body
66 : shortcode_body.slice( 0, shortcode_name_end );
67
68 if ( ! /^[A-Za-z0-9_.*-]+$/.test( shortcode_name ) ) {
69 return '';
70 }
71
72 for ( index = shortcode_name.length; index < shortcode_body.length; index++ ) {
73 character = shortcode_body.charAt( index );
74
75 if ( active_quote ) {
76 if ( character === active_quote ) {
77 active_quote = '';
78 }
79 continue;
80 }
81
82 if ( '"' === character || "'" === character ) {
83 active_quote = character;
84 }
85 }
86
87 return active_quote ? '' : '[' + shortcode_body + ']';
88 }
89
90 /**
91 * Escape preview text when the shared sanitizer is unexpectedly unavailable.
92 *
93 * @param {*} raw_value Preview value.
94 *
95 * @returns {string} HTML-safe preview value.
96 */
97 function wpbc_bfb_custom_shortcode_escape_html( raw_value ) {
98 return String( raw_value )
99 .replace( /&/g, '&amp;' )
100 .replace( /</g, '&lt;' )
101 .replace( />/g, '&gt;' )
102 .replace( /"/g, '&quot;' )
103 .replace( /'/g, '&#039;' );
104 }
105
106 /**
107 * Render and export one validated custom shortcode token.
108 */
109 class WPBC_BFB_Field_Custom_Shortcode extends Base {
110
111 /**
112 * Return defaults kept in sync with the PHP schema.
113 *
114 * @returns {{type:string, shortcode:string, usage_key:string}} Field defaults.
115 */
116 static get_defaults() {
117 return {
118 type : 'custom_shortcode',
119 shortcode : '[field_name_hint]',
120 usage_key : 'custom_shortcode'
121 };
122 }
123
124 /**
125 * Render an inert and escaped Builder preview.
126 *
127 * The raw draft remains in `data-shortcode` while the preview and exporter
128 * use only a validated token. This lets the author finish typing without
129 * silently replacing an incomplete draft with the example value.
130 *
131 * @param {HTMLElement} el Builder field element.
132 * @param {Object} data Field properties.
133 * @param {Object} ctx Builder context.
134 *
135 * @returns {void}
136 */
137 static render( el, data, ctx ) {
138 var field_data;
139 var raw_shortcode;
140 var shortcode;
141 var boot;
142 var display_shortcode;
143 var invalid_html;
144 var escape_html;
145
146 if ( ! el ) {
147 return;
148 }
149
150 field_data = this.normalize_data( data );
151 raw_shortcode = String( field_data.shortcode || '' ).trim();
152 shortcode = wpbc_bfb_custom_shortcode_normalize( raw_shortcode );
153 boot = wpbc_bfb_custom_shortcode_get_boot();
154 display_shortcode = raw_shortcode || boot.example_shortcode;
155 escape_html = Core.WPBC_BFB_Sanitize && Core.WPBC_BFB_Sanitize.escape_html
156 ? Core.WPBC_BFB_Sanitize.escape_html
157 : wpbc_bfb_custom_shortcode_escape_html;
158 invalid_html = shortcode
159 ? ''
160 : '<span class="wpbc_bfb__help" role="alert">' + escape_html( boot.invalid_message ) + '</span>';
161
162 el.dataset.shortcode = raw_shortcode;
163 el.innerHTML =
164 '<span class="wpbc_bfb__noaction wpbc_bfb__no-drag-zone" inert="">' +
165 '<code class="wpbc_bfb__custom-shortcode-preview">' + escape_html( display_shortcode ) + '</code>' +
166 '</span>' +
167 invalid_html;
168
169 if ( Core.UI && Core.UI.WPBC_BFB_Overlay && typeof Core.UI.WPBC_BFB_Overlay.ensure === 'function' ) {
170 Core.UI.WPBC_BFB_Overlay.ensure( ctx && ctx.builder, el );
171 }
172 }
173
174 /**
175 * Preserve the standard Builder post-drop behavior.
176 *
177 * @param {Object} data Field properties.
178 * @param {HTMLElement} el Builder field element.
179 * @param {Object} ctx Builder context.
180 *
181 * @returns {void}
182 */
183 static on_field_drop( data, el, ctx ) {
184 if ( typeof super.on_field_drop === 'function' ) {
185 super.on_field_drop( data, el, ctx );
186 }
187 }
188 }
189
190 registry.register( 'custom_shortcode', WPBC_BFB_Field_Custom_Shortcode );
191
192 /**
193 * Export one validated token to the Advanced Booking Form.
194 *
195 * @param {Object} field Field data from the Builder structure.
196 * @param {Function} emit Exporter output callback.
197 *
198 * @returns {void}
199 */
200 function wpbc_bfb_export_custom_shortcode_to_form( field, emit ) {
201 var shortcode = wpbc_bfb_custom_shortcode_normalize( field && field.shortcode );
202
203 if ( shortcode ) {
204 emit( shortcode );
205 }
206 }
207
208 /**
209 * Register the Advanced Booking Form exporter.
210 *
211 * @returns {void}
212 */
213 function wpbc_bfb_register_custom_shortcode_form_exporter() {
214 var Exporter = window.WPBC_BFB_Exporter;
215
216 if ( ! Exporter || typeof Exporter.register !== 'function' ) {
217 return;
218 }
219 if ( typeof Exporter.has_exporter === 'function' && Exporter.has_exporter( 'custom_shortcode' ) ) {
220 return;
221 }
222
223 Exporter.register( 'custom_shortcode', wpbc_bfb_export_custom_shortcode_to_form );
224 }
225
226 if ( window.WPBC_BFB_Exporter && typeof window.WPBC_BFB_Exporter.register === 'function' ) {
227 wpbc_bfb_register_custom_shortcode_form_exporter();
228 } else if ( document && typeof document.addEventListener === 'function' ) {
229 document.addEventListener( 'wpbc:bfb:exporter-ready', wpbc_bfb_register_custom_shortcode_form_exporter, { once: true } );
230 }
231
232 /**
233 * Omit the custom token from submitted Booking Data output.
234 *
235 * @returns {void}
236 */
237 function wpbc_bfb_omit_custom_shortcode_from_content() {
238 return;
239 }
240
241 /**
242 * Register an empty Booking Data exporter.
243 *
244 * The field pack modifies only the Advanced Booking Form. It cannot infer the
245 * correct Booking Data representation for arbitrary display or input tokens.
246 *
247 * @returns {void}
248 */
249 function wpbc_bfb_register_custom_shortcode_content_exporter() {
250 var Exporter = window.WPBC_BFB_ContentExporter;
251
252 if ( ! Exporter || typeof Exporter.register !== 'function' ) {
253 return;
254 }
255 if ( typeof Exporter.has_exporter === 'function' && Exporter.has_exporter( 'custom_shortcode' ) ) {
256 return;
257 }
258
259 Exporter.register( 'custom_shortcode', wpbc_bfb_omit_custom_shortcode_from_content );
260 }
261
262 if ( window.WPBC_BFB_ContentExporter && typeof window.WPBC_BFB_ContentExporter.register === 'function' ) {
263 wpbc_bfb_register_custom_shortcode_content_exporter();
264 } else if ( document && typeof document.addEventListener === 'function' ) {
265 document.addEventListener( 'wpbc:bfb:content-exporter-ready', wpbc_bfb_register_custom_shortcode_content_exporter, { once: true } );
266 }
267 } )( window, document );
268