PluginProbe
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages / 3.4.4
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages v3.4.4
3.4.4 3.4.3 3.4.2 3.4.1 3.4.0 3.3.9 3.3.8 3.3.7 3.3.6 3.3.5 3.3.4 3.3.3 3.3.2 3.3.1 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.2.7 2.2.8 2.2.9 2.3.0 All 197 releases
← All changes | resources/backend/js/gutenberg-block-formatters.js +156 -188 2.2.8 → 3.4.4 View file →
@@ -2,23 +2,25 @@
2 2 * Registers formatters in the Block Toolbar in the Gutenberg editor.
3 3 *
4 4 * @since 2.2.0
5 5 *
6 - * @package ConvertKit
7 6 * @author ConvertKit
8 7 */
9 8
9 +/**
10 + * @typedef {import('@wordpress/element').WPElement} WPElement
11 + */
12 +
10 13 // Register Gutenberg Block Toolbar formatters if the Gutenberg Editor is loaded on screen.
11 14 // This prevents JS errors if this script is accidentally enqueued on a non-
12 15 // Gutenberg editor screen, or the Classic Editor Plugin is active.
13 -if ( typeof wp !== 'undefined' &&
14 - typeof wp.blocks !== 'undefined' ) {
15 -
16 +if (convertKitGutenbergEnabled()) {
16 17 // Register each ConvertKit formatter in Gutenberg.
17 - for ( const formatter in convertkit_block_formatters ) {
18 - convertKitGutenbergRegisterBlockFormatter( convertkit_block_formatters[ formatter ] );
18 + for (const formatter in convertkit_block_formatters) {
19 + convertKitGutenbergRegisterBlockFormatter(
20 + convertkit_block_formatters[formatter]
21 + );
19 22 }
20 -
21 23 }
22 24
23 25 /**
24 26 * Registers the given formatter in Gutenberg.
@@ -24,36 +26,23 @@
24 26 * Registers the given formatter in Gutenberg.
25 27 *
26 28 * @since 2.2.0
27 29 *
28 - * @param object formatter Block formatter.
30 + * @param {Object} formatter Block formatter.
29 31 */
30 -function convertKitGutenbergRegisterBlockFormatter( formatter ) {
31 -
32 - ( function( editor, richText, element, components ) {
33 -
32 +function convertKitGutenbergRegisterBlockFormatter(formatter) {
33 + (function (editor, richText, element, components) {
34 34 // Define the Gutenberg/React components to use.
35 + const { Fragment, useState, createElement } = element;
35 36 const {
36 - Fragment,
37 - useState,
38 - createElement
39 - } = element;
40 - const {
41 37 registerFormatType,
42 38 toggleFormat,
43 39 applyFormat,
44 40 useAnchorRef,
45 - useAnchor
41 + useAnchor,
46 42 } = richText;
47 - const {
48 - BlockControls,
49 - RichTextToolbarButton,
50 - } = editor;
51 - const {
52 - Button,
53 - Popover,
54 - SelectControl
55 - } = components;
43 + const { RichTextToolbarButton } = editor;
44 + const { Popover, SelectControl } = components;
56 45
57 46 /**
58 47 * Returns the icon to display in the block toolbar for this formatter, depending
59 48 * on the supplied formatter's configuration.
@@ -59,31 +48,27 @@
59 48 * on the supplied formatter's configuration.
60 49 *
61 50 * @since 2.2.0
62 51 *
63 - * @return element|string
52 + * @return {WPElement|string} Either a WordPress element (RawHTML) or a dashicon string.
64 53 */
65 - const getIcon = function() {
66 -
54 + const getIcon = function () {
67 55 // Return a fallback default icon if none is specified for this block formatter.
68 - if ( typeof formatter.gutenberg_icon === 'undefined' ) {
56 + if (typeof formatter.gutenberg_icon === 'undefined') {
69 57 return 'dashicons-tablet';
70 58 }
71 59
72 60 // Return HTML element if the icon is an SVG string.
73 - if ( formatter.gutenberg_icon.search( 'svg' ) >= 0 ) {
74 - return element.RawHTML(
75 - {
76 - children: formatter.gutenberg_icon
77 - }
78 - );
61 + if (formatter.gutenberg_icon.search('svg') >= 0) {
62 + return element.RawHTML({
63 + children: formatter.gutenberg_icon,
64 + });
79 65 }
80 66
81 67 // Just return the string, as it's a dashicon CSS class.
82 68 return formatter.gutenberg_icon;
69 + };
83 70
84 - }
85 -
86 71 /**
87 72 * Returns an object of this formatter's attributes if this formatter
88 73 * has been used on the selected text.
89 74 *
@@ -91,44 +76,45 @@
91 76 * selected text.
92 77 *
93 78 * @since 2.2.0
94 79 *
95 - * @param object activeFormats All active formatters applied to the selected text.
96 - * @return object
80 + * @param {Object} activeFormats All active formatters applied to the selected text.
81 + * @return {Object} Attributes.
97 82 */
98 - const getAttributes = function( activeFormats ) {
99 -
83 + const getAttributes = function (activeFormats) {
100 84 // Define the attribute object.
101 - let attributes = {};
102 - for ( let attribute in formatter.attributes ) {
103 - attributes[ attribute ] = '';
85 + const attributes = {};
86 + for (const attribute in formatter.attributes) {
87 + attributes[attribute] = '';
104 88 }
105 89
106 90 // Return if no active formats have been applied to the selected text.
107 - if ( typeof activeFormats === 'undefined' ) {
91 + if (typeof activeFormats === 'undefined') {
108 92 return attributes;
109 93 }
110 94
111 95 // Return if this formatter has not been used on the selected text.
112 - const formats = activeFormats.filter( format => 'convertkit/' + formatter.name === format['type'] );
113 - if ( formats.length === 0 ) {
96 + const formats = activeFormats.filter(
97 + (format) => 'convertkit/' + formatter.name === format.type
98 + );
99 + if (formats.length === 0) {
114 100 return attributes;
115 101 }
116 102
117 103 // This formatter has been applied to the selected text.
118 104 // Build the object of attributes and return.
119 - for ( let attribute in formatter.attributes ) {
120 - if ( typeof formats[0].unregisteredAttributes !== 'undefined' ) {
121 - attributes[ attribute ] = formats[0].unregisteredAttributes[ attribute ];
122 - } else if ( typeof formats[0].attributes !== 'undefined' ) {
123 - attributes[ attribute ] = formats[0].attributes[ attribute ];
105 + for (const attribute in formatter.attributes) {
106 + if (typeof formats[0].unregisteredAttributes !== 'undefined') {
107 + attributes[attribute] =
108 + formats[0].unregisteredAttributes[attribute];
109 + } else if (typeof formats[0].attributes !== 'undefined') {
110 + attributes[attribute] = formats[0].attributes[attribute];
124 111 }
125 112 }
126 113
127 114 return attributes;
115 + };
128 116
129 - }
130 -
131 117 /**
132 118 * Updates the block formatter's attributes when a field in the
133 119 * formatter's popover modal has its value changed.
134 120 *
@@ -133,53 +119,45 @@
133 119 * formatter's popover modal has its value changed.
134 120 *
135 121 * @since 2.2.0
136 122 *
137 - * @param object props Block formatter properties.
138 - * @param array field Field definition.
139 - * @param string newValue New value
123 + * @param {Object} props Block formatter properties.
124 + * @param {Object} field Field definition.
125 + * @param {string} newValue New value.
140 126 */
141 - const setAttributes = function( props, field, newValue ) {
142 -
127 + const setAttributes = function (props, field, newValue) {
143 128 // Define properties and functions to use.
144 129 const { onChange, value } = props;
145 130
146 131 // If no value exists, remove the formatter.
147 - if ( newValue === '' ) {
132 + if (newValue === '') {
148 133 return onChange(
149 - toggleFormat(
150 - value,
151 - {
152 - type: 'convertkit/' + formatter.name
153 - }
154 - )
134 + toggleFormat(value, {
135 + type: 'convertkit/' + formatter.name,
136 + })
155 137 );
156 138 }
157 139
158 140 // Build object of new attributes.
159 - let attributes = {};
160 - for ( let attribute in formatter.attributes ) {
141 + const attributes = {};
142 + for (const attribute in formatter.attributes) {
161 143 // If 'None' selected, blank the attribute's value.
162 - if ( newValue === '' ) {
163 - attributes[ attribute ] = '';
144 + if (newValue === '') {
145 + attributes[attribute] = '';
164 146 } else {
165 - attributes[ attribute ] = field.data[ newValue ][ attribute ];
147 + attributes[attribute] = field.data[newValue][attribute];
166 148 }
167 149 }
168 150
169 151 // Apply formatter with new attributes.
170 152 return onChange(
171 - applyFormat(
172 - value,
173 - {
174 - type: 'convertkit/' + formatter.name,
175 - attributes: attributes
176 - }
177 - )
153 + applyFormat(value, {
154 + type: 'convertkit/' + formatter.name,
155 + attributes,
156 + })
178 157 );
158 + };
179 159
180 - }
181 -
182 160 /**
183 161 * Return an array of field elements to display in the popover modal when
184 162 * this formatter is active.
185 163 *
@@ -184,84 +162,71 @@
184 162 * this formatter is active.
185 163 *
186 164 * @since 2.2.0
187 165 *
188 - * @param object props Block formatter properties.
189 - * @param object setShowPopover Function to toggle showing/hiding the popover.
190 - * @param object attributes Field attributes.
191 - * @return array Field elements
166 + * @param {Object} props Block formatter properties.
167 + * @param {Function} setShowPopover Function to toggle showing/hiding the popover.
168 + * @param {Object} attributes Field attributes.
169 + * @return {Array} Field elements
192 170 */
193 - const getFields = function( props, setShowPopover, attributes ) {
194 -
171 + const getFields = function (props, setShowPopover, attributes) {
195 172 // Define array of field elements.
196 - let elements = [];
173 + const elements = [];
197 174
198 175 // Return if no fields exist.
199 - if ( formatter.fields.length === 0 ) {
176 + if (formatter.fields.length === 0) {
200 177 return elements;
201 178 }
202 179
203 180 // Iterate through the formatter's fields, adding a field element for each.
204 - for ( let fieldName in formatter.fields ) {
205 - const field = formatter.fields[ fieldName ];
181 + for (const fieldName in formatter.fields) {
182 + const field = formatter.fields[fieldName];
206 183
207 184 // Build options for <select> input.
208 - let fieldOptions = [
185 + const fieldOptions = [
209 186 {
210 187 label: '(None)',
211 - value: ''
212 - }
188 + value: '',
189 + },
213 190 ];
214 - for ( let fieldValue in field.values ) {
215 - fieldOptions.push(
216 - {
217 - label: field.values[ fieldValue ],
218 - value: fieldValue
219 - }
220 - );
191 + for (const fieldValue in field.values) {
192 + fieldOptions.push({
193 + label: field.values[fieldValue],
194 + value: fieldValue,
195 + });
221 196 }
222 197
223 198 // Sort field's options alphabetically by label.
224 - fieldOptions.sort(
225 - function ( x, y ) {
199 + fieldOptions.sort(function (x, y) {
200 + const a = x.label.toUpperCase(),
201 + b = y.label.toUpperCase();
202 + return a.localeCompare(b);
203 + });
226 204
227 - let a = x.label.toUpperCase(),
228 - b = y.label.toUpperCase();
229 - return a.localeCompare( b );
230 -
231 - }
232 - );
233 -
234 205 // Add field to array.
235 206 elements.push(
236 - createElement(
237 - SelectControl,
238 - {
239 - key: 'convertkit_' + formatter.name + '_' + fieldName,
240 - id: 'convertkit-' + formatter.name + '-' + fieldName,
241 - label: field.label,
242 - value: attributes[ fieldName ],
243 - help: field.description,
244 - options: fieldOptions,
245 - onChange: function( newValue ) {
207 + createElement(SelectControl, {
208 + key: 'convertkit_' + formatter.name + '_' + fieldName,
209 + id: 'convertkit-' + formatter.name + '-' + fieldName,
210 + label: field.label,
211 + value: attributes[fieldName],
212 + help: field.description,
213 + options: fieldOptions,
214 + onChange(newValue) {
215 + // Hide popover.
216 + setShowPopover(false);
246 217
247 - // Hide popover.
248 - setShowPopover( false );
249 -
250 - // Update and apply attributes to the selected text.
251 - setAttributes( props, field, newValue );
252 -
253 - }
254 - }
255 - )
218 + // Update and apply attributes to the selected text.
219 + setAttributes(props, field, newValue);
220 + },
221 + })
256 222 );
257 223 }
258 224
259 225 // Return elements.
260 226 return elements;
227 + };
261 228
262 - }
263 -
264 229 /**
265 230 * Display modal when the formatter's button is clicked, and save
266 231 * changes that are made.
267 232 *
@@ -266,93 +231,96 @@
266 231 * changes that are made.
267 232 *
268 233 * @since 2.2.0
269 234 *
270 - * @param object props Block formatter properties.
271 - * @return object Block formatter button and modal elements
235 + * @param {Object} props Block formatter properties.
236 + * @return {Object} Block formatter button and modal elements
272 237 */
273 - const editFormatType = function( props ) {
274 -
238 + const EditFormatType = function (props) {
275 239 // Get props.
276 240 const { contentRef, isActive, value } = props;
277 - const { activeFormats } = value;
241 + const { activeFormats } = value;
278 242 let anchorRef;
279 243
280 244 // Get anchor reference to the text.
281 - if ( typeof useAnchor === 'undefined' ) {
245 + if (typeof useAnchor === 'undefined') {
282 246 // Use WordPress 6.0 and lower useAnchorRef(), as useAnchor() isn't available.
283 - anchorRef = useAnchorRef( { ref: contentRef, value } );
247 + anchorRef = useAnchorRef({ ref: contentRef, value }); // eslint-disable-line react-hooks/rules-of-hooks
284 248 } else {
285 249 // Use WordPress 6.1+ useAnchor(), as useAnchorRef() is deprecated in 6.2+.
286 - anchorRef = useAnchor( { editableContentElement: contentRef.current, value } );
250 + // eslint-disable-next-line react-hooks/rules-of-hooks
251 + anchorRef = useAnchor({
252 + editableContentElement: contentRef.current,
253 + value,
254 + });
287 255 }
288 256
289 257 // State to show popover.
290 - const [ showPopover, setShowPopover ] = useState( false );
258 + const [showPopover, setShowPopover] = useState(false);
291 259
292 260 // Get attributes.
293 - let attributes = getAttributes( activeFormats );
261 + const attributes = getAttributes(activeFormats);
294 262
295 263 // Define fields to display in the popover modal.
296 - let popoverModalElements = getFields( props, setShowPopover, attributes );
264 + const popoverModalElements = getFields(
265 + props,
266 + setShowPopover,
267 + attributes
268 + );
297 269
298 270 // Return block toolbar button and its modal.
299 - return (
300 - createElement(
301 - Fragment,
302 - {
303 - key: 'convertkit_' + formatter.name + '_rich_text_toolbar_fragment'
271 + return createElement(
272 + Fragment,
273 + {
274 + key:
275 + 'convertkit_' +
276 + formatter.name +
277 + '_rich_text_toolbar_fragment',
278 + },
279 + // Register the button in the rich text toolbar.
280 + createElement(RichTextToolbarButton, {
281 + key:
282 + 'convertkit_' +
283 + formatter.name +
284 + '_rich_text_toolbar_button',
285 + icon: getIcon(formatter),
286 + title: formatter.title,
287 + isActive,
288 + onClick() {
289 + setShowPopover(true);
304 290 },
305 - // Register the button in the rich text toolbar.
291 + }),
292 + // Popover which displays fields when the button is active.
293 + showPopover &&
306 294 createElement(
307 - RichTextToolbarButton,
308 - {
309 - key: 'convertkit_' + formatter.name + '_rich_text_toolbar_button',
310 - icon: getIcon( formatter ),
311 - title: formatter.title,
312 - isActive: isActive,
313 - onClick: function() {
314 - setShowPopover( true );
315 - }
316 - },
317 - ),
318 - // Popover which displays fields when the button is active.
319 - showPopover && ( createElement(
320 295 Popover,
321 296 {
322 - key: 'convertkit_' + formatter.name + '_popover',
323 - className: 'convertkit-popover',
324 - anchor: anchorRef,
325 - onClose: function() {
326 - setShowPopover( false );
327 - }
297 + key: 'convertkit_' + formatter.name + '_popover',
298 + className: 'convertkit-popover',
299 + anchor: anchorRef,
300 + onClose() {
301 + setShowPopover(false);
302 + },
328 303 },
329 304 popoverModalElements
330 - ) )
331 - )
305 + )
332 306 );
307 + };
333 308
334 - }
335 -
336 309 // Register Format Type.
337 - registerFormatType(
338 - 'convertkit/' + formatter.name,
339 - {
340 - title: formatter.title,
310 + registerFormatType('convertkit/' + formatter.name, {
311 + title: formatter.title,
341 312
342 - // The tagName and className combination allow Gutenberg to uniquely identify
343 - // whether this formatter has been used on the selected text.
344 - tagName: formatter.tag,
345 - className: 'convertkit-' + formatter.name,
346 - attributes: formatter.attributes,
347 - edit: editFormatType,
348 - }
349 - );
350 -
351 - } (
313 + // The tagName and className combination allow Gutenberg to uniquely identify
314 + // whether this formatter has been used on the selected text.
315 + tagName: formatter.tag,
316 + className: 'convertkit-' + formatter.name,
317 + attributes: formatter.attributes,
318 + edit: EditFormatType,
319 + });
320 + })(
352 321 window.wp.blockEditor,
353 322 window.wp.richText,
354 323 window.wp.element,
355 324 window.wp.components
356 - ) );
357 -
325 + );
358 326 }