PluginProbe
Gutenberg / 15.2.3
Gutenberg v15.2.3
23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 7.4.0 All 402 releases
gutenberg / build / shortcode / index.js

index.js in Gutenberg 15.2.3, at build/shortcode/index.js

600 lines 16.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /******/ (function() { // webpackBootstrap
2 /******/ var __webpack_modules__ = ({
3
4 /***/ 9756:
5 /***/ (function(module) {
6
7 /**
8 * Memize options object.
9 *
10 * @typedef MemizeOptions
11 *
12 * @property {number} [maxSize] Maximum size of the cache.
13 */
14
15 /**
16 * Internal cache entry.
17 *
18 * @typedef MemizeCacheNode
19 *
20 * @property {?MemizeCacheNode|undefined} [prev] Previous node.
21 * @property {?MemizeCacheNode|undefined} [next] Next node.
22 * @property {Array<*>} args Function arguments for cache
23 * entry.
24 * @property {*} val Function result.
25 */
26
27 /**
28 * Properties of the enhanced function for controlling cache.
29 *
30 * @typedef MemizeMemoizedFunction
31 *
32 * @property {()=>void} clear Clear the cache.
33 */
34
35 /**
36 * Accepts a function to be memoized, and returns a new memoized function, with
37 * optional options.
38 *
39 * @template {Function} F
40 *
41 * @param {F} fn Function to memoize.
42 * @param {MemizeOptions} [options] Options object.
43 *
44 * @return {F & MemizeMemoizedFunction} Memoized function.
45 */
46 function memize( fn, options ) {
47 var size = 0;
48
49 /** @type {?MemizeCacheNode|undefined} */
50 var head;
51
52 /** @type {?MemizeCacheNode|undefined} */
53 var tail;
54
55 options = options || {};
56
57 function memoized( /* ...args */ ) {
58 var node = head,
59 len = arguments.length,
60 args, i;
61
62 searchCache: while ( node ) {
63 // Perform a shallow equality test to confirm that whether the node
64 // under test is a candidate for the arguments passed. Two arrays
65 // are shallowly equal if their length matches and each entry is
66 // strictly equal between the two sets. Avoid abstracting to a
67 // function which could incur an arguments leaking deoptimization.
68
69 // Check whether node arguments match arguments length
70 if ( node.args.length !== arguments.length ) {
71 node = node.next;
72 continue;
73 }
74
75 // Check whether node arguments match arguments values
76 for ( i = 0; i < len; i++ ) {
77 if ( node.args[ i ] !== arguments[ i ] ) {
78 node = node.next;
79 continue searchCache;
80 }
81 }
82
83 // At this point we can assume we've found a match
84
85 // Surface matched node to head if not already
86 if ( node !== head ) {
87 // As tail, shift to previous. Must only shift if not also
88 // head, since if both head and tail, there is no previous.
89 if ( node === tail ) {
90 tail = node.prev;
91 }
92
93 // Adjust siblings to point to each other. If node was tail,
94 // this also handles new tail's empty `next` assignment.
95 /** @type {MemizeCacheNode} */ ( node.prev ).next = node.next;
96 if ( node.next ) {
97 node.next.prev = node.prev;
98 }
99
100 node.next = head;
101 node.prev = null;
102 /** @type {MemizeCacheNode} */ ( head ).prev = node;
103 head = node;
104 }
105
106 // Return immediately
107 return node.val;
108 }
109
110 // No cached value found. Continue to insertion phase:
111
112 // Create a copy of arguments (avoid leaking deoptimization)
113 args = new Array( len );
114 for ( i = 0; i < len; i++ ) {
115 args[ i ] = arguments[ i ];
116 }
117
118 node = {
119 args: args,
120
121 // Generate the result from original function
122 val: fn.apply( null, args ),
123 };
124
125 // Don't need to check whether node is already head, since it would
126 // have been returned above already if it was
127
128 // Shift existing head down list
129 if ( head ) {
130 head.prev = node;
131 node.next = head;
132 } else {
133 // If no head, follows that there's no tail (at initial or reset)
134 tail = node;
135 }
136
137 // Trim tail if we're reached max size and are pending cache insertion
138 if ( size === /** @type {MemizeOptions} */ ( options ).maxSize ) {
139 tail = /** @type {MemizeCacheNode} */ ( tail ).prev;
140 /** @type {MemizeCacheNode} */ ( tail ).next = null;
141 } else {
142 size++;
143 }
144
145 head = node;
146
147 return node.val;
148 }
149
150 memoized.clear = function() {
151 head = null;
152 tail = null;
153 size = 0;
154 };
155
156 if ( false ) {}
157
158 // Ignore reason: There's not a clear solution to create an intersection of
159 // the function with additional properties, where the goal is to retain the
160 // function signature of the incoming argument and add control properties
161 // on the return value.
162
163 // @ts-ignore
164 return memoized;
165 }
166
167 module.exports = memize;
168
169
170 /***/ })
171
172 /******/ });
173 /************************************************************************/
174 /******/ // The module cache
175 /******/ var __webpack_module_cache__ = {};
176 /******/
177 /******/ // The require function
178 /******/ function __webpack_require__(moduleId) {
179 /******/ // Check if module is in cache
180 /******/ var cachedModule = __webpack_module_cache__[moduleId];
181 /******/ if (cachedModule !== undefined) {
182 /******/ return cachedModule.exports;
183 /******/ }
184 /******/ // Create a new module (and put it into the cache)
185 /******/ var module = __webpack_module_cache__[moduleId] = {
186 /******/ // no module.id needed
187 /******/ // no module.loaded needed
188 /******/ exports: {}
189 /******/ };
190 /******/
191 /******/ // Execute the module function
192 /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
193 /******/
194 /******/ // Return the exports of the module
195 /******/ return module.exports;
196 /******/ }
197 /******/
198 /************************************************************************/
199 /******/ /* webpack/runtime/compat get default export */
200 /******/ !function() {
201 /******/ // getDefaultExport function for compatibility with non-harmony modules
202 /******/ __webpack_require__.n = function(module) {
203 /******/ var getter = module && module.__esModule ?
204 /******/ function() { return module['default']; } :
205 /******/ function() { return module; };
206 /******/ __webpack_require__.d(getter, { a: getter });
207 /******/ return getter;
208 /******/ };
209 /******/ }();
210 /******/
211 /******/ /* webpack/runtime/define property getters */
212 /******/ !function() {
213 /******/ // define getter functions for harmony exports
214 /******/ __webpack_require__.d = function(exports, definition) {
215 /******/ for(var key in definition) {
216 /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
217 /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
218 /******/ }
219 /******/ }
220 /******/ };
221 /******/ }();
222 /******/
223 /******/ /* webpack/runtime/hasOwnProperty shorthand */
224 /******/ !function() {
225 /******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
226 /******/ }();
227 /******/
228 /************************************************************************/
229 var __webpack_exports__ = {};
230 // This entry need to be wrapped in an IIFE because it need to be in strict mode.
231 !function() {
232 "use strict";
233 /* unused harmony exports next, replace, string, regexp, attrs, fromMatch */
234 /* harmony import */ var memize__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9756);
235 /* harmony import */ var memize__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(memize__WEBPACK_IMPORTED_MODULE_0__);
236 /**
237 * External dependencies
238 */
239
240 /**
241 * Shortcode attributes object.
242 *
243 * @typedef {Object} WPShortcodeAttrs
244 *
245 * @property {Object} named Object with named attributes.
246 * @property {Array} numeric Array with numeric attributes.
247 */
248
249 /**
250 * Shortcode object.
251 *
252 * @typedef {Object} WPShortcode
253 *
254 * @property {string} tag Shortcode tag.
255 * @property {WPShortcodeAttrs} attrs Shortcode attributes.
256 * @property {string} content Shortcode content.
257 * @property {string} type Shortcode type: `self-closing`,
258 * `closed`, or `single`.
259 */
260
261 /**
262 * @typedef {Object} WPShortcodeMatch
263 *
264 * @property {number} index Index the shortcode is found at.
265 * @property {string} content Matched content.
266 * @property {WPShortcode} shortcode Shortcode instance of the match.
267 */
268
269 /**
270 * Find the next matching shortcode.
271 *
272 * @param {string} tag Shortcode tag.
273 * @param {string} text Text to search.
274 * @param {number} index Index to start search from.
275 *
276 * @return {WPShortcodeMatch | undefined} Matched information.
277 */
278
279 function next(tag, text) {
280 let index = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
281 const re = regexp(tag);
282 re.lastIndex = index;
283 const match = re.exec(text);
284
285 if (!match) {
286 return;
287 } // If we matched an escaped shortcode, try again.
288
289
290 if ('[' === match[1] && ']' === match[7]) {
291 return next(tag, text, re.lastIndex);
292 }
293
294 const result = {
295 index: match.index,
296 content: match[0],
297 shortcode: fromMatch(match)
298 }; // If we matched a leading `[`, strip it from the match and increment the
299 // index accordingly.
300
301 if (match[1]) {
302 result.content = result.content.slice(1);
303 result.index++;
304 } // If we matched a trailing `]`, strip it from the match.
305
306
307 if (match[7]) {
308 result.content = result.content.slice(0, -1);
309 }
310
311 return result;
312 }
313 /**
314 * Replace matching shortcodes in a block of text.
315 *
316 * @param {string} tag Shortcode tag.
317 * @param {string} text Text to search.
318 * @param {Function} callback Function to process the match and return
319 * replacement string.
320 *
321 * @return {string} Text with shortcodes replaced.
322 */
323
324 function replace(tag, text, callback) {
325 return text.replace(regexp(tag), function (match, left, $3, attrs, slash, content, closing, right) {
326 // If both extra brackets exist, the shortcode has been properly
327 // escaped.
328 if (left === '[' && right === ']') {
329 return match;
330 } // Create the match object and pass it through the callback.
331
332
333 const result = callback(fromMatch(arguments)); // Make sure to return any of the extra brackets if they weren't used to
334 // escape the shortcode.
335
336 return result || result === '' ? left + result + right : match;
337 });
338 }
339 /**
340 * Generate a string from shortcode parameters.
341 *
342 * Creates a shortcode instance and returns a string.
343 *
344 * Accepts the same `options` as the `shortcode()` constructor, containing a
345 * `tag` string, a string or object of `attrs`, a boolean indicating whether to
346 * format the shortcode using a `single` tag, and a `content` string.
347 *
348 * @param {Object} options
349 *
350 * @return {string} String representation of the shortcode.
351 */
352
353 function string(options) {
354 return new shortcode(options).string();
355 }
356 /**
357 * Generate a RegExp to identify a shortcode.
358 *
359 * The base regex is functionally equivalent to the one found in
360 * `get_shortcode_regex()` in `wp-includes/shortcodes.php`.
361 *
362 * Capture groups:
363 *
364 * 1. An extra `[` to allow for escaping shortcodes with double `[[]]`
365 * 2. The shortcode name
366 * 3. The shortcode argument list
367 * 4. The self closing `/`
368 * 5. The content of a shortcode when it wraps some content.
369 * 6. The closing tag.
370 * 7. An extra `]` to allow for escaping shortcodes with double `[[]]`
371 *
372 * @param {string} tag Shortcode tag.
373 *
374 * @return {RegExp} Shortcode RegExp.
375 */
376
377 function regexp(tag) {
378 return new RegExp('\\[(\\[?)(' + tag + ')(?![\\w-])([^\\]\\/]*(?:\\/(?!\\])[^\\]\\/]*)*?)(?:(\\/)\\]|\\](?:([^\\[]*(?:\\[(?!\\/\\2\\])[^\\[]*)*)(\\[\\/\\2\\]))?)(\\]?)', 'g');
379 }
380 /**
381 * Parse shortcode attributes.
382 *
383 * Shortcodes accept many types of attributes. These can chiefly be divided into
384 * named and numeric attributes:
385 *
386 * Named attributes are assigned on a key/value basis, while numeric attributes
387 * are treated as an array.
388 *
389 * Named attributes can be formatted as either `name="value"`, `name='value'`,
390 * or `name=value`. Numeric attributes can be formatted as `"value"` or just
391 * `value`.
392 *
393 * @param {string} text Serialised shortcode attributes.
394 *
395 * @return {WPShortcodeAttrs} Parsed shortcode attributes.
396 */
397
398 const attrs = memize__WEBPACK_IMPORTED_MODULE_0___default()(text => {
399 const named = {};
400 const numeric = []; // This regular expression is reused from `shortcode_parse_atts()` in
401 // `wp-includes/shortcodes.php`.
402 //
403 // Capture groups:
404 //
405 // 1. An attribute name, that corresponds to...
406 // 2. a value in double quotes.
407 // 3. An attribute name, that corresponds to...
408 // 4. a value in single quotes.
409 // 5. An attribute name, that corresponds to...
410 // 6. an unquoted value.
411 // 7. A numeric attribute in double quotes.
412 // 8. A numeric attribute in single quotes.
413 // 9. An unquoted numeric attribute.
414
415 const pattern = /([\w-]+)\s*=\s*"([^"]*)"(?:\s|$)|([\w-]+)\s*=\s*'([^']*)'(?:\s|$)|([\w-]+)\s*=\s*([^\s'"]+)(?:\s|$)|"([^"]*)"(?:\s|$)|'([^']*)'(?:\s|$)|(\S+)(?:\s|$)/g; // Map zero-width spaces to actual spaces.
416
417 text = text.replace(/[\u00a0\u200b]/g, ' ');
418 let match; // Match and normalize attributes.
419
420 while (match = pattern.exec(text)) {
421 if (match[1]) {
422 named[match[1].toLowerCase()] = match[2];
423 } else if (match[3]) {
424 named[match[3].toLowerCase()] = match[4];
425 } else if (match[5]) {
426 named[match[5].toLowerCase()] = match[6];
427 } else if (match[7]) {
428 numeric.push(match[7]);
429 } else if (match[8]) {
430 numeric.push(match[8]);
431 } else if (match[9]) {
432 numeric.push(match[9]);
433 }
434 }
435
436 return {
437 named,
438 numeric
439 };
440 });
441 /**
442 * Generate a Shortcode Object from a RegExp match.
443 *
444 * Accepts a `match` object from calling `regexp.exec()` on a `RegExp` generated
445 * by `regexp()`. `match` can also be set to the `arguments` from a callback
446 * passed to `regexp.replace()`.
447 *
448 * @param {Array} match Match array.
449 *
450 * @return {WPShortcode} Shortcode instance.
451 */
452
453 function fromMatch(match) {
454 let type;
455
456 if (match[4]) {
457 type = 'self-closing';
458 } else if (match[6]) {
459 type = 'closed';
460 } else {
461 type = 'single';
462 }
463
464 return new shortcode({
465 tag: match[2],
466 attrs: match[3],
467 type,
468 content: match[5]
469 });
470 }
471 /**
472 * Creates a shortcode instance.
473 *
474 * To access a raw representation of a shortcode, pass an `options` object,
475 * containing a `tag` string, a string or object of `attrs`, a string indicating
476 * the `type` of the shortcode ('single', 'self-closing', or 'closed'), and a
477 * `content` string.
478 *
479 * @param {Object} options Options as described.
480 *
481 * @return {WPShortcode} Shortcode instance.
482 */
483
484 const shortcode = Object.assign(function (options) {
485 const {
486 tag,
487 attrs: attributes,
488 type,
489 content
490 } = options || {};
491 Object.assign(this, {
492 tag,
493 type,
494 content
495 }); // Ensure we have a correctly formatted `attrs` object.
496
497 this.attrs = {
498 named: {},
499 numeric: []
500 };
501
502 if (!attributes) {
503 return;
504 }
505
506 const attributeTypes = ['named', 'numeric']; // Parse a string of attributes.
507
508 if (typeof attributes === 'string') {
509 this.attrs = attrs(attributes); // Identify a correctly formatted `attrs` object.
510 } else if (attributes.length === attributeTypes.length && attributeTypes.every((t, key) => t === attributes[key])) {
511 this.attrs = attributes; // Handle a flat object of attributes.
512 } else {
513 Object.entries(attributes).forEach(_ref => {
514 let [key, value] = _ref;
515 this.set(key, value);
516 });
517 }
518 }, {
519 next,
520 replace,
521 string,
522 regexp,
523 attrs,
524 fromMatch
525 });
526 Object.assign(shortcode.prototype, {
527 /**
528 * Get a shortcode attribute.
529 *
530 * Automatically detects whether `attr` is named or numeric and routes it
531 * accordingly.
532 *
533 * @param {(number|string)} attr Attribute key.
534 *
535 * @return {string} Attribute value.
536 */
537 get(attr) {
538 return this.attrs[typeof attr === 'number' ? 'numeric' : 'named'][attr];
539 },
540
541 /**
542 * Set a shortcode attribute.
543 *
544 * Automatically detects whether `attr` is named or numeric and routes it
545 * accordingly.
546 *
547 * @param {(number|string)} attr Attribute key.
548 * @param {string} value Attribute value.
549 *
550 * @return {WPShortcode} Shortcode instance.
551 */
552 set(attr, value) {
553 this.attrs[typeof attr === 'number' ? 'numeric' : 'named'][attr] = value;
554 return this;
555 },
556
557 /**
558 * Transform the shortcode into a string.
559 *
560 * @return {string} String representation of the shortcode.
561 */
562 string() {
563 let text = '[' + this.tag;
564 this.attrs.numeric.forEach(value => {
565 if (/\s/.test(value)) {
566 text += ' "' + value + '"';
567 } else {
568 text += ' ' + value;
569 }
570 });
571 Object.entries(this.attrs.named).forEach(_ref2 => {
572 let [name, value] = _ref2;
573 text += ' ' + name + '="' + value + '"';
574 }); // If the tag is marked as `single` or `self-closing`, close the tag and
575 // ignore any additional content.
576
577 if ('single' === this.type) {
578 return text + ']';
579 } else if ('self-closing' === this.type) {
580 return text + ' /]';
581 } // Complete the opening tag.
582
583
584 text += ']';
585
586 if (this.content) {
587 text += this.content;
588 } // Add the closing tag.
589
590
591 return text + '[/' + this.tag + ']';
592 }
593
594 });
595 /* harmony default export */ __webpack_exports__["default"] = (shortcode);
596
597 }();
598 (window.wp = window.wp || {}).shortcode = __webpack_exports__["default"];
599 /******/ })()
600 ;