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