PluginProbe
Gutenberg / 17.1.2
Gutenberg v17.1.2
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 17.1.2, at build/shortcode/index.js

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