[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/js/dist/ -> shortcode.js (source)

   1  /******/ (() => { // webpackBootstrap
   2  /******/     "use strict";
   3  /******/     // The require scope
   4  /******/     var __webpack_require__ = {};
   5  /******/     
   6  /************************************************************************/
   7  /******/     /* webpack/runtime/define property getters */
   8  /******/     (() => {
   9  /******/         // define getter functions for harmony exports
  10  /******/         __webpack_require__.d = (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  /******/     (() => {
  21  /******/         __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
  22  /******/     })();
  23  /******/     
  24  /************************************************************************/
  25  var __webpack_exports__ = {};
  26  
  27  // EXPORTS
  28  __webpack_require__.d(__webpack_exports__, {
  29    "default": () => (/* binding */ build_module)
  30  });
  31  
  32  // UNUSED EXPORTS: attrs, fromMatch, next, regexp, replace, string
  33  
  34  ;// ./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  ;// ./node_modules/@wordpress/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 */ const build_module = (shortcode);
 552  
 553  (window.wp = window.wp || {}).shortcode = __webpack_exports__["default"];
 554  /******/ })()
 555  ;


Generated : Sat Dec 21 08:20:01 2024 Cross-referenced by PHPXref