vendor: 6,042 bytes, lines 1-189
1/** Highest positive signed 32-bit float value */ 2const maxInt = 2147483647; // aka. 0x7FFFFFFF or 2^31-1 3 4/** Bootstring parameters */ 5const base = 36; 6const tMin = 1; 7const tMax = 26; 8const skew = 38; 9const damp = 700; 10const initialBias = 72; 11const initialN = 128; // 0x80 12const delimiter = '-'; // '\x2D' 13 14/** Regular expressions */ 15const regexPunycode = /^xn--/; 16const regexNonASCII = /[^\0-\x7F]/; // Note: U+007F DEL is excluded too. 17const regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g; // RFC 3490 separators 18 19/** Error messages */ 20const errors = { 21 'overflow': 'Overflow: input needs wider integers to process', 22 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', 23 'invalid-input': 'Invalid input' 24}; 25 26/** Convenience shortcuts */ 27const baseMinusTMin = base - tMin; 28const floor = Math.floor; 29const stringFromCharCode = String.fromCharCode; 30 31/*--------------------------------------------------------------------------*/ 32 33/** 34 * A generic error utility function. 35 * @private 36 * @param {String} type The error type. 37 * @returns {Error} Throws a `RangeError` with the applicable error message. 38 */ 39function error(type) { 40 throw new RangeError(errors[type]); 41} 42 43/** 44 * A generic `Array#map` utility function. 45 * @private 46 * @param {Array} array The array to iterate over. 47 * @param {Function} callback The function that gets called for every array 48 * item. 49 * @returns {Array} A new array of values returned by the callback function. 50 */ 51function map(array, callback) { 52 const result = []; 53 let length = array.length; 54 while (length--) { 55 result[length] = callback(array[length]); 56 } 57 return result; 58} 59 60/** 61 * A simple `Array#map`-like wrapper to work with domain name strings or email 62 * addresses. 63 * @private 64 * @param {String} domain The domain name or email address. 65 * @param {Function} callback The function that gets called for every 66 * character. 67 * @returns {String} A new string of characters returned by the callback 68 * function. 69 */ 70function mapDomain(domain, callback) { 71 const parts = domain.split('@'); 72 let result = ''; 73 if (parts.length > 1) { 74 // In email addresses, only the domain name should be punycoded. Leave 75 // the local part (i.e. everything up to `@`) intact. 76 result = parts[0] + '@'; 77 domain = parts[1]; 78 } 79 // Avoid `split(regex)` for IE8 compatibility. See #17. 80 domain = domain.replace(regexSeparators, '\x2E'); 81 const labels = domain.split('.'); 82 const encoded = map(labels, callback).join('.'); 83 return result + encoded; 84} 85 86/** 87 * Creates an array containing the numeric code points of each Unicode 88 * character in the string. While JavaScript uses UCS-2 internally, 89 * this function will convert a pair of surrogate halves (each of which 90 * UCS-2 exposes as separate characters) into a single code point, 91 * matching UTF-16. 92 * @see `punycode.ucs2.encode` 93 * @see <https://mathiasbynens.be/notes/javascript-encoding> 94 * @memberOf punycode.ucs2 95 * @name decode 96 * @param {String} string The Unicode input string (UCS-2). 97 * @returns {Array} The new array of code points. 98 */ 99function ucs2decode(string) { 100 const output = []; 101 let counter = 0; 102 const length = string.length; 103 while (counter < length) { 104 const value = string.charCodeAt(counter++); 105 if (value >= 0xD800 && value <= 0xDBFF && counter < length) { 106 // It's a high surrogate, and there is a next character. 107 const extra = string.charCodeAt(counter++); 108 if ((extra & 0xFC00) == 0xDC00) { 109 // Low surrogate. 110 output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); 111 } else { 112 // It's an unmatched surrogate; only append this code unit, in case the 113 // next code unit is the high surrogate of a surrogate pair. 114 output.push(value); 115 counter--; 116 } 117 } else { 118 output.push(value); 119 } 120 } 121 return output; 122} 123 124/** 125 * Creates a string based on an array of numeric code points. 126 * @see `punycode.ucs2.decode` 127 * @memberOf punycode.ucs2 128 * @name encode 129 * @param {Array} codePoints The array of numeric code points. 130 * @returns {String} The new Unicode string (UCS-2). 131 */ 132const ucs2encode = codePoints => String.fromCodePoint(...codePoints); 133 134/** 135 * Converts a basic code point into a digit/integer. 136 * @see `digitToBasic()` 137 * @private 138 * @param {Number} codePoint The basic numeric code point value. 139 * @returns {Number} The numeric value of a basic code point (for use in 140 * representing integers) in the range `0` to `base - 1`, or `base` if 141 * the code point does not represent a value. 142 */ 143const basicToDigit = function basicToDigit(codePoint) { 144 if (codePoint >= 0x30 && codePoint < 0x3A) { 145 return 26 + (codePoint - 0x30); 146 } 147 if (codePoint >= 0x41 && codePoint < 0x5B) { 148 return codePoint - 0x41; 149 } 150 if (codePoint >= 0x61 && codePoint < 0x7B) { 151 return codePoint - 0x61; 152 } 153 return base; 154}; 155 156/** 157 * Converts a digit/integer into a basic code point. 158 * @see `basicToDigit()` 159 * @private 160 * @param {Number} digit The numeric value of a basic code point. 161 * @returns {Number} The basic code point whose value (when used for 162 * representing integers) is `digit`, which needs to be in the range 163 * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is 164 * used; else, the lowercase form is used. The behavior is undefined 165 * if `flag` is non-zero and `digit` has no uppercase form. 166 */ 167const digitToBasic = function digitToBasic(digit, flag) { 168 // 0..25 map to ASCII a..z or A..Z 169 // 26..35 map to ASCII 0..9 170 return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); 171}; 172 173/** 174 * Bias adaptation function as per section 3.4 of RFC 3492. 175 * https://tools.ietf.org/html/rfc3492#section-3.4 176 * @private 177 */ 178const adapt = function adapt(delta, numPoints, firstTime) { 179 let k = 0; 180 delta = firstTime ? floor(delta / damp) : delta >> 1; 181 delta += floor(delta / numPoints); 182 for /* no initialization */ 183 (; delta > baseMinusTMin * tMax >> 1; k += base) { 184 delta = floor(delta / baseMinusTMin); 185 } 186 return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); 187}; 188 189/**
190 * Converts a Punycode string of ASCII-only symbols to a string of Unicode 191 * symbols. 192 * @memberOf punycode 193 * @param {String} input The Punycode string of ASCII-only symbols. 194 * @returns {String} The resulting string of Unicode symbols. 195 */ 196const decode = function decode(input) { 197 // Don't use UCS-2. 198 const output = []; 199 const inputLength = input.length; 200 let i = 0; 201 let n = initialN; 202 let bias = initialBias; 203 204 // Handle the basic code points: let `basic` be the number of input code 205 // points before the last delimiter, or `0` if there is none, then copy 206 // the first basic code points to the output. 207 208 let basic = input.lastIndexOf(delimiter); 209 if (basic < 0) { 210 basic = 0; 211 } 212 for (let j = 0; j < basic; ++j) { 213 // if it's not a basic code point 214 if (input.charCodeAt(j) >= 0x80) { 215 error('not-basic'); 216 } 217 output.push(input.charCodeAt(j)); 218 } 219 220 // Main decoding loop: start just after the last delimiter if any basic code 221 // points were copied; start at the beginning otherwise. 222 223 for /* no final expression */ 224 (let index = basic > 0 ? basic + 1 : 0; index < inputLength;) { 225 // `index` is the index of the next character to be consumed. 226 // Decode a generalized variable-length integer into `delta`, 227 // which gets added to `i`. The overflow checking is easier 228 // if we increase `i` as we go, then subtract off its starting 229 // value at the end to obtain `delta`. 230 const oldi = i; 231 for /* no condition */ 232 (let w = 1, k = base;; k += base) { 233 if (index >= inputLength) { 234 error('invalid-input'); 235 } 236 const digit = basicToDigit(input.charCodeAt(index++)); 237 if (digit >= base) { 238 error('invalid-input'); 239 } 240 if (digit > floor((maxInt - i) / w)) { 241 error('overflow'); 242 } 243 i += digit * w; 244 const t = k <= bias ? tMin : k >= bias + tMax ? tMax : k - bias; 245 if (digit < t) { 246 break; 247 } 248 const baseMinusT = base - t; 249 if (w > floor(maxInt / baseMinusT)) { 250 error('overflow'); 251 } 252 w *= baseMinusT; 253 } 254 const out = output.length + 1; 255 bias = adapt(i - oldi, out, oldi == 0); 256 257 // `i` was supposed to wrap around from `out` to `0`, 258 // incrementing `n` each time, so we'll fix that now: 259 if (floor(i / out) > maxInt - n) { 260 error('overflow'); 261 } 262 n += floor(i / out); 263 i %= out; 264 265 // Insert `n` at position `i` of the output. 266 output.splice(i++, 0, n); 267 } 268 return String.fromCodePoint(...output); 269}; 270 271/** 272 * Converts a string of Unicode symbols (e.g. a domain name label) to a 273 * Punycode string of ASCII-only symbols. 274 * @memberOf punycode 275 * @param {String} input The string of Unicode symbols. 276 * @returns {String} The resulting Punycode string of ASCII-only symbols. 277 */ 278const encode = function encode(input) { 279 const output = []; 280 281 // Convert the input in UCS-2 to an array of Unicode code points. 282 input = ucs2decode(input); 283 284 // Cache the length. 285 const inputLength = input.length; 286 287 // Initialize the state. 288 let n = initialN; 289 let delta = 0; 290 let bias = initialBias; 291 292 // Handle the basic code points. 293 for (const currentValue of input) { 294 if (currentValue < 0x80) { 295 output.push(stringFromCharCode(currentValue)); 296 } 297 } 298 const basicLength = output.length; 299 let handledCPCount = basicLength; 300 301 // `handledCPCount` is the number of code points that have been handled; 302 // `basicLength` is the number of basic code points. 303 304 // Finish the basic string with a delimiter unless it's empty. 305 if (basicLength) { 306 output.push(delimiter); 307 } 308 309 // Main encoding loop: 310 while (handledCPCount < inputLength) { 311 // All non-basic code points < n have been handled already. Find the next 312 // larger one: 313 let m = maxInt; 314 for (const currentValue of input) { 315 if (currentValue >= n && currentValue < m) { 316 m = currentValue; 317 } 318 } 319 320 // Increase `delta` enough to advance the decoder's <n,i> state to <m,0>, 321 // but guard against overflow. 322 const handledCPCountPlusOne = handledCPCount + 1; 323 if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { 324 error('overflow'); 325 } 326 delta += (m - n) * handledCPCountPlusOne; 327 n = m; 328 for (const currentValue of input) { 329 if (currentValue < n && ++delta > maxInt) { 330 error('overflow'); 331 } 332 if (currentValue === n) { 333 // Represent delta as a generalized variable-length integer. 334 let q = delta; 335 for /* no condition */ 336 (let k = base;; k += base) { 337 const t = k <= bias ? tMin : k >= bias + tMax ? tMax : k - bias; 338 if (q < t) { 339 break; 340 } 341 const qMinusT = q - t; 342 const baseMinusT = base - t; 343 output.push(stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))); 344 q = floor(qMinusT / baseMinusT); 345 } 346 output.push(stringFromCharCode(digitToBasic(q, 0))); 347 bias = adapt(delta, handledCPCountPlusOne, handledCPCount === basicLength); 348 delta = 0; 349 ++handledCPCount; 350 } 351 } 352 ++delta; 353 ++n; 354 } 355 return output.join(''); 356}; 357 358/** 359 * Converts a Punycode string representing a domain name or an email address 360 * to Unicode. Only the Punycoded parts of the input will be converted, i.e. 361 * it doesn't matter if you call it on a string that has already been 362 * converted to Unicode. 363 * @memberOf punycode 364 * @param {String} input The Punycoded domain name or email address to 365 * convert to Unicode. 366 * @returns {String} The Unicode representation of the given Punycode
367 * string. 368 */ 369const toUnicode = function toUnicode(input) { 370 return mapDomain(input, function (string) { 371 return regexPunycode.test(string) ? decode(string.slice(4).toLowerCase()) : string; 372 }); 373}; 374 375/** 376 * Converts a Unicode string representing a domain name or an email address to 377 * Punycode. Only the non-ASCII parts of the domain name will be converted, 378 * i.e. it doesn't matter if you call it with a domain that's already in 379 * ASCII. 380 * @memberOf punycode 381 * @param {String} input The domain name or email address to convert, as a 382 * Unicode string. 383 * @returns {String} The Punycode representation of the given domain name or 384 * email address. 385 */ 386const toASCII = function toASCII(input) { 387 return mapDomain(input, function (string) { 388 return regexNonASCII.test(string) ? 'xn--' + encode(string) : string; 389 }); 390}; 391 392/*--------------------------------------------------------------------------*/ 393 394/** Define the public API */ 395const punycode = { 396 /** 397 * A string representing the current Punycode.js version number. 398 * @memberOf punycode
399 * @type String 400 */ 401 'version': '2.3.1', 402 /** 403 * An object of methods to convert from JavaScript's internal character 404 * representation (UCS-2) to Unicode code points, and back. 405 * @see <https://mathiasbynens.be/notes/javascript-encoding> 406 * @memberOf punycode 407 * @type Object 408 */ 409 'ucs2': { 410 'decode': ucs2decode, 411 'encode': ucs2encode 412 }, 413 'decode': decode, 414 'encode': encode, 415 'toASCII': toASCII, 416 'toUnicode': toUnicode 417}; 418 419/** 420 * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> 421 * @license GNU General Public License version 2 or later; see LICENSE.txt 422 */ 423class JFormValidator { 424 constructor() { 425 this.customValidators = {}; 426 this.handlers = []; 427 this.handlers = {}; 428 this.removeMarking = this.removeMarking.bind(this); 429 this.inputEmail = () => { 430 const input = document.createElement('input'); 431 input.setAttribute('type', 'email'); 432 return input.type !== 'text'; 433 }; 434 435 // Default handlers 436 this.setHandler('username', value => { 437 const regex = /[<|>|"|'|%|;|(|)|&]/i; 438 return !regex.test(value); 439 }); 440 this.setHandler('password', value => { 441 const regex = /^\S[\S ]{2,98}\S$/; 442 return regex.test(value); 443 }); 444 this.setHandler('numeric', value => { 445 const regex = /^(\d|-)?(\d|,)*\.?\d*$/; 446 return regex.test(value); 447 }); 448 this.setHandler('email', value => { 449 const newValue = punycode.toASCII(value); 450 const regex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/; 451 return regex.test(newValue); 452 }); 453 454 // Attach all forms with a class 'form-validate' 455 document.querySelectorAll('form').forEach(form => { 456 if (form.classList.contains('form-validate')) { 457 this.attachToForm(form); 458 } 459 }); 460 } 461 get custom() { 462 return this.customValidators; 463 } 464 set custom(value) { 465 this.customValidators = value; 466 } 467 setHandler(name, func, en) { 468 const isEnabled = en === '' ? true : en; 469 this.handlers[name] = { 470 enabled: isEnabled, 471 exec: func 472 }; 473 } 474 markValid(element) { 475 // Get a label 476 const label = element.form.querySelector(`label[for="${element.id}"]`); 477 let message; 478 if (element.classList.contains('required') || element.getAttribute('required')) { 479 if (label) { 480 message = label.querySelector('span.form-control-feedback'); 481 } 482 } 483 element.classList.remove('form-control-danger', 'invalid'); 484 element.classList.add('form-control-success'); 485 element.parentNode.classList.remove('has-danger'); 486 element.parentNode.classList.add('has-success'); 487 element.setAttribute('aria-invalid', 'false'); 488 489 // Remove message 490 if (message) { 491 message.parentNode.removeChild(message); 492 } 493 494 // Restore Label 495 if (label) { 496 label.classList.remove('invalid'); 497 } 498 } 499 markInvalid(element, empty) { 500 // Get a label 501 const label = element.form.querySelector(`label[for="${element.id}"]`); 502 element.classList.remove('form-control-success', 'valid'); 503 element.classList.add('form-control-danger', 'invalid'); 504 element.parentNode.classList.remove('has-success'); 505 element.parentNode.classList.add('has-danger'); 506 element.setAttribute('aria-invalid', 'true'); 507 508 // Display custom message 509 let mesgCont; 510 const message = element.getAttribute('data-validation-text'); 511 if (label) { 512 mesgCont = label.querySelector('span.form-control-feedback'); 513 } 514 if (!mesgCont) { 515 const elMsg = document.createElement('span'); 516 elMsg.classList.add('form-control-feedback'); 517 if (empty && empty === 'checkbox') { 518 elMsg.innerHTML = message !== null ? Joomla.sanitizeHtml(message) : Joomla.sanitizeHtml(Joomla.Text._('JLIB_FORM_FIELD_REQUIRED_CHECK')); 519 } else if (empty && empty === 'value') { 520 elMsg.innerHTML = message !== null ? Joomla.sanitizeHtml(message) : Joomla.sanitizeHtml(Joomla.Text._('JLIB_FORM_FIELD_REQUIRED_VALUE')); 521 } else { 522 elMsg.innerHTML = message !== null ? Joomla.sanitizeHtml(message) : Joomla.sanitizeHtml(Joomla.Text._('JLIB_FORM_FIELD_INVALID_VALUE')); 523 } 524 if (label) { 525 label.appendChild(elMsg); 526 } 527 } 528 529 // Mark the Label as well 530 if (label) { 531 label.classList.add('invalid'); 532 } 533 } 534 removeMarking(element) { 535 // Get the associated label 536 let message; 537 const label = element.form.querySelector(`label[for="${element.i
537d}"]`); 538 if (label) { 539 message = label.querySelector('span.form-control-feedback'); 540 } 541 element.classList.remove('form-control-danger', 'form-control-success', 'remove'); 542 element.classList.add('valid'); 543 element.parentNode.classList.remove('has-danger', 'has-success'); 544 545 // Remove message 546 if (message && label) { 547 label.removeChild(message); 548 } 549 550 // Restore Label 551 if (label) { 552 label.classList.remove('invalid'); 553 } 554 } 555 handleResponse(state, element, empty) { 556 const tagName = element.tagName.toLowerCase(); 557 558 // Set the element and its label (if exists) invalid state 559 if (tagName !== 'button' && element.value !== undefined || tagName === 'fieldset') { 560 if (state === false) { 561 this.markInvalid(element, empty); 562 } else { 563 this.markValid(element); 564 } 565 } 566 } 567 validate(element) { 568 let tagName; 569 570 // Ignore the element if its currently disabled, 571 // because are not submitted for the http-request. 572 // For those case return always true. 573 if (element.getAttribute('disabled') === 'disabled' || element.getAttribute('display') === 'none') { 574 this.handleResponse(true, element); 575 return true; 576 } 577 // If the field is required make sure it has a value 578 if (element.getAttribute('required') || element.classList.contains('required')) { 579 tagName = element.tagName.toLowerCase(); 580 if (tagName === 'fieldset' && (element.classList.contains('radio') || element.classList.contains('checkboxes'))) { 581 // No options are checked. 582 if (element.querySelector('input:checked') === null) { 583 this.handleResponse(false, element, 'checkbox'); 584 return false; 585 } 586 } else if (element.getAttribute('type') === 'checkbox' && element.checked !== true || tagName === 'select' && !element.value.length) { 587 this.handleResponse(false, element, 'checkbox'); 588 return false; 589 } else if (!element.value || element.classList.contains('placeholder')) { 590 // If element has class placeholder that means it is empty. 591 this.handleResponse(false, element, 'value'); 592 return false; 593 } 594 } 595 596 // Only validate the field if the validate class is set 597 const handler = element.getAttribute('class') && element.getAttribute('class').match(/validate-([a-zA-Z0-9_-]+)/) ? element.getAttribute('class').match(/validate-([a-zA-Z0-9_-]+)/)[1] : ''; 598 if (element.getAttribute('pattern') && element.getAttribute('pattern') !== '') { 599 if (element.value.length) { 600 const isValid = new RegExp(`^${element.getAttribute('pattern')}$`).test(element.value); 601 this.handleResponse(isValid, element, 'empty'); 602 return isValid; 603 } 604 if (element.hasAttribute('required') || element.classList.contains('required')) { 605 this.handleResponse(false, element, 'empty'); 606 return false; 607 } 608 this.handleResponse(true, element); 609 return true; 610 } 611 if (handler === '') { 612 this.handleResponse(true, element); 613 return true; 614 } 615 616 // Check the additional validation types 617 if (handler && handler !== 'none' && this.handlers[handler] && element.value) { 618 // Execute the validation handler and return result 619 if (this.handlers[handler].exec(element.value, element) !== true) { 620 this.handleResponse(false, element, 'invalid_value'); 621 return false; 622 } 623 } 624 625 // Return validation state 626 this.handleResponse(true, element); 627 return true; 628 } 629 isValid(form) { 630 let valid = true; 631 let message; 632 let error; 633 let fields; 634 const invalid = []; 635 636 // Validate form fields 637 if (form.nodeName === 'FORM') { 638 fields = [].slice.call(form.elements); 639 } else { 640 fields = form.querySelectorAll('input, textarea, select, button, fieldset'); 641 } 642 fields.forEach(field => { 643 if (this.validate(field) === false) { 644 valid = false; 645 invalid.push(field); 646 } 647 }); 648 649 // Run custom form validators if present 650 if (Object.keys(this.customValidators).length) {
651 Object.keys(this.customValidators).forEach(key => { 652 if (this.customValidators[key].exec() !== true) { 653 valid = false; 654 } 655 }); 656 } 657 if (!valid && invalid.length > 0) { 658 if (form.getAttribute('data-validation-text')) { 659 message = form.getAttribute('data-validation-text'); 660 } else { 661 message = Joomla.Text._('JLIB_FORM_CONTAINS_INVALID_FIELDS'); 662 } 663 error = { 664 error: [message] 665 }; 666 Joomla.renderMessages(error); 667 } 668 return valid; 669 } 670 attachToForm(form) { 671 let elements; 672 if (form.nodeName === 'FORM') { 673 elements = [].slice.call(form.elements); 674 } else { 675 elements = form.querySelectorAll('input, textarea, select, button, fieldset'); 676 } 677 678 // Iterate through the form object and attach the validate method to all input fields. 679 elements.forEach(element => { 680 const tagName = element.tagName.toLowerCase(); 681 if (['input', 'textarea', 'select', 'fieldset'].indexOf(tagName) > -1 && element.classList.contains('required')) { 682 element.setAttribute('required', ''); 683 } 684 685 // Attach isValid method to submit button 686 if ((tagName === 'input' || tagName === 'button') && (element.getAttribute('type') === 'submit' || element.getAttribute('type') === 'image')) { 687 if (element.classList.contains('validate')) { 688 element.addEventListener('click', () => this.isValid(form)); 689 } 690 } else if (tagName !== 'button' && !(tagName === 'input' && element.getAttribute('type') === 'button')) { 691 // Attach validate method only to fields 692 if (tagName !== 'fieldset') { 693 element.addEventListener('blur', ({ 694 target 695 }) => this.validate(target)); 696 element.addEventListener('focus', ({ 697 target 698 }) => this.removeMarking(target)); 699 if (element.classList.contains('validate-email') && this.inputEmail) { 700 element.setAttribute('type', 'email'); 701 } 702 } 703 } 704 }); 705 } 706} 707document.formvalidator = new JFormValidator(); 708 709/** 710 * Expose the classes to the global scope 711 * These will be removed in Joomla! 6.0 712 */ 713window.JFormValidator = JFormValidator; 714window.punycode = punycode;
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.