customizer-utils.js (19352B)
1 (function ($) { 2 3 // source: https://github.com/andymantell/node-wpautop 4 function _autop_newline_preservation_helper(matches) { 5 return matches[0].replace("\n", "<WPPreserveNewline />"); 6 }; 7 8 function wpautop(pee, br) { 9 if (typeof(br) === 'undefined') { 10 br = true; 11 } 12 13 var pre_tags = {}; 14 if (pee.trim() === '') { 15 return ''; 16 } 17 18 pee = pee + "\n"; // just to make things a little easier, pad the end 19 if (pee.indexOf('<pre') > -1) { 20 var pee_parts = pee.split('</pre>'); 21 var last_pee = pee_parts.pop(); 22 pee = ''; 23 pee_parts.forEach(function (pee_part, index) { 24 var start = pee_part.indexOf('<pre'); 25 26 // Malformed html? 27 if (start === -1) { 28 pee += pee_part; 29 return; 30 } 31 32 var name = "<pre wp-pre-tag-" + index + "></pre>"; 33 pre_tags[name] = pee_part.substr(start) + '</pre>'; 34 pee += pee_part.substr(0, start) + name; 35 36 }); 37 38 pee += last_pee; 39 } 40 41 pee = pee.replace(/<br \/>\s*<br \/>/, "\n\n"); 42 43 // Space things out a little 44 var 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)'; 45 pee = pee.replace(new RegExp('(<' + allblocks + '[^>]*>)', 'gmi'), "\n$1"); 46 pee = pee.replace(new RegExp('(</' + allblocks + '>)', 'gmi'), "$1\n\n"); 47 pee = pee.replace(/\r\n|\r/, "\n"); // cross-platform newlines 48 49 if (pee.indexOf('<option') > -1) { 50 // no P/BR around option 51 pee = pee.replace(/\s*<option'/gmi, '<option'); 52 pee = pee.replace(/<\/option>\s*/gmi, '</option>'); 53 } 54 55 if (pee.indexOf('</object>') > -1) { 56 // no P/BR around param and embed 57 pee = pee.replace(/(<object[^>]*>)\s*/gmi, '$1'); 58 pee = pee.replace(/\s*<\/object>/gmi, '</object>'); 59 pee = pee.replace(/\s*(<\/?(?:param|embed)[^>]*>)\s*/gmi, '$1'); 60 } 61 62 if (pee.indexOf('<source') > -1 || pee.indexOf('<track') > -1) { 63 // no P/BR around source and track 64 pee = pee.replace(/([<\[](?:audio|video)[^>\]]*[>\]])\s*/gmi, '$1'); 65 pee = pee.replace(/\s*([<\[]\/(?:audio|video)[>\]])/gmi, '$1'); 66 pee = pee.replace(/\s*(<(?:source|track)[^>]*>)\s*/gmi, '$1'); 67 } 68 69 pee = pee.replace(/\n\n+/gmi, "\n\n"); // take care of duplicates 70 71 // make paragraphs, including one at the end 72 var pees = pee.split(/\n\s*\n/); 73 pee = ''; 74 pees.forEach(function (tinkle) { 75 pee += '<p>' + tinkle.replace(/^\s+|\s+$/g, '') + "</p>\n"; 76 }); 77 78 pee = pee.replace(/<p>\s*<\/p>/gmi, ''); // under certain strange conditions it could create a P of entirely whitespace 79 pee = pee.replace(/<p>([^<]+)<\/(div|address|form)>/gmi, "<p>$1</p></$2>"); 80 pee = pee.replace(new RegExp('<p>\s*(</?' + allblocks + '[^>]*>)\s*</p>', 'gmi'), "$1", pee); // don't pee all over a tag 81 pee = pee.replace(/<p>(<li.+?)<\/p>/gmi, "$1"); // problem with nested lists 82 pee = pee.replace(/<p><blockquote([^>]*)>/gmi, "<blockquote$1><p>"); 83 pee = pee.replace(/<\/blockquote><\/p>/gmi, '</p></blockquote>'); 84 pee = pee.replace(new RegExp('<p>\s*(</?' + allblocks + '[^>]*>)', 'gmi'), "$1"); 85 pee = pee.replace(new RegExp('(</?' + allblocks + '[^>]*>)\s*</p>', 'gmi'), "$1"); 86 87 if (br) { 88 pee = pee.replace(/<(script|style)(?:.|\n)*?<\/\\1>/gmi, _autop_newline_preservation_helper); // /s modifier from php PCRE regexp replaced with (?:.|\n) 89 pee = pee.replace(/(<br \/>)?\s*\n/gmi, "<br />\n"); // optionally make line breaks 90 pee = pee.replace('<WPPreserveNewline />', "\n"); 91 } 92 93 pee = pee.replace(new RegExp('(</?' + allblocks + '[^>]*>)\s*<br />', 'gmi'), "$1"); 94 pee = pee.replace(/<br \/>(\s*<\/?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)[^>]*>)/gmi, '$1'); 95 pee = pee.replace(/\n<\/p>$/gmi, '</p>'); 96 97 if (Object.keys(pre_tags).length) { 98 pee = pee.replace(new RegExp(Object.keys(pre_tags).join('|'), "gi"), function (matched) { 99 return pre_tags[matched]; 100 }); 101 } 102 103 return pee; 104 }; 105 106 CP_Customizer.addModule(function (CP_Customizer) { 107 CP_Customizer.utils = CP_Customizer.utils || {}; 108 109 CP_Customizer.utils.wpautop = function (value) { 110 value = wpautop(value); 111 112 if (jQuery(value).length === 1) { 113 return jQuery(value).html(); 114 } 115 116 return value; 117 118 }; 119 120 121 CP_Customizer.utils.phpTrim = function (str, charlist) { 122 123 var whitespace = [ 124 ' ', 125 '\n', 126 '\r', 127 '\t', 128 '\f', 129 '\x0b', 130 '\xa0', 131 '\u2000', 132 '\u2001', 133 '\u2002', 134 '\u2003', 135 '\u2004', 136 '\u2005', 137 '\u2006', 138 '\u2007', 139 '\u2008', 140 '\u2009', 141 '\u200a', 142 '\u200b', 143 '\u2028', 144 '\u2029', 145 '\u3000' 146 ].join(''); 147 148 var l = 0; 149 var i = 0; 150 str += ''; 151 152 if (charlist) { 153 whitespace = (charlist + '').replace(/([[\]().?/*{}+$^:])/g, '$1') 154 } 155 l = str.length 156 for (i = 0; i < l; i++) { 157 if (whitespace.indexOf(str.charAt(i)) === -1) { 158 str = str.substring(i) 159 break 160 } 161 } 162 l = str.length 163 for (i = l - 1; i >= 0; i--) { 164 if (whitespace.indexOf(str.charAt(i)) === -1) { 165 str = str.substring(0, i + 1) 166 break 167 } 168 } 169 return whitespace.indexOf(str.charAt(0)) === -1 ? str : '' 170 }; 171 172 CP_Customizer.utils.normalizeBackgroundImageValue = function (value) { 173 value = value.replace(/url\((.*)\)/, "$1"); 174 return CP_Customizer.utils.phpTrim(value, "\"'"); 175 }; 176 177 178 CP_Customizer.utils.htmlDecode = function (value) { 179 var result = $('<div/>').html(value).text(); 180 return result; 181 }; 182 183 CP_Customizer.utils.htmlEscape = function (str) { 184 return str 185 .replace(/&/g, '&') 186 .replace(/"/g, '"') 187 .replace(/'/g, ''') 188 .replace(/</g, '<') 189 .replace(/>/g, '>'); 190 }; 191 192 193 var htmlEntityMap = { 194 '&': '&', 195 '<': '<', 196 '>': '>', 197 '"': '"', 198 "'": ''', 199 '/': '/', 200 '`': '`', 201 '=': '=' 202 }; 203 204 CP_Customizer.utils.htmlUnescape = function (str) { 205 206 for (var item in htmlEntityMap) { 207 var regExp = new RegExp(htmlEntityMap[item], 'g'); 208 str = str.replace(regExp, item); 209 } 210 211 return str; 212 }; 213 214 215 CP_Customizer.utils.setToPath = function (schema, path, value) { 216 217 if (!schema) { 218 return schema; 219 } 220 221 if (_.isString(schema)) { 222 schema = CP_Customizer.utils.normalizeValue(schema); 223 } 224 225 var pList = path.split('.'); 226 var len = pList.length; 227 228 if (len > 1) { 229 var first = pList.shift(); 230 var remainingPath = pList.join('.'); 231 schema[first] = CP_Customizer.utils.setToPath(schema[first], remainingPath, value); 232 } else { 233 schema[path] = value; 234 } 235 236 return schema; 237 }; 238 239 CP_Customizer.utils.normalizeShortcodeString = function (shortcode) { 240 shortcode = CP_Customizer.utils.htmlDecode(shortcode); 241 242 return '[' + CP_Customizer.utils.phpTrim(shortcode) + ']'; 243 }; 244 245 CP_Customizer.utils.getSpectrumColorFormated = function ($spectrumElement) { 246 var value = $spectrumElement.spectrum('get'); 247 248 249 if (!value) { 250 return value; 251 } 252 253 if (value.getAlpha() < 1) { 254 return "rgba(" + value._r + "," + value._g + "," + value._b + "," + value._a + ")"; 255 } else { 256 return value.toHexString(); 257 } 258 }; 259 260 CP_Customizer.utils.normalizeValue = function (value, convertToArray) { 261 262 263 if (_.isString(value)) { 264 265 try { 266 value = decodeURI(value); 267 268 } catch (e) { 269 270 } 271 272 try { 273 value = JSON.parse(value); 274 275 } catch (e) { 276 277 } 278 279 } 280 281 if (_.isObject(value) && convertToArray) { 282 var hasOnlyNumberKeys = _.keys(value).map(function (k) { 283 return _.isNumber(parseInt(k)) 284 }).reduce(function (a, b) { 285 return (a && b); 286 }, true); 287 288 if (hasOnlyNumberKeys) { 289 var newValue = []; 290 _.keys(value).forEach(function (k) { 291 292 if (_.isUndefined(value[k])) { 293 return; 294 } 295 296 newValue.push(value[k]); 297 }); 298 299 value = newValue; 300 } 301 } 302 303 return value; 304 }; 305 306 CP_Customizer.utils.getValue = function (component) { 307 var value = undefined; 308 309 if (component instanceof CP_Customizer.wpApi.Control) { 310 value = component.setting.get(); 311 } 312 313 if (component instanceof CP_Customizer.wpApi.Setting) { 314 value = component.get(); 315 } 316 317 if (_.isString(component)) { 318 value = CP_Customizer.wpApi(component).get(); 319 } 320 321 if (_.isString(value)) { 322 323 try { 324 value = decodeURI(value); 325 326 } catch (e) { 327 328 } 329 330 try { 331 value = JSON.parse(value); 332 } catch (e) { 333 334 } 335 336 } 337 338 return value; 339 }; 340 341 CP_Customizer.utils.deepClone = function (toClone, asArray) { 342 var result = jQuery.extend(true, {}, toClone); 343 if (asArray) { 344 result = _.toArray(result); 345 } 346 return result; 347 }; 348 349 CP_Customizer.utils.cssValueNumber = function (value) { 350 var matches = value.match(/\d+(.\d+)?/); 351 352 if (!matches || !_.isArray(matches)) { 353 return null; 354 } 355 356 return matches.shift(); 357 }; 358 359 CP_Customizer.utils.arrayChunk = function (bigArray, perGroup) { 360 perGroup = perGroup || 5; 361 var result = _.groupBy(bigArray, function (element, index) { 362 return Math.floor(index / perGroup); 363 }); 364 365 return _.toArray(result); 366 }; 367 368 CP_Customizer.utils.normalizeClassAttr = function (classes, asSelector) { 369 classes = classes.split(' ').filter(function (item) { 370 return (item.trim().length > 0); 371 }); 372 373 if (asSelector) { 374 return (classes.length ? '.' + classes.join('.') : ''); 375 } else { 376 return classes.join(' '); 377 } 378 }; 379 380 CP_Customizer.utils.getFileInfo = function (url) { 381 var filename = url.substring(url.lastIndexOf("/") + 1, url.lastIndexOf(".")); 382 var parts = url.split("/" + filename)[0]; 383 var path = parts[0]; 384 var extension = parts.length > 1 ? parts[1].split('/')[0] : ''; 385 386 return { 387 path: path, 388 file: filename + (extension ? '.' + extension : extension), 389 filename: filename, 390 extension: extension 391 } 392 }; 393 394 var imageExtensions = ["tif", "tiff", "gif", "jpeg", "jpg", "jif", "jfif", "jp2", "jpx", "j2k", "j2c", "fpx", "pcd", "png", "pdf", "bmp", "ico"]; 395 CP_Customizer.utils.isImageFile = function (url) { 396 var fileInfo = CP_Customizer.utils.getFileInfo(url); 397 398 return (imageExtensions.indexOf(fileInfo.extension) !== -1); 399 400 }; 401 402 // https://stackoverflow.com/a/13896633 403 // TODO: make work with ?x[a]=2&x[b]=3 404 CP_Customizer.utils.parseUrlQuery = function (str) { 405 if (typeof str !== "string" || str.length === 0) return {}; 406 var s = str.split("&"); 407 var s_length = s.length; 408 var bit, query = {}, first, second; 409 for (var i = 0; i < s_length; i++) { 410 bit = s[i].split("="); 411 first = decodeURIComponent(bit[0]); 412 if (first.length === 0) continue; 413 second = decodeURIComponent(bit[1]); 414 if (typeof query[first] === "undefined") query[first] = second; 415 else if (query[first] instanceof Array) query[first].push(second); 416 else query[first] = [query[first], second]; 417 } 418 return query; 419 }; 420 421 422 CP_Customizer.utils.stringifyUrlQuery = function (query) { 423 var queryString = ""; 424 for (var key in query) { 425 426 if (!query.hasOwnProperty(key)) { 427 continue; 428 } 429 430 var data = query[key]; 431 432 if (!_.isUndefined(data)) { 433 if (_.isString(data)) { 434 queryString += '&' + encodeURIComponent(key) + '=' + encodeURIComponent(data); 435 } 436 437 if (_.isArray(data)) { 438 for (var i = 0; i < data.length; i++) { 439 queryString += '&' + encodeURIComponent(key) + '[' + i + ']=' + encodeURIComponent(data[i]); 440 } 441 } 442 443 } else { 444 queryString += '&' + encodeURIComponent(key); 445 } 446 } 447 448 if (queryString.length) { 449 queryString = '?' + CP_Customizer.utils.phpTrim(queryString, '&'); 450 } 451 452 return queryString; 453 }; 454 455 CP_Customizer.utils.parseURL = function (url) { 456 var location = ((url.split('?')[0] || '').split('#')[0] || ''), 457 queryString = (url.indexOf('?') !== -1) ? url.split('?').pop().split('#')[0] : '', 458 query = CP_Customizer.utils.parseUrlQuery(queryString), 459 hash = (url.indexOf('#') !== -1) ? url.replace(/(.*)#/, '').trim() : ''; 460 461 return { 462 location: location.replace(/\/$/, ''), 463 query: query, 464 hash: hash.length ? '#' + hash : '' 465 } 466 467 }; 468 469 CP_Customizer.utils.removeUrlQueryStrings = function (url, strings) { 470 var parsedUrl = CP_Customizer.utils.parseURL(url), 471 hash = parsedUrl.hash, 472 queryKeys = Object.getOwnPropertyNames(parsedUrl.query), 473 query = {}; 474 475 for (var i = 0; i < queryKeys.length; i++) { 476 var key = queryKeys[i]; 477 if (strings.indexOf(key) === -1) { 478 query[key] = parsedUrl.query[key]; 479 } 480 } 481 482 var queryString = CP_Customizer.utils.stringifyUrlQuery(query); 483 484 if (!queryString.length) { 485 queryString = "/"; 486 } 487 488 return parsedUrl.location + queryString + hash; 489 }; 490 491 CP_Customizer.utils.nodeMatchingClasses = function (node, classList, firstMatchOnly) { 492 493 if (!$(node).length) { 494 if (firstMatchOnly) { 495 return undefined; 496 } 497 return []; 498 } 499 500 result = Array.from($(node)[0].classList).filter(function (_class) { 501 return (classList.indexOf(_class) !== -1); 502 }); 503 504 if (firstMatchOnly) { 505 if (result.length) { 506 result = result[0]; 507 } else { 508 result = undefined; 509 } 510 } 511 512 return result; 513 }; 514 515 CP_Customizer.utils.colorInArray = function (colorsArray, color, includeAlpha) { 516 var inArray = false; 517 color = tinycolor(color); 518 519 for (var i = 0; i < colorsArray.length; i++) { 520 521 var _color = tinycolor(colorsArray[i]); 522 inArray = (color._r === _color._r) && (color._g === _color._g) && (color._b === _color._b); 523 524 if (includeAlpha) { 525 inArray = inArray && (color._a === _color._a); 526 } 527 528 if (inArray) { 529 break; 530 } 531 } 532 533 return inArray; 534 535 } 536 537 CP_Customizer.utils.valueToBool = function (value) { 538 if (_.isBoolean(value)) { 539 return value; 540 } 541 542 if (_.isString(value)) { 543 544 var _v = value.toLowerCase(); 545 if (_v === "yes" || _v === "true") { 546 return true; 547 } 548 549 if (_v === "no" || _v === "false") { 550 return false; 551 } 552 } 553 554 555 if (!isNaN(value)) { 556 return !!parseInt(value); 557 } 558 559 return !!value; 560 } 561 562 563 CP_Customizer.utils.convertColor = { 564 toRGB: function (color) { 565 return tinycolor(color).toRgbString(); 566 }, 567 toRGBA: function (color, alpha) { 568 return tinycolor(color).setAlpha(alpha).toRgbString(); 569 }, 570 toHex: function (color) { 571 return tinycolor(color).toHexString(); 572 }, 573 brighten: function (color, value) { 574 return tinycolor(color).brighten(value).toRgbString(); 575 } 576 } 577 578 CP_Customizer.hasClass = function (element, classes) { 579 var elementClasses = Array.from($(element)[0].classList); 580 } 581 }); 582 })(jQuery);