[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/js/dist/ -> autop.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  /******/     /* webpack/runtime/make namespace object */
  25  /******/     (() => {
  26  /******/         // define __esModule on exports
  27  /******/         __webpack_require__.r = (exports) => {
  28  /******/             if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
  29  /******/                 Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
  30  /******/             }
  31  /******/             Object.defineProperty(exports, '__esModule', { value: true });
  32  /******/         };
  33  /******/     })();
  34  /******/     
  35  /************************************************************************/
  36  var __webpack_exports__ = {};
  37  __webpack_require__.r(__webpack_exports__);
  38  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
  39  /* harmony export */   autop: () => (/* binding */ autop),
  40  /* harmony export */   removep: () => (/* binding */ removep)
  41  /* harmony export */ });
  42  /* wp:polyfill */
  43  /**
  44   * The regular expression for an HTML element.
  45   */
  46  const htmlSplitRegex = (() => {
  47    /* eslint-disable no-multi-spaces */
  48    const comments = '!' +
  49    // Start of comment, after the <.
  50    '(?:' +
  51    // Unroll the loop: Consume everything until --> is found.
  52    '-(?!->)' +
  53    // Dash not followed by end of comment.
  54    '[^\\-]*' +
  55    // Consume non-dashes.
  56    ')*' +
  57    // Loop possessively.
  58    '(?:-->)?'; // End of comment. If not found, match all input.
  59  
  60    const cdata = '!\\[CDATA\\[' +
  61    // Start of comment, after the <.
  62    '[^\\]]*' +
  63    // Consume non-].
  64    '(?:' +
  65    // Unroll the loop: Consume everything until ]]> is found.
  66    '](?!]>)' +
  67    // One ] not followed by end of comment.
  68    '[^\\]]*' +
  69    // Consume non-].
  70    ')*?' +
  71    // Loop possessively.
  72    '(?:]]>)?'; // End of comment. If not found, match all input.
  73  
  74    const escaped = '(?=' +
  75    // Is the element escaped?
  76    '!--' + '|' + '!\\[CDATA\\[' + ')' + '((?=!-)' +
  77    // If yes, which type?
  78    comments + '|' + cdata + ')';
  79    const regex = '(' +
  80    // Capture the entire match.
  81    '<' +
  82    // Find start of element.
  83    '(' +
  84    // Conditional expression follows.
  85    escaped +
  86    // Find end of escaped element.
  87    '|' +
  88    // ... else ...
  89    '[^>]*>?' +
  90    // Find end of normal element.
  91    ')' + ')';
  92    return new RegExp(regex);
  93    /* eslint-enable no-multi-spaces */
  94  })();
  95  
  96  /**
  97   * Separate HTML elements and comments from the text.
  98   *
  99   * @param input The text which has to be formatted.
 100   *
 101   * @return The formatted text.
 102   */
 103  function htmlSplit(input) {
 104    const parts = [];
 105    let workingInput = input;
 106    let match;
 107    while (match = workingInput.match(htmlSplitRegex)) {
 108      // The `match` result, when invoked on a RegExp with the `g` flag (`/foo/g`) will not include `index`.
 109      // If the `g` flag is omitted, `index` is included.
 110      // `htmlSplitRegex` does not have the `g` flag so we can assert it will have an index number.
 111      // Assert `match.index` is a number.
 112      const index = match.index;
 113      parts.push(workingInput.slice(0, index));
 114      parts.push(match[0]);
 115      workingInput = workingInput.slice(index + match[0].length);
 116    }
 117    if (workingInput.length) {
 118      parts.push(workingInput);
 119    }
 120    return parts;
 121  }
 122  
 123  /**
 124   * Replace characters or phrases within HTML elements only.
 125   *
 126   * @param haystack     The text which has to be formatted.
 127   * @param replacePairs In the form {from: 'to', …}.
 128   *
 129   * @return The formatted text.
 130   */
 131  function replaceInHtmlTags(haystack, replacePairs) {
 132    // Find all elements.
 133    const textArr = htmlSplit(haystack);
 134    let changed = false;
 135  
 136    // Extract all needles.
 137    const needles = Object.keys(replacePairs);
 138  
 139    // Loop through delimiters (elements) only.
 140    for (let i = 1; i < textArr.length; i += 2) {
 141      for (let j = 0; j < needles.length; j++) {
 142        const needle = needles[j];
 143        if (-1 !== textArr[i].indexOf(needle)) {
 144          textArr[i] = textArr[i].replace(new RegExp(needle, 'g'), replacePairs[needle]);
 145          changed = true;
 146          // After one strtr() break out of the foreach loop and look at next element.
 147          break;
 148        }
 149      }
 150    }
 151    if (changed) {
 152      haystack = textArr.join('');
 153    }
 154    return haystack;
 155  }
 156  
 157  /**
 158   * Replaces double line-breaks with paragraph elements.
 159   *
 160   * A group of regex replaces used to identify text formatted with newlines and
 161   * replace double line-breaks with HTML paragraph tags. The remaining line-
 162   * breaks after conversion become `<br />` tags, unless br is set to 'false'.
 163   *
 164   * @param text The text which has to be formatted.
 165   * @param br   Optional. If set, will convert all remaining line-
 166   *             breaks after paragraphing. Default true.
 167   *
 168   * @example
 169   *```js
 170   * import { autop } from '@wordpress/autop';
 171   * autop( 'my text' ); // "<p>my text</p>"
 172   * ```
 173   *
 174   * @return Text which has been converted into paragraph tags.
 175   */
 176  function autop(text, br = true) {
 177    const preTags = [];
 178    if (text.trim() === '') {
 179      return '';
 180    }
 181  
 182    // Just to make things a little easier, pad the end.
 183    text = text + '\n';
 184  
 185    /*
 186     * Pre tags shouldn't be touched by autop.
 187     * Replace pre tags with placeholders and bring them back after autop.
 188     */
 189    if (text.indexOf('<pre') !== -1) {
 190      const textParts = text.split('</pre>');
 191      const lastText = textParts.pop();
 192      text = '';
 193      for (let i = 0; i < textParts.length; i++) {
 194        const textPart = textParts[i];
 195        const start = textPart.indexOf('<pre');
 196  
 197        // Malformed html?
 198        if (start === -1) {
 199          text += textPart;
 200          continue;
 201        }
 202        const name = '<pre wp-pre-tag-' + i + '></pre>';
 203        preTags.push([name, textPart.substr(start) + '</pre>']);
 204        text += textPart.substr(0, start) + name;
 205      }
 206      text += lastText;
 207    }
 208    // Change multiple <br>s into two line breaks, which will turn into paragraphs.
 209    text = text.replace(/<br\s*\/?>\s*<br\s*\/?>/g, '\n\n');
 210    const allBlocks = '(?:table|thead|tfoot|caption|col|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|form|map|area|blockquote|address|math|style|p|h[1-6]|hr|fieldset|legend|section|article|aside|hgroup|header|footer|nav|figure|figcaption|details|menu|summary)';
 211  
 212    // Add a double line break above block-level opening tags.
 213    text = text.replace(new RegExp('(<' + allBlocks + '[\\s/>])', 'g'), '\n\n$1');
 214  
 215    // Add a double line break below block-level closing tags.
 216    text = text.replace(new RegExp('(</' + allBlocks + '>)', 'g'), '$1\n\n');
 217  
 218    // Standardize newline characters to "\n".
 219    text = text.replace(/\r\n|\r/g, '\n');
 220  
 221    // Find newlines in all elements and add placeholders.
 222    text = replaceInHtmlTags(text, {
 223      '\n': ' <!-- wpnl --> '
 224    });
 225  
 226    // Collapse line breaks before and after <option> elements so they don't get autop'd.
 227    if (text.indexOf('<option') !== -1) {
 228      text = text.replace(/\s*<option/g, '<option');
 229      text = text.replace(/<\/option>\s*/g, '</option>');
 230    }
 231  
 232    /*
 233     * Collapse line breaks inside <object> elements, before <param> and <embed> elements
 234     * so they don't get autop'd.
 235     */
 236    if (text.indexOf('</object>') !== -1) {
 237      text = text.replace(/(<object[^>]*>)\s*/g, '$1');
 238      text = text.replace(/\s*<\/object>/g, '</object>');
 239      text = text.replace(/\s*(<\/?(?:param|embed)[^>]*>)\s*/g, '$1');
 240    }
 241  
 242    /*
 243     * Collapse line breaks inside <audio> and <video> elements,
 244     * before and after <source> and <track> elements.
 245     */
 246    if (text.indexOf('<source') !== -1 || text.indexOf('<track') !== -1) {
 247      text = text.replace(/([<\[](?:audio|video)[^>\]]*[>\]])\s*/g, '$1');
 248      text = text.replace(/\s*([<\[]\/(?:audio|video)[>\]])/g, '$1');
 249      text = text.replace(/\s*(<(?:source|track)[^>]*>)\s*/g, '$1');
 250    }
 251  
 252    // Collapse line breaks before and after <figcaption> elements.
 253    if (text.indexOf('<figcaption') !== -1) {
 254      text = text.replace(/\s*(<figcaption[^>]*>)/, '$1');
 255      text = text.replace(/<\/figcaption>\s*/, '</figcaption>');
 256    }
 257  
 258    // Remove more than two contiguous line breaks.
 259    text = text.replace(/\n\n+/g, '\n\n');
 260  
 261    // Split up the contents into an array of strings, separated by double line breaks.
 262    const texts = text.split(/\n\s*\n/).filter(Boolean);
 263  
 264    // Reset text prior to rebuilding.
 265    text = '';
 266  
 267    // Rebuild the content as a string, wrapping every bit with a <p>.
 268    texts.forEach(textPiece => {
 269      text += '<p>' + textPiece.replace(/^\n*|\n*$/g, '') + '</p>\n';
 270    });
 271  
 272    // Under certain strange conditions it could create a P of entirely whitespace.
 273    text = text.replace(/<p>\s*<\/p>/g, '');
 274  
 275    // Add a closing <p> inside <div>, <address>, or <form> tag if missing.
 276    text = text.replace(/<p>([^<]+)<\/(div|address|form)>/g, '<p>$1</p></$2>');
 277  
 278    // If an opening or closing block element tag is wrapped in a <p>, unwrap it.
 279    text = text.replace(new RegExp('<p>\\s*(</?' + allBlocks + '[^>]*>)\\s*</p>', 'g'), '$1');
 280  
 281    // In some cases <li> may get wrapped in <p>, fix them.
 282    text = text.replace(/<p>(<li.+?)<\/p>/g, '$1');
 283  
 284    // If a <blockquote> is wrapped with a <p>, move it inside the <blockquote>.
 285    text = text.replace(/<p><blockquote([^>]*)>/gi, '<blockquote$1><p>');
 286    text = text.replace(/<\/blockquote><\/p>/g, '</p></blockquote>');
 287  
 288    // If an opening or closing block element tag is preceded by an opening <p> tag, remove it.
 289    text = text.replace(new RegExp('<p>\\s*(</?' + allBlocks + '[^>]*>)', 'g'), '$1');
 290  
 291    // If an opening or closing block element tag is followed by a closing <p> tag, remove it.
 292    text = text.replace(new RegExp('(</?' + allBlocks + '[^>]*>)\\s*</p>', 'g'), '$1');
 293  
 294    // Optionally insert line breaks.
 295    if (br) {
 296      // Replace newlines that shouldn't be touched with a placeholder.
 297      text = text.replace(/<(script|style).*?<\/\\1>/g, match => match[0].replace(/\n/g, '<WPPreserveNewline />'));
 298  
 299      // Normalize <br>
 300      text = text.replace(/<br>|<br\/>/g, '<br />');
 301  
 302      // Replace any new line characters that aren't preceded by a <br /> with a <br />.
 303      text = text.replace(/(<br \/>)?\s*\n/g, (a, b) => b ? a : '<br />\n');
 304  
 305      // Replace newline placeholders with newlines.
 306      text = text.replace(/<WPPreserveNewline \/>/g, '\n');
 307    }
 308  
 309    // If a <br /> tag is after an opening or closing block tag, remove it.
 310    text = text.replace(new RegExp('(</?' + allBlocks + '[^>]*>)\\s*<br />', 'g'), '$1');
 311  
 312    // If a <br /> tag is before a subset of opening or closing block tags, remove it.
 313    text = text.replace(/<br \/>(\s*<\/?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)[^>]*>)/g, '$1');
 314    text = text.replace(/\n<\/p>$/g, '</p>');
 315  
 316    // Replace placeholder <pre> tags with their original content.
 317    preTags.forEach(preTag => {
 318      const [name, original] = preTag;
 319      text = text.replace(name, original);
 320    });
 321  
 322    // Restore newlines in all elements.
 323    if (-1 !== text.indexOf('<!-- wpnl -->')) {
 324      text = text.replace(/\s?<!-- wpnl -->\s?/g, '\n');
 325    }
 326    return text;
 327  }
 328  
 329  /**
 330   * Replaces `<p>` tags with two line breaks. "Opposite" of autop().
 331   *
 332   * Replaces `<p>` tags with two line breaks except where the `<p>` has attributes.
 333   * Unifies whitespace. Indents `<li>`, `<dt>` and `<dd>` for better readability.
 334   *
 335   * @param html The content from the editor.
 336   *
 337   * @example
 338   * ```js
 339   * import { removep } from '@wordpress/autop';
 340   * removep( '<p>my text</p>' ); // "my text"
 341   * ```
 342   *
 343   * @return The content with stripped paragraph tags.
 344   */
 345  function removep(html) {
 346    const blocklist = 'blockquote|ul|ol|li|dl|dt|dd|table|thead|tbody|tfoot|tr|th|td|h[1-6]|fieldset|figure';
 347    const blocklist1 = blocklist + '|div|p';
 348    const blocklist2 = blocklist + '|pre';
 349    const preserve = [];
 350    let preserveLinebreaks = false;
 351    let preserveBr = false;
 352    if (!html) {
 353      return '';
 354    }
 355  
 356    // Protect script and style tags.
 357    if (html.indexOf('<script') !== -1 || html.indexOf('<style') !== -1) {
 358      html = html.replace(/<(script|style)[^>]*>[\s\S]*?<\/\1>/g, match => {
 359        preserve.push(match);
 360        return '<wp-preserve>';
 361      });
 362    }
 363  
 364    // Protect pre tags.
 365    if (html.indexOf('<pre') !== -1) {
 366      preserveLinebreaks = true;
 367      html = html.replace(/<pre[^>]*>[\s\S]+?<\/pre>/g, a => {
 368        a = a.replace(/<br ?\/?>(\r\n|\n)?/g, '<wp-line-break>');
 369        a = a.replace(/<\/?p( [^>]*)?>(\r\n|\n)?/g, '<wp-line-break>');
 370        return a.replace(/\r?\n/g, '<wp-line-break>');
 371      });
 372    }
 373  
 374    // Remove line breaks but keep <br> tags inside image captions.
 375    if (html.indexOf('[caption') !== -1) {
 376      preserveBr = true;
 377      html = html.replace(/\[caption[\s\S]+?\[\/caption\]/g, a => {
 378        return a.replace(/<br([^>]*)>/g, '<wp-temp-br$1>').replace(/[\r\n\t]+/, '');
 379      });
 380    }
 381  
 382    // Normalize white space characters before and after block tags.
 383    html = html.replace(new RegExp('\\s*</(' + blocklist1 + ')>\\s*', 'g'), '</$1>\n');
 384    html = html.replace(new RegExp('\\s*<((?:' + blocklist1 + ')(?: [^>]*)?)>', 'g'), '\n<$1>');
 385  
 386    // Mark </p> if it has any attributes.
 387    html = html.replace(/(<p [^>]+>[\s\S]*?)<\/p>/g, '$1</p#>');
 388  
 389    // Preserve the first <p> inside a <div>.
 390    html = html.replace(/<div( [^>]*)?>\s*<p>/gi, '<div$1>\n\n');
 391  
 392    // Remove paragraph tags.
 393    html = html.replace(/\s*<p>/gi, '');
 394    html = html.replace(/\s*<\/p>\s*/gi, '\n\n');
 395  
 396    // Normalize white space chars and remove multiple line breaks.
 397    html = html.replace(/\n[\s\u00a0]+\n/g, '\n\n');
 398  
 399    // Replace <br> tags with line breaks.
 400    html = html.replace(/(\s*)<br ?\/?>\s*/gi, (_, space) => {
 401      if (space && space.indexOf('\n') !== -1) {
 402        return '\n\n';
 403      }
 404      return '\n';
 405    });
 406  
 407    // Fix line breaks around <div>.
 408    html = html.replace(/\s*<div/g, '\n<div');
 409    html = html.replace(/<\/div>\s*/g, '</div>\n');
 410  
 411    // Fix line breaks around caption shortcodes.
 412    html = html.replace(/\s*\[caption([^\[]+)\[\/caption\]\s*/gi, '\n\n[caption$1[/caption]\n\n');
 413    html = html.replace(/caption\]\n\n+\[caption/g, 'caption]\n\n[caption');
 414  
 415    // Pad block elements tags with a line break.
 416    html = html.replace(new RegExp('\\s*<((?:' + blocklist2 + ')(?: [^>]*)?)\\s*>', 'g'), '\n<$1>');
 417    html = html.replace(new RegExp('\\s*</(' + blocklist2 + ')>\\s*', 'g'), '</$1>\n');
 418  
 419    // Indent <li>, <dt> and <dd> tags.
 420    html = html.replace(/<((li|dt|dd)[^>]*)>/g, ' \t<$1>');
 421  
 422    // Fix line breaks around <select> and <option>.
 423    if (html.indexOf('<option') !== -1) {
 424      html = html.replace(/\s*<option/g, '\n<option');
 425      html = html.replace(/\s*<\/select>/g, '\n</select>');
 426    }
 427  
 428    // Pad <hr> with two line breaks.
 429    if (html.indexOf('<hr') !== -1) {
 430      html = html.replace(/\s*<hr( [^>]*)?>\s*/g, '\n\n<hr$1>\n\n');
 431    }
 432  
 433    // Remove line breaks in <object> tags.
 434    if (html.indexOf('<object') !== -1) {
 435      html = html.replace(/<object[\s\S]+?<\/object>/g, a => {
 436        return a.replace(/[\r\n]+/g, '');
 437      });
 438    }
 439  
 440    // Unmark special paragraph closing tags.
 441    html = html.replace(/<\/p#>/g, '</p>\n');
 442  
 443    // Pad remaining <p> tags whit a line break.
 444    html = html.replace(/\s*(<p [^>]+>[\s\S]*?<\/p>)/g, '\n$1');
 445  
 446    // Trim.
 447    html = html.replace(/^\s+/, '');
 448    html = html.replace(/[\s\u00a0]+$/, '');
 449    if (preserveLinebreaks) {
 450      html = html.replace(/<wp-line-break>/g, '\n');
 451    }
 452    if (preserveBr) {
 453      html = html.replace(/<wp-temp-br([^>]*)>/g, '<br$1>');
 454    }
 455  
 456    // Restore preserved tags.
 457    if (preserve.length) {
 458      html = html.replace(/<wp-preserve>/g, () => {
 459        return preserve.shift();
 460      });
 461    }
 462    return html;
 463  }
 464  
 465  (window.wp = window.wp || {}).autop = __webpack_exports__;
 466  /******/ })()
 467  ;


Generated : Sat Feb 22 08:20:01 2025 Cross-referenced by PHPXref