Created
August 20, 2024 07:38
-
-
Save jevinskie/240d9343a5230468664dbe74a5a9d170 to your computer and use it in GitHub Desktop.
SafariShared.framework embedded JavaScript and HTML - iOS 18.0 beta 6 22A5338b
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // # sourceURL=__InjectedScript_AutomaticPasswords.js | |
| /* Copyright (c) 2024 Apple Inc. All rights reserved. */ | |
| FormMetadata.prototype._collectExtraControlMetadata = function(t, o) { | |
| let e = t.getAttribute("passwordrules"); | |
| o.ControlPasswordRules = e || void 0 | |
| }, FormMetadata.prototype.removeAutomaticStrongPasswordFromPasswordElement = function(t) { | |
| let o = this.formControlWithUniqueID(t); | |
| o && this._isTextField(o) && (this.clearField(t), this._updateAnnotationsForField(o), FormMetadataJSController.setInputElementAutofilled(o, !1)) | |
| }; | |
| let AutomaticPasswords = function() {}; | |
| AutomaticPasswords.prototype = { | |
| removeAutomaticPasswordElements : function(t, o, e) { | |
| for (let o of t) | |
| FormMetadataJS.removeAutomaticStrongPasswordFromPasswordElement(o); | |
| if (!e) | |
| return; | |
| let r = document.activeElement, | |
| a = o ? FormMetadataJS.formControlWithUniqueID(o) : null; | |
| a && a.blur(), a && a === r && a.focus() | |
| }, | |
| blurControlWithID : function(t) { | |
| let o = t ? FormMetadataJS.formControlWithUniqueID(t) : null; | |
| o && o.blur() | |
| }, | |
| setStrongPasswordElementViewableIfAppropriate : function(t, o) { | |
| for (let e of t) { | |
| let t = FormMetadataJS.formControlWithUniqueID(e); | |
| if (!t) | |
| return; | |
| if ("text" === t.type) | |
| return FormMetadataJSController.setInputElementAutoFilledAndViewable(t, !1), void FormMetadataJSController.setInputElementAutofilled(t, !1); | |
| FormMetadataJSController.setInputElementAutoFilledAndViewable(t, o) | |
| } | |
| } | |
| }; | |
| var AutomaticPasswordsJS = new AutomaticPasswords; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <meta http-equiv="content-type" content="text/html; charset=utf-8"> | |
| <meta name="viewport" content="width=device-width, viewport-fit=cover"> | |
| <title class="l12n">This Connection Is Not Private</title> | |
| <style> | |
| body { | |
| --font-color: #434343; | |
| --compact-font-color: #434343; | |
| --blue-color: rgb(0, 122, 255); | |
| --horizontal-padding: 32px; | |
| --compact-horizontal-padding: 20px; | |
| --border-radius: 6px; | |
| --ios-border-radius: 10px; | |
| --title-color: #444; | |
| --icon-element-color: #dc143c; | |
| } | |
| * { | |
| padding: 0; | |
| margin: 0; | |
| } | |
| body:not(.ios) * { | |
| font-family: -apple-system-font; | |
| } | |
| html, body { | |
| height: 100%; | |
| width: 100%; | |
| } | |
| body { | |
| font-size: 13px; | |
| background: linear-gradient(30deg, #dfdfdf 0%, #fafafb 100%); | |
| background-repeat: no-repeat; | |
| background-attachment: fixed; | |
| cursor: default; | |
| -webkit-user-select: none; | |
| } | |
| #title { | |
| overflow: hidden; | |
| color: var(--title-color); | |
| padding-top: 3px; | |
| } | |
| .alert { | |
| background-color: white; | |
| min-width: 320px; | |
| max-width: 672px; | |
| position: relative; | |
| margin: 0 auto; | |
| padding-top: 28px; | |
| border-radius: var(--border-radius); | |
| box-shadow: 0px 6px 10px rgba(0, 0, 0, 0.14); | |
| } | |
| .alert-body { | |
| margin: 21px 0 0 0; | |
| padding-left: var(--horizontal-padding); | |
| padding-right: var(--horizontal-padding); | |
| padding-bottom: 24px; | |
| color: var(--font-color); | |
| } | |
| .alert-body p:first-of-type { | |
| margin-bottom: 15px; | |
| margin-top: 20px; | |
| } | |
| .alert-body p:last-of-type { | |
| margin-bottom: 0; | |
| } | |
| .bottom-bar { | |
| margin-top: 1.3em; | |
| height: 22px; | |
| } | |
| .bottom-bar button { | |
| float: right; | |
| font-size: 13px; | |
| line-height: 21px; | |
| min-width: 90px; | |
| margin: 0 4px; | |
| vertical-align: bottom; | |
| padding: 0 12px; | |
| } | |
| .bottom-bar .details { | |
| float: left; | |
| } | |
| .bottom-bar .details a { | |
| cursor: pointer; | |
| font-size: 14px; | |
| margin-top: 2px; | |
| } | |
| #details { | |
| display: none; | |
| padding: 22px var(--horizontal-padding) 10px var(--horizontal-padding); | |
| border-top: 1px solid rgb(217, 217, 217); | |
| color: var(--font-color); | |
| background-color: rgb(243, 243, 243); | |
| border-bottom-left-radius: var(--border-radius); | |
| border-bottom-right-radius: var(--border-radius); | |
| } | |
| .bottom-bar.goBack .closePage, .bottom-bar.closePage .goBack, #ignoreWarning { | |
| display: block; | |
| } | |
| #openDateAndTimeButton { | |
| display: none; | |
| } | |
| a { | |
| color: inherit; | |
| text-decoration: underline; | |
| cursor: pointer; | |
| } | |
| #lock, #clock { | |
| float: left; | |
| width: 30px; | |
| top: 4px; | |
| margin-right: 15px; | |
| position: relative; | |
| } | |
| #clock { | |
| display: none; | |
| } | |
| .lock-element { | |
| fill: var(--icon-element-color); | |
| } | |
| .clock-element { | |
| fill: var(--icon-element-color); | |
| } | |
| body.clockWarning #clock { | |
| display: block; | |
| } | |
| body.clockWarning #lock { | |
| display: none; | |
| } | |
| body.clockWarning #goBackButton { | |
| display: none; | |
| } | |
| body.clockWarning #openDateAndTimeButton { | |
| display: block; | |
| } | |
| h1 { | |
| font-size: 2em; | |
| font-weight: 700; | |
| line-height: 30px; | |
| padding: 0 var(--horizontal-padding); | |
| margin-bottom: -6px; | |
| } | |
| p { | |
| font-size: 14px; | |
| line-height: 19px; | |
| margin-bottom: 1em; | |
| word-wrap: break-word; | |
| } | |
| body.ios .alert { | |
| box-shadow: none; | |
| border-radius: var(--ios-border-radius); | |
| max-width: 640px; | |
| } | |
| body.ios .alert-body { | |
| font: -apple-system-body; | |
| } | |
| body.ios #details { | |
| font: -apple-system-body; | |
| border-bottom-left-radius: var(--ios-border-radius); | |
| border-bottom-right-radius: var(--ios-border-radius); | |
| } | |
| body.ios h1 { | |
| font-size: 26px; | |
| font-family: -webkit-system-font; | |
| } | |
| body.ios p { | |
| font-size: 1.1em; | |
| line-height: unset; | |
| } | |
| body.ios button { | |
| background: none; | |
| border: none; | |
| color: var(--blue-color); | |
| font: -apple-system-short-body; | |
| } | |
| body.ios #detailsButton { | |
| color: var(--font-color); | |
| } | |
| @media screen and (max-width: 666px) { | |
| /* iPhone 6 in landscape (667px) and smaller, including all iPhones in portrait */ | |
| body { | |
| color: var(--compact-font-color); | |
| } | |
| .alert { | |
| box-shadow: none; | |
| background-color: var(--red-color); | |
| } | |
| .alert-body { | |
| color: var(--compact-font-color); | |
| padding-left: var(--compact-horizontal-padding); | |
| padding-right: var(--compact-horizontal-padding); | |
| padding-bottom: 30px; | |
| } | |
| h1 { | |
| color: var(--compact-font-color); | |
| padding: 0 var(--compact-horizontal-padding); | |
| } | |
| body.ios button, | |
| body.ios #detailsButton { | |
| text-decoration: underline; | |
| } | |
| #details { | |
| background-color: var(--red-color); | |
| padding: 22px var(--compact-horizontal-padding) 22px var(--compact-horizontal-padding); | |
| border-top-width: 1px; | |
| border-top-color: rgba(0, 0, 0, .15); | |
| } | |
| } | |
| /* RTL support */ | |
| html[dir="rtl"] .bottom-bar button { | |
| float: left; | |
| } | |
| html[dir="rtl"] :matches(#lock, #clock) { | |
| float: right; | |
| margin-left: 15px; | |
| margin-right: 0; | |
| } | |
| </style> | |
| <link rel=stylesheet type="text/css" href="safari-resource:/CertificateWarningExtras.css"> | |
| <script type="text/javascript" src="safari-resource:/Utilities.js" charset="utf-8"></script> | |
| <script type="text/javascript" src="safari-resource:/WBSHTMLViewController.js" charset="utf-8"></script> | |
| <script type="text/javascript"> | |
| // Should be kept in sync with WBSCertificateWarningCategory in WBSCertificateWarningPageContext.h. | |
| var CertificateWarningCategory = { | |
| Expired: 0, | |
| InvalidCanBypass: 1, | |
| InvalidCannotBypass: 2, | |
| HostnameMismatch: 3, | |
| IncorrectClock: 4, | |
| LegacyTLS: 5, | |
| }; | |
| var CertificateWarning = { | |
| _host: undefined, | |
| _canGoBack: undefined, | |
| _warningCategory: undefined, | |
| _numberOfDaysInvalid: undefined, | |
| _expiredCertificateDetails: undefined, | |
| _clockSkew: undefined, | |
| get host() | |
| { | |
| return this._host; | |
| }, | |
| set host(value) | |
| { | |
| if (this._host === value) | |
| return; | |
| this._host = value; | |
| }, | |
| get canGoBack() | |
| { | |
| return this._canGoBack; | |
| }, | |
| set canGoBack(value) | |
| { | |
| if (this._canGoBack === value) | |
| return; | |
| this._canGoBack = value; | |
| }, | |
| get warningCategory() | |
| { | |
| return this._warningCategory; | |
| }, | |
| set warningCategory(value) | |
| { | |
| if (this._warningCategory === value) | |
| return; | |
| this._warningCategory = value; | |
| }, | |
| get numberOfDaysInvalid() | |
| { | |
| return this._numberOfDaysInvalid; | |
| }, | |
| set numberOfDaysInvalid(value) | |
| { | |
| if (this._numberOfDaysInvalid === value) | |
| return; | |
| this._numberOfDaysInvalid = value; | |
| }, | |
| get expiredCertificateDetails() | |
| { | |
| return this._expiredCertificateDetails; | |
| }, | |
| set expiredCertificateDetails(value) | |
| { | |
| if (this._expiredCertificateDetails === value) | |
| return; | |
| this._expiredCertificateDetails = value; | |
| }, | |
| get clockSkew() | |
| { | |
| return this._clockSkew; | |
| }, | |
| set clockSkew(value) | |
| { | |
| if (this._clockSkew === value) | |
| return; | |
| this._clockSkew = value; | |
| }, | |
| pageLoaded: function() | |
| { | |
| if (/Macintosh/g.test(navigator.userAgent)) | |
| document.body.classList.add("mac"); | |
| else | |
| document.body.classList.add("ios"); | |
| HTMLViewController.pageLoaded(); | |
| CertificateWarningController.pageLoaded(); | |
| window.addEventListener("resize", layOut, false); | |
| layOut(); | |
| }, | |
| currentSystemTime: function() | |
| { | |
| var dateFormatter = Intl.DateTimeFormat(undefined, { weekday: "long", day: "numeric", month: "long", year: "numeric" }); | |
| return dateFormatter.format(new Date()); | |
| }, | |
| showIncorrectClockWarning: function() | |
| { | |
| console.assert(this.warningCategory === CertificateWarningCategory.IncorrectClock); | |
| console.assert(this.clockSkew !== 0); | |
| document.body.classList.add("clockWarning"); | |
| var title = HTMLViewController.UIString("Your Clock Is Set Incorrectly"); | |
| document.title = title; | |
| document.getElementById("title").textContent = title; | |
| var incorrectClockHTMLTemplate = HTMLViewController.UIString("Safari can’t connect to “%hostname%” because your system clock is incorrectly set to %@. Set your system clock to the correct time and try again.").format(this.currentSystemTime()); | |
| var incorrectClockHTML = incorrectClockHTMLTemplate.replace("%hostname%", this.host); | |
| var warningText = document.getElementById("warningText"); | |
| warningText.innerHTML = incorrectClockHTML; | |
| var detailsTextHTMLTemplate = HTMLViewController.UIString("Because your system clock is set incorrectly, Safari can’t verify that your connection is private. If you understand the risks involved, you can %visit-this-site-link%."); | |
| var detailsTextHTML = "<a role='button' onClick='CertificateWarningController.visitInsecureWebsiteWithTemporaryBypass();'>%@</a>".format(HTMLViewController.UIString("visit this website")); | |
| var detailsText = detailsTextHTMLTemplate.replace("%visit-this-site-link%", detailsTextHTML); | |
| document.getElementById("detailsText").innerHTML = detailsText; | |
| setDetailsVisibility(false); | |
| }, | |
| updateDetailsStrings: function() | |
| { | |
| if (this.warningCategory === CertificateWarningCategory.IncorrectClock) { | |
| this.showIncorrectClockWarning(); | |
| return; | |
| } | |
| var warningText = document.getElementById("warningText"); | |
| var warningTextHTMLTemplate; | |
| if (this.warningCategory === CertificateWarningCategory.LegacyTLS) { | |
| if (this.canGoBack) | |
| warningTextHTMLTemplate = HTMLViewController.UIString("This website has an outdated security configuration, which may allow an attacker to steal personal or financial information entered into “%hostname%”. You should go back to the previous page."); | |
| else | |
| warningTextHTMLTemplate = HTMLViewController.UIString("This website has an outdated security configuration, which may allow an attacker to steal personal or financial information entered into “%hostname%”. You should close this page."); | |
| } else { | |
| if (this.canGoBack) | |
| warningTextHTMLTemplate = HTMLViewController.UIString("This website may be impersonating “%hostname%” to steal your personal or financial information. You should go back to the previous page."); | |
| else | |
| warningTextHTMLTemplate = HTMLViewController.UIString("This website may be impersonating “%hostname%” to steal your personal or financial information. You should close this page."); | |
| } | |
| var warningTextHTML = warningTextHTMLTemplate.replace("%hostname%", this.host); | |
| warningText.innerHTML = warningTextHTML; | |
| var bypassCertificateWarningHTMLTemplate = HTMLViewController.UIString("If you understand the risks involved, you can %visit-this-site-link%."); | |
| var visitUnsafeWebsiteLinkHTML = "<a role='button' onClick='CertificateWarningController.visitInsecureWebsite();'>%@</a>".format(HTMLViewController.UIString("visit this website")); | |
| var bypassCertificateWarningHTML = bypassCertificateWarningHTMLTemplate.replace("%visit-this-site-link%", visitUnsafeWebsiteLinkHTML); | |
| var viewCertificateHTMLTemplate = HTMLViewController.UIString("To learn more, you can %view-the-certificate%."); | |
| var viewCertificateLinkHTML = "<a role='button' onClick='CertificateWarningController.showCertificateInformation();'>%@</a>".format(HTMLViewController.UIString("view the certificate")); | |
| var viewCertificateHTML = viewCertificateHTMLTemplate.replace("%view-the-certificate%", viewCertificateLinkHTML); | |
| var detailsText = document.getElementById("detailsText"); | |
| switch (this.warningCategory) { | |
| case CertificateWarningCategory.Expired: | |
| var firstParagraphHTMLTemplate = HTMLViewController.UIString("Safari warns you when a website has %certificate-description%. %expiration-date-details%. This may happen if the website is misconfigured, an attacker has compromised your connection, or your system clock is incorrect. Your system clock is set to %@. If this is not right, %fixing-the-clock% may address this warning."); | |
| var firstParagraphWithDateHTMLTemplate = firstParagraphHTMLTemplate.format(this.currentSystemTime()); | |
| var openClockSettingsLinkHTML = "<a role='button' onClick='CertificateWarningController.openClockSettings();'>%@</a>".format(HTMLViewController.UIString("fixing the clock")); | |
| var firstParagraphWithClockHTMLTemplate = firstParagraphWithDateHTMLTemplate.replace("%fixing-the-clock%", openClockSettingsLinkHTML); | |
| var firstParagraphWithExpirationDateDetails = firstParagraphWithClockHTMLTemplate.replace("%expiration-date-details%", this.expiredCertificateDetails); | |
| var certificateDescription; | |
| if (this.numberOfDaysInvalid > 0) | |
| certificateDescription = HTMLViewController.UIString("an expired certificate"); | |
| else | |
| certificateDescription = HTMLViewController.UIString("a certificate that is not valid"); | |
| var firstParagraph = firstParagraphWithExpirationDateDetails.replace("%certificate-description%", certificateDescription); | |
| // Localizers: The space in between viewCertificateHTML and bypassCertificateWarningHTML should be translated to the appropriate space between two sentences. | |
| detailsText.innerHTML = "<p>" + firstParagraph + "</p><p>" + viewCertificateHTML + " " + bypassCertificateWarningHTML + "</p>"; | |
| break; | |
| case CertificateWarningCategory.HostnameMismatch: | |
| case CertificateWarningCategory.InvalidCanBypass: | |
| // FIXME 30320099: Hostname mismatch should be its own unique case. | |
| var firstParagraph = HTMLViewController.UIString("Safari warns you when a website has a certificate that is not valid. This may happen if the website is misconfigured or an attacker has compromised your connection."); | |
| // Localizers: The space in between viewCertificateHTML and bypassCertificateWarningHTML should be translated to the appropriate space between two sentences. | |
| detailsText.innerHTML = "<p>" + firstParagraph + "</p><p>" + viewCertificateHTML + " " + bypassCertificateWarningHTML + "</p>"; | |
| break; | |
| case CertificateWarningCategory.InvalidCannotBypass: | |
| var firstParagraph = HTMLViewController.UIString("Safari warns you when a website has a certificate that is not valid. This may happen if an attacker has compromised your connection. For your protection, you can’t visit this website. You can check back later to see if this issue has been resolved. You can also contact the website owner to tell them about this error."); | |
| // Localizers: The space in between firstParagraph and viewCertificateHTML should be translated to the appropriate space between two sentences. | |
| detailsText.innerHTML = firstParagraph + " " + viewCertificateHTML; | |
| break; | |
| case CertificateWarningCategory.LegacyTLS: | |
| var firstParagraph = HTMLViewController.UIString("Safari warns you when a website uses TLS 1.0 or TLS 1.1, which are not secure. This may allow an attacker to compromise your connection to steal your personal or financial information, including passwords, phone numbers, and credit cards."); | |
| detailsText.innerHTML = "<p>" + firstParagraph + "</p><p>" + bypassCertificateWarningHTML + "</p>"; | |
| break; | |
| default: | |
| console.assert(false, "Invalid warning category given"); | |
| break; | |
| } | |
| setDetailsVisibility(false); | |
| }, | |
| updateUI: function(host, warningCategory, canGoBack, numberOfDaysInvalid, expiredCertificateDetails, clockSkew) | |
| { | |
| this.warningCategory = warningCategory; | |
| this.host = host; | |
| this.canGoBack = canGoBack; | |
| this.numberOfDaysInvalid = numberOfDaysInvalid; | |
| this.expiredCertificateDetails = expiredCertificateDetails; | |
| this.clockSkew = clockSkew; | |
| if (!canGoBack) | |
| document.getElementById("goBackButton").textContent = HTMLViewController.UIString("Close Page"); | |
| this.updateDetailsStrings(); | |
| }, | |
| setTextDirection: function(textDirection) | |
| { | |
| document.documentElement.setAttribute("dir", textDirection); | |
| } | |
| }; | |
| function setDetailsVisibility(show) | |
| { | |
| var detailsDiv = document.getElementById("details"); | |
| if (show) { | |
| detailsDiv.style.display = "block"; | |
| document.getElementById("detailsButton").style.display = "none"; | |
| detailsDiv.scrollIntoViewIfNeeded(); | |
| } else { | |
| detailsDiv.style.display = "none"; | |
| document.getElementById("detailsButton").style.display = "block"; | |
| } | |
| layOut(); | |
| } | |
| function layOut() | |
| { | |
| const minimumMarginTop = 22; | |
| const maximumMarginTop = 156; | |
| var alertBox = document.getElementById("alert"); | |
| var alertHeight = alertBox.getBoundingClientRect().height; | |
| var viewportHeight = window.innerHeight; | |
| if (viewportHeight > alertHeight + 2 * maximumMarginTop) | |
| alertBox.style.top = maximumMarginTop + "px"; | |
| else | |
| alertBox.style.top = Math.max(minimumMarginTop, (viewportHeight - alertHeight) / 2) + "px"; | |
| } | |
| HTMLViewController.loadLocalizedStrings(CertificateWarningController); | |
| window.addEventListener("load", function() { CertificateWarning.pageLoaded(); }, false); | |
| </script> | |
| </head> | |
| <body> | |
| <div id="alert" class="alert"> | |
| <h1> | |
| <svg id="lock" x="0px" y="0px" viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;" xml:space="preserve"> | |
| <polygon class="lock-element" points="9.9,19 9.9,20.2 38.8,47 40,47 "/> | |
| <polygon class="lock-element" points="9.9,22.2 7.5,22.2 7.5,47 38.8,47 9.9,20.2 "/> | |
| <path class="lock-element" d="M24.4,6.2c5.5,0,9.9,4.1,9.9,9.2v6.9h-3l10.4,9.5v-9.5h-2.5v-6.9c0-7.6-6.6-13.8-14.8-13.8c-4.4,0-8.3,1.8-11,4.6L17,9.4C18.8,7.4,21.4,6.2,24.4,6.2z"/> | |
| <path class="lock-element" d="M49.3,47.9c1-0.9,1-2.4,0-3.3l-45-42c-1-0.9-2.6-0.9-3.6,0c-1,0.9-1,2.4,0,3.3l45,42C46.7,48.8,48.3,48.8,49.3,47.9z"/> | |
| </svg> | |
| <svg id="clock" x="0px" y="0px" viewBox="0 0 150 150" style="enable-background:new 0 0 150 150;" xml:space="preserve"> | |
| <path class="clock-element" d="M75,0C33.6,0,0,33.6,0,75c0,41.4,33.6,75,75,75s75-33.6,75-75C150,33.6,116.4,0,75,0z M81,68v7 c0,3.3-2.7,6-6,6H45c-3.3,0-6-2.7-6-6v-1c0-3.3,2.7-6,6-6h23V26c0-3.3,2.7-6,6-6h1c3.3,0,6,2.7,6,6V68z"/> | |
| </svg> | |
| <div id="title" class="l12n">This Connection Is Not Private</div> | |
| </h1> | |
| <div class="alert-body"> | |
| <div class="item"> | |
| <p id="warningText"></p> | |
| </div> | |
| <div class="bottom-bar goBack closePage" id="bottom-bar"> | |
| <button type="button" id="goBackButton" class="l12n goBack" onClick="CertificateWarningController.goBackSelected();">Go Back</button> | |
| <button type="button" id="openDateAndTimeButton" class="l12n" onClick="CertificateWarningController.openClockSettings();">Open Date & Time…</button> | |
| <button type="button" id="detailsButton" class="l12n" onClick="setDetailsVisibility(true);">Show Details</button> | |
| </div> | |
| </div> | |
| <div id="details"> | |
| <p id="detailsText"></p> | |
| </div> | |
| </div> | |
| </body> | |
| </html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| This file has a UTF-8 BOM in it so it can be included from a UTF-16 page | |
| without specifying an explicit character set. When editing it, please be | |
| sure to preserve the BOM (first three bytes of the file, EF BB BF). | |
| */ | |
| @media (prefers-dark-interface) { | |
| body { | |
| background: none; | |
| background-color: rgb(30, 30, 30); | |
| --font-color: rgb(181, 182, 184); | |
| --compact-font-color: rgb(181, 182, 184); | |
| --title-color: rgb(224, 225, 225); | |
| } | |
| .alert { | |
| background-color: rgb(56, 57, 59); | |
| box-shadow: 0 6px 12px rgba(0, 0, 0, .24); | |
| } | |
| #details { | |
| background-color: rgb(46, 47, 49); | |
| border-top-color: rgb(90, 92, 93); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <meta http-equiv="content-type" content="text/html; charset=utf-8"> | |
| <meta name="viewport" content="width=device-width, viewport-fit=cover"> | |
| <title class="l12n">This Connection Is Not Private</title> | |
| <style> | |
| :root { | |
| --bypass-feature-icon-color: #000000; | |
| } | |
| @media (prefers-color-scheme:dark) { | |
| :root { | |
| --bypass-feature-icon-color: #FFFFFF; | |
| } | |
| } | |
| body { | |
| --font-color: #434343; | |
| --compact-font-color: #434343; | |
| --blue-color: rgb(0, 122, 255); | |
| --horizontal-padding: 32px; | |
| --compact-horizontal-padding: 20px; | |
| --border-radius: 6px; | |
| --ios-border-radius: 10px; | |
| --title-color: #444; | |
| --icon-element-color: #dc143c; | |
| } | |
| * { | |
| padding: 0; | |
| margin: 0; | |
| } | |
| body:not(.ios) * { | |
| font-family: -apple-system-font; | |
| } | |
| html, body { | |
| height: 100%; | |
| width: 100%; | |
| } | |
| body { | |
| font-size: 13px; | |
| background: linear-gradient(30deg, #dfdfdf 0%, #fafafb 100%); | |
| background-repeat: no-repeat; | |
| background-attachment: fixed; | |
| cursor: default; | |
| -webkit-user-select: none; | |
| } | |
| #title { | |
| overflow: hidden; | |
| color: var(--title-color); | |
| padding-top: 3px; | |
| } | |
| .alert { | |
| background-color: white; | |
| min-width: 320px; | |
| max-width: 672px; | |
| position: relative; | |
| margin: 0 auto; | |
| padding-top: 28px; | |
| border-radius: var(--border-radius); | |
| box-shadow: 0px 6px 10px rgba(0, 0, 0, 0.14); | |
| } | |
| .alert-body { | |
| margin: 21px 0 0 0; | |
| padding-left: var(--horizontal-padding); | |
| padding-right: var(--horizontal-padding); | |
| padding-bottom: 24px; | |
| color: var(--font-color); | |
| } | |
| .alert-body p:first-of-type { | |
| margin-bottom: 15px; | |
| margin-top: 20px; | |
| } | |
| .alert-body p:last-of-type { | |
| margin-bottom: 0; | |
| } | |
| .bottom-bar { | |
| margin-top: 1.3em; | |
| height: 22px; | |
| } | |
| .bottom-bar button { | |
| float: right; | |
| font-size: 13px; | |
| line-height: 21px; | |
| min-width: 90px; | |
| margin: 0 4px; | |
| vertical-align: bottom; | |
| padding: 0 12px; | |
| } | |
| .bottom-bar .details { | |
| float: left; | |
| } | |
| .bottom-bar .details a { | |
| cursor: pointer; | |
| font-size: 14px; | |
| margin-top: 2px; | |
| } | |
| #details { | |
| display: none; | |
| padding: 22px var(--horizontal-padding) 10px var(--horizontal-padding); | |
| border-top: 1px solid rgb(217, 217, 217); | |
| color: var(--font-color); | |
| background-color: rgb(243, 243, 243); | |
| border-bottom-left-radius: var(--border-radius); | |
| border-bottom-right-radius: var(--border-radius); | |
| } | |
| .bottom-bar.goBack .closePage, .bottom-bar.closePage .goBack, #ignoreWarning { | |
| display: block; | |
| } | |
| #openDateAndTimeButton { | |
| display: none; | |
| } | |
| #bypassFeatureButton { | |
| display: none; | |
| } | |
| a { | |
| color: inherit; | |
| text-decoration: underline; | |
| cursor: pointer; | |
| } | |
| #lock, #clock { | |
| float: left; | |
| width: 30px; | |
| top: 4px; | |
| margin-right: 15px; | |
| position: relative; | |
| } | |
| #clock { | |
| display: none; | |
| } | |
| #bypassFeatureIcon { | |
| display: none; | |
| } | |
| .lock-element { | |
| fill: var(--icon-element-color); | |
| } | |
| .clock-element { | |
| fill: var(--icon-element-color); | |
| } | |
| body.clockWarning #clock { | |
| display: block; | |
| } | |
| body.clockWarning #lock { | |
| display: none; | |
| } | |
| body.clockWarning #goBackButton { | |
| display: none; | |
| } | |
| body.clockWarning #openDateAndTimeButton { | |
| display: block; | |
| } | |
| body.bypassFeature #bypassFeatureButton { | |
| display: block; | |
| } | |
| body.bypassFeature #detailsButton { | |
| display: none; | |
| } | |
| body.bypassFeature #bypassFeatureIcon { | |
| display: block; | |
| float: left; | |
| width: 34px; | |
| top: 4px; | |
| margin-right: 15px; | |
| position: relative; | |
| } | |
| body.bypassFeature #lock { | |
| display: none; | |
| } | |
| h1 { | |
| font-size: 2em; | |
| font-weight: 700; | |
| line-height: 30px; | |
| padding: 0 var(--horizontal-padding); | |
| margin-bottom: -6px; | |
| } | |
| p { | |
| font-size: 14px; | |
| line-height: 19px; | |
| margin-bottom: 1em; | |
| word-wrap: break-word; | |
| } | |
| body.ios .alert { | |
| box-shadow: none; | |
| border-radius: var(--ios-border-radius); | |
| max-width: 640px; | |
| } | |
| body.ios .alert-body { | |
| font: -apple-system-body; | |
| } | |
| body.ios #details { | |
| font: -apple-system-body; | |
| border-bottom-left-radius: var(--ios-border-radius); | |
| border-bottom-right-radius: var(--ios-border-radius); | |
| } | |
| body.ios h1 { | |
| font-size: 26px; | |
| font-family: -webkit-system-font; | |
| } | |
| body.ios p { | |
| font-size: 1.1em; | |
| line-height: unset; | |
| } | |
| body.ios button { | |
| background: none; | |
| border: none; | |
| color: var(--blue-color); | |
| font: -apple-system-short-body; | |
| } | |
| body.ios #detailsButton { | |
| color: var(--font-color); | |
| } | |
| body.ios #bypassFeatureIcon { | |
| fill: #000000; | |
| } | |
| body:not(.ios) #bypassFeatureIcon { | |
| fill: var(--bypass-feature-icon-color); | |
| } | |
| @media screen and (max-width: 666px) { | |
| /* iPhone 6 in landscape (667px) and smaller, including all iPhones in portrait */ | |
| body { | |
| color: var(--compact-font-color); | |
| } | |
| .alert { | |
| box-shadow: none; | |
| background-color: var(--red-color); | |
| } | |
| .alert-body { | |
| color: var(--compact-font-color); | |
| padding-left: var(--compact-horizontal-padding); | |
| padding-right: var(--compact-horizontal-padding); | |
| padding-bottom: 30px; | |
| } | |
| h1 { | |
| color: var(--compact-font-color); | |
| padding: 0 var(--compact-horizontal-padding); | |
| } | |
| body.ios button, | |
| body.ios #detailsButton { | |
| text-decoration: underline; | |
| } | |
| #details { | |
| background-color: var(--red-color); | |
| padding: 22px var(--compact-horizontal-padding) 22px var(--compact-horizontal-padding); | |
| border-top-width: 1px; | |
| border-top-color: rgba(0, 0, 0, .15); | |
| } | |
| } | |
| /* RTL support */ | |
| html[dir="rtl"] .bottom-bar button { | |
| float: left; | |
| } | |
| html[dir="rtl"] :matches(#lock, #clock, #bypassFeatureIcon) { | |
| float: right; | |
| margin-left: 15px; | |
| margin-right: 0; | |
| } | |
| </style> | |
| <link rel=stylesheet type="text/css" href="safari-resource:/CertificateWarningExtras.css"> | |
| <script type="text/javascript" src="safari-resource:/Utilities.js" charset="utf-8"></script> | |
| <script type="text/javascript" src="safari-resource:/WBSHTMLViewController.js" charset="utf-8"></script> | |
| <script type="text/javascript"> | |
| // Should be kept in sync with WBSCertificateWarningCategory in WBSCertificateWarningPageContext.h. | |
| var CertificateWarningCategory = { | |
| Expired: 0, | |
| InvalidCanBypass: 1, | |
| InvalidCannotBypass: 2, | |
| HostnameMismatch: 3, | |
| IncorrectClock: 4, | |
| LegacyTLS: 5, | |
| // Placeholder | |
| BypassFeatureNormal: 7, | |
| BypassFeatureUnencrypted: 8, | |
| }; | |
| var CertificateWarning = { | |
| _host: undefined, | |
| _canGoBack: undefined, | |
| _warningCategory: undefined, | |
| _numberOfDaysInvalid: undefined, | |
| _expiredCertificateDetails: undefined, | |
| _clockSkew: undefined, | |
| get host() | |
| { | |
| return this._host; | |
| }, | |
| set host(value) | |
| { | |
| if (this._host === value) | |
| return; | |
| this._host = value; | |
| }, | |
| get canGoBack() | |
| { | |
| return this._canGoBack; | |
| }, | |
| set canGoBack(value) | |
| { | |
| if (this._canGoBack === value) | |
| return; | |
| this._canGoBack = value; | |
| }, | |
| get warningCategory() | |
| { | |
| return this._warningCategory; | |
| }, | |
| set warningCategory(value) | |
| { | |
| if (this._warningCategory === value) | |
| return; | |
| this._warningCategory = value; | |
| }, | |
| get numberOfDaysInvalid() | |
| { | |
| return this._numberOfDaysInvalid; | |
| }, | |
| set numberOfDaysInvalid(value) | |
| { | |
| if (this._numberOfDaysInvalid === value) | |
| return; | |
| this._numberOfDaysInvalid = value; | |
| }, | |
| get expiredCertificateDetails() | |
| { | |
| return this._expiredCertificateDetails; | |
| }, | |
| set expiredCertificateDetails(value) | |
| { | |
| if (this._expiredCertificateDetails === value) | |
| return; | |
| this._expiredCertificateDetails = value; | |
| }, | |
| get clockSkew() | |
| { | |
| return this._clockSkew; | |
| }, | |
| set clockSkew(value) | |
| { | |
| if (this._clockSkew === value) | |
| return; | |
| this._clockSkew = value; | |
| }, | |
| pageLoaded: function() | |
| { | |
| if (/Macintosh/g.test(navigator.userAgent)) | |
| document.body.classList.add("mac"); | |
| else | |
| document.body.classList.add("ios"); | |
| HTMLViewController.pageLoaded(); | |
| CertificateWarningController.pageLoaded(); | |
| window.addEventListener("resize", layOut, false); | |
| layOut(); | |
| }, | |
| currentSystemTime: function() | |
| { | |
| var dateFormatter = Intl.DateTimeFormat(undefined, { weekday: "long", day: "numeric", month: "long", year: "numeric" }); | |
| return dateFormatter.format(new Date()); | |
| }, | |
| showIncorrectClockWarning: function() | |
| { | |
| console.assert(this.warningCategory === CertificateWarningCategory.IncorrectClock); | |
| console.assert(this.clockSkew !== 0); | |
| document.body.classList.add("clockWarning"); | |
| var title = HTMLViewController.UIString("Your Clock Is Set Incorrectly"); | |
| document.title = title; | |
| document.getElementById("title").textContent = title; | |
| var incorrectClockHTMLTemplate = HTMLViewController.UIString("Safari can’t connect to “%hostname%” because your system clock is incorrectly set to %@. Set your system clock to the correct time and try again.").format(this.currentSystemTime()); | |
| var incorrectClockHTML = incorrectClockHTMLTemplate.replace("%hostname%", this.host); | |
| var warningText = document.getElementById("warningText"); | |
| warningText.innerHTML = incorrectClockHTML; | |
| var detailsTextHTMLTemplate = HTMLViewController.UIString("Because your system clock is set incorrectly, Safari can’t verify that your connection is private. If you understand the risks involved, you can %visit-this-site-link%."); | |
| var detailsTextHTML = "<a role='button' onClick='CertificateWarningController.visitInsecureWebsiteWithTemporaryBypass();'>%@</a>".format(HTMLViewController.UIString("visit this website")); | |
| var detailsText = detailsTextHTMLTemplate.replace("%visit-this-site-link%", detailsTextHTML); | |
| document.getElementById("detailsText").innerHTML = detailsText; | |
| setDetailsVisibility(false); | |
| }, | |
| showBypassFeatureNavigationFailedWarning: function() | |
| { | |
| console.assert(this.warningCategory === CertificateWarningCategory.BypassFeatureNormal || this.warningCategory === CertificateWarningCategory.BypassFeatureUnencrypted); | |
| document.body.classList.add("bypassFeature"); | |
| document.getElementById("title").textContent = CertificateWarningController.bypassFeatureTitleText(); | |
| document.getElementById("warningText").textContent = CertificateWarningController.bypassFeatureWarningText(); | |
| }, | |
| updateDetailsStrings: function() | |
| { | |
| if (this.warningCategory === CertificateWarningCategory.IncorrectClock) { | |
| this.showIncorrectClockWarning(); | |
| return; | |
| } | |
| if (this.warningCategory === CertificateWarningCategory.BypassFeatureNormal || this.warningCategory === CertificateWarningCategory.BypassFeatureUnencrypted) { | |
| this.showBypassFeatureNavigationFailedWarning(); | |
| return; | |
| } | |
| var warningText = document.getElementById("warningText"); | |
| var warningTextHTMLTemplate; | |
| if (this.warningCategory === CertificateWarningCategory.LegacyTLS) { | |
| if (this.canGoBack) | |
| warningTextHTMLTemplate = HTMLViewController.UIString("This website has an outdated security configuration, which may allow an attacker to steal personal or financial information entered into “%hostname%”. You should go back to the previous page."); | |
| else | |
| warningTextHTMLTemplate = HTMLViewController.UIString("This website has an outdated security configuration, which may allow an attacker to steal personal or financial information entered into “%hostname%”. You should close this page."); | |
| } else { | |
| if (this.canGoBack) | |
| warningTextHTMLTemplate = HTMLViewController.UIString("This website may be impersonating “%hostname%” to steal your personal or financial information. You should go back to the previous page."); | |
| else | |
| warningTextHTMLTemplate = HTMLViewController.UIString("This website may be impersonating “%hostname%” to steal your personal or financial information. You should close this page."); | |
| } | |
| var warningTextHTML = warningTextHTMLTemplate.replace("%hostname%", this.host); | |
| warningText.innerHTML = warningTextHTML; | |
| var bypassCertificateWarningHTMLTemplate = HTMLViewController.UIString("If you understand the risks involved, you can %visit-this-site-link%."); | |
| var visitUnsafeWebsiteLinkHTML = "<a role='button' onClick='CertificateWarningController.visitInsecureWebsite();'>%@</a>".format(HTMLViewController.UIString("visit this website")); | |
| var bypassCertificateWarningHTML = bypassCertificateWarningHTMLTemplate.replace("%visit-this-site-link%", visitUnsafeWebsiteLinkHTML); | |
| var viewCertificateHTMLTemplate = HTMLViewController.UIString("To learn more, you can %view-the-certificate%."); | |
| var viewCertificateLinkHTML = "<a role='button' onClick='CertificateWarningController.showCertificateInformation();'>%@</a>".format(HTMLViewController.UIString("view the certificate")); | |
| var viewCertificateHTML = viewCertificateHTMLTemplate.replace("%view-the-certificate%", viewCertificateLinkHTML); | |
| var detailsText = document.getElementById("detailsText"); | |
| switch (this.warningCategory) { | |
| case CertificateWarningCategory.Expired: | |
| var firstParagraphHTMLTemplate = HTMLViewController.UIString("Safari warns you when a website has %certificate-description%. %expiration-date-details%. This may happen if the website is misconfigured, an attacker has compromised your connection, or your system clock is incorrect. Your system clock is set to %@. If this is not right, %fixing-the-clock% may address this warning."); | |
| var firstParagraphWithDateHTMLTemplate = firstParagraphHTMLTemplate.format(this.currentSystemTime()); | |
| var openClockSettingsLinkHTML = "<a role='button' onClick='CertificateWarningController.openClockSettings();'>%@</a>".format(HTMLViewController.UIString("fixing the clock")); | |
| var firstParagraphWithClockHTMLTemplate = firstParagraphWithDateHTMLTemplate.replace("%fixing-the-clock%", openClockSettingsLinkHTML); | |
| var firstParagraphWithExpirationDateDetails = firstParagraphWithClockHTMLTemplate.replace("%expiration-date-details%", this.expiredCertificateDetails); | |
| var certificateDescription; | |
| if (this.numberOfDaysInvalid > 0) | |
| certificateDescription = HTMLViewController.UIString("an expired certificate"); | |
| else | |
| certificateDescription = HTMLViewController.UIString("a certificate that is not valid"); | |
| var firstParagraph = firstParagraphWithExpirationDateDetails.replace("%certificate-description%", certificateDescription); | |
| // Localizers: The space in between viewCertificateHTML and bypassCertificateWarningHTML should be translated to the appropriate space between two sentences. | |
| detailsText.innerHTML = "<p>" + firstParagraph + "</p><p>" + viewCertificateHTML + " " + bypassCertificateWarningHTML + "</p>"; | |
| break; | |
| case CertificateWarningCategory.HostnameMismatch: | |
| case CertificateWarningCategory.InvalidCanBypass: | |
| // FIXME 30320099: Hostname mismatch should be its own unique case. | |
| var firstParagraph = HTMLViewController.UIString("Safari warns you when a website has a certificate that is not valid. This may happen if the website is misconfigured or an attacker has compromised your connection."); | |
| // Localizers: The space in between viewCertificateHTML and bypassCertificateWarningHTML should be translated to the appropriate space between two sentences. | |
| detailsText.innerHTML = "<p>" + firstParagraph + "</p><p>" + viewCertificateHTML + " " + bypassCertificateWarningHTML + "</p>"; | |
| break; | |
| case CertificateWarningCategory.InvalidCannotBypass: | |
| var firstParagraph = HTMLViewController.UIString("Safari warns you when a website has a certificate that is not valid. This may happen if an attacker has compromised your connection. For your protection, you can’t visit this website. You can check back later to see if this issue has been resolved. You can also contact the website owner to tell them about this error."); | |
| // Localizers: The space in between firstParagraph and viewCertificateHTML should be translated to the appropriate space between two sentences. | |
| detailsText.innerHTML = firstParagraph + " " + viewCertificateHTML; | |
| break; | |
| case CertificateWarningCategory.LegacyTLS: | |
| var firstParagraph = HTMLViewController.UIString("Safari warns you when a website uses TLS 1.0 or TLS 1.1, which are not secure. This may allow an attacker to compromise your connection to steal your personal or financial information, including passwords, phone numbers, and credit cards."); | |
| detailsText.innerHTML = "<p>" + firstParagraph + "</p><p>" + bypassCertificateWarningHTML + "</p>"; | |
| break; | |
| default: | |
| console.assert(false, "Invalid warning category given"); | |
| break; | |
| } | |
| setDetailsVisibility(false); | |
| }, | |
| updateUI: function(host, warningCategory, canGoBack, numberOfDaysInvalid, expiredCertificateDetails, clockSkew) | |
| { | |
| this.warningCategory = warningCategory; | |
| this.host = host; | |
| this.canGoBack = canGoBack; | |
| this.numberOfDaysInvalid = numberOfDaysInvalid; | |
| this.expiredCertificateDetails = expiredCertificateDetails; | |
| this.clockSkew = clockSkew; | |
| if (!canGoBack) | |
| document.getElementById("goBackButton").textContent = HTMLViewController.UIString("Close Page"); | |
| document.getElementById("bypassFeatureButton").textContent = CertificateWarningController.bypassFeatureButtonText(); | |
| var svg = document.getElementById("bypassFeatureIcon"); | |
| var path = document.createElementNS("http://www.w3.org/2000/svg", 'path'); | |
| var pathString = CertificateWarningController.bypassFeatureIconPath(); | |
| path.setAttribute("d", pathString); | |
| path.style.opacity = 0.5; | |
| svg.appendChild(path); | |
| this.updateDetailsStrings(); | |
| }, | |
| setTextDirection: function(textDirection) | |
| { | |
| document.documentElement.setAttribute("dir", textDirection); | |
| } | |
| }; | |
| function setDetailsVisibility(show) | |
| { | |
| var detailsDiv = document.getElementById("details"); | |
| if (show) { | |
| detailsDiv.style.display = "block"; | |
| document.getElementById("detailsButton").style.display = "none"; | |
| detailsDiv.scrollIntoViewIfNeeded(); | |
| } else { | |
| detailsDiv.style.display = "none"; | |
| document.getElementById("detailsButton").style.display = "block"; | |
| } | |
| layOut(); | |
| } | |
| function layOut() | |
| { | |
| const minimumMarginTop = 22; | |
| const maximumMarginTop = 156; | |
| var alertBox = document.getElementById("alert"); | |
| var alertHeight = alertBox.getBoundingClientRect().height; | |
| var viewportHeight = window.innerHeight; | |
| if (viewportHeight > alertHeight + 2 * maximumMarginTop) | |
| alertBox.style.top = maximumMarginTop + "px"; | |
| else | |
| alertBox.style.top = Math.max(minimumMarginTop, (viewportHeight - alertHeight) / 2) + "px"; | |
| } | |
| HTMLViewController.loadLocalizedStrings(CertificateWarningController); | |
| window.addEventListener("load", function() { CertificateWarning.pageLoaded(); }, false); | |
| </script> | |
| </head> | |
| <body> | |
| <div id="alert" class="alert"> | |
| <h1> | |
| <svg id="lock" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="33.6768" height="31.2098"> | |
| <rect height="30.1758" opacity="0" width="27.3834" x="0" y="0"/> | |
| <path class="lock-element" d="M13.396 2.55615C16.1353 2.55615 18.5229 4.50439 18.5229 8.21045L18.5229 12.019L13.2056 12.019L23.4009 22.1851L23.4009 15.4907C23.4009 13.4692 22.5073 12.312 20.8374 12.0776L20.8374 8.51807C20.8374 3.01025 17.2339 0.344238 13.396 0.344238C10.3784 0.344238 7.56592 2.01416 6.49658 5.29541L8.37158 7.18506C8.75244 4.16748 10.9058 2.55615 13.396 2.55615ZM6.70166 29.0698L20.105 29.0698C20.7935 29.0698 21.3794 28.9087 21.8042 28.6304L5.42725 12.2681L5.29541 12.2681C4.09424 12.6636 3.40576 13.7769 3.40576 15.4907L3.40576 25.5835C3.40576 27.8979 4.54834 29.0698 6.70166 29.0698ZM25.4517 29.8462C25.9058 30.2856 26.6235 30.2856 27.0483 29.8462C27.4878 29.4067 27.5024 28.689 27.0483 28.2495L1.94092 3.14209C1.50146 2.70264 0.769043 2.70264 0.32959 3.14209C-0.109863 3.58154-0.109863 4.31396 0.32959 4.73877Z"/> | |
| </svg> | |
| <svg id="clock" x="0px" y="0px" viewBox="0 0 150 150" style="enable-background:new 0 0 150 150;" xml:space="preserve"> | |
| <path class="clock-element" d="M75,0C33.6,0,0,33.6,0,75c0,41.4,33.6,75,75,75s75-33.6,75-75C150,33.6,116.4,0,75,0z M81,68v7 c0,3.3-2.7,6-6,6H45c-3.3,0-6-2.7-6-6v-1c0-3.3,2.7-6,6-6h23V26c0-3.3,2.7-6,6-6h1c3.3,0,6,2.7,6,6V68z"/> | |
| </svg> | |
| <svg id="bypassFeatureIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="33.6768" height="31.2098"> | |
| <rect height="31.2098" opacity="0" width="33.6768" x="0" y="0"/> | |
| </svg> | |
| <div id="title" class="l12n">This Connection Is Not Private</div> | |
| </h1> | |
| <div class="alert-body"> | |
| <div class="item"> | |
| <p id="warningText"></p> | |
| </div> | |
| <div class="bottom-bar goBack closePage" id="bottom-bar"> | |
| <button type="button" id="goBackButton" class="l12n goBack" onClick="CertificateWarningController.goBackSelected();">Go Back</button> | |
| <button type="button" id="openDateAndTimeButton" class="l12n" onClick="CertificateWarningController.openClockSettings();">Open Date & Time…</button> | |
| <button type="button" id="detailsButton" class="l12n" onClick="setDetailsVisibility(true);">Show Details</button> | |
| <button type="button" id="bypassFeatureButton" class="l12n" onClick="CertificateWarningController.bypassFeatureVisitWebsite();">Continue</button> | |
| </div> | |
| </div> | |
| <div id="details"> | |
| <p id="detailsText"></p> | |
| </div> | |
| </div> | |
| </body> | |
| </html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // # sourceURL=__InjectedScript_FormMetadataClassification.js | |
| /* Copyright (c) 2024 Apple Inc. All rights reserved. */ | |
| "use strict"; | |
| const WBSABAddressProperty = "Address", | |
| WBSABPhoneProperty = "Phone", | |
| _WBSABAddressZIPKey = "ZIP", | |
| WBSFormControlMetadataDefaultMaxLength = 524288, | |
| WBSIgnoredClassificationToken = "-sf-ignored", | |
| WBSLocaleForCreditCardExpirationDate = "en_US", | |
| WBSCreditCardTypeClassificationToken = "cc-type", | |
| WBSCreditCardHolderNameClassificationToken = "cc-name", | |
| WBSCreditCardNumberClassificationToken = "cc-number", | |
| WBSCreditCardExpirationClassificationToken = "cc-exp", | |
| WBSCreditCardSecurityCodeClassificationToken = "cc-csc", | |
| WBSCreditCardHolderGivenNameClassificationToken = "cc-given-name", | |
| WBSCreditCardHolderAdditionalNameClassificationToken = "cc-additional-name", | |
| WBSCreditCardHolderFamilyNameClassificationToken = "cc-family-name", | |
| WBSCreditCardExpirationMonthClassificationToken = "cc-exp-month", | |
| WBSCreditCardExpirationYearClassificationToken = "cc-exp-year", | |
| WBSCreditCardHolderNameClassificationDefaultOrderedParts = [ WBSCreditCardHolderGivenNameClassificationToken, WBSCreditCardHolderAdditionalNameClassificationToken, WBSCreditCardHolderFamilyNameClassificationToken ], | |
| WBSCreditCardExpirationClassificationDefaultOrderedParts = [ WBSCreditCardExpirationMonthClassificationToken, WBSCreditCardExpirationYearClassificationToken ], | |
| WBSCredentialUsernameClassificationToken = "username", | |
| WBSCredentialCurrentPasswordClassificationToken = "current-password", | |
| WBSCredentialNewPasswordClassificationToken = "new-password", | |
| WBSContactNameClassificationToken = "name", | |
| WBSContactGivenNameClassificationToken = "given-name", | |
| WBSContactAdditionalNameClassificationToken = "additional-name", | |
| WBSContactFamilyNameClassificationToken = "family-name", | |
| WBSContactClassificationDefaultOrderedParts = [ WBSContactGivenNameClassificationToken, WBSContactAdditionalNameClassificationToken, WBSContactFamilyNameClassificationToken ], | |
| WBSContactNamePartsSet = new Set(WBSContactClassificationDefaultOrderedParts), | |
| WBSContactInstantMessageClassificationToken = "-sf-instant-message", | |
| WBSContactPostalCodeClassificationToken = "postal-code", | |
| WBSContactStreetAddressClassificationToken = "street-address", | |
| WBSContactStreetAddressLine1ClassificationToken = "address-line1", | |
| WBSContactStreetAddressLine2ClassificationToken = "address-line2", | |
| WBSContactStreetAddressLine3ClassificationToken = "address-line3", | |
| WBSContactTelephoneClassificationToken = "tel", | |
| WBSContactTelephoneCountryCodeClassificationToken = "tel-country-code", | |
| WBSContactTelephoneAreaCodeClassificationToken = "tel-area-code", | |
| WBSContactTelephoneLocalPrefixClassificationToken = "tel-local-prefix", | |
| WBSContactTelephoneLocalSuffixClassificationToken = "tel-local-suffix", | |
| WBSContactTelephoneExtensionClassificationToken = "tel-extension", | |
| WBSContactTelephoneDefaultOrderedParts = [ WBSContactTelephoneCountryCodeClassificationToken, WBSContactTelephoneAreaCodeClassificationToken, WBSContactTelephoneLocalPrefixClassificationToken, WBSContactTelephoneLocalSuffixClassificationToken, WBSContactTelephoneExtensionClassificationToken ], | |
| WBSContactBirthdayClassificationToken = "bday", | |
| WBSContactBirthdayDayClassificationToken = "bday-day", | |
| WBSContactBirthdayMonthClassificationToken = "bday-month", | |
| WBSContactBirthdayYearClassificationToken = "bday-year"; | |
| class FormMetadataClassification { | |
| #t(t) | |
| { | |
| return null != t && "object" == typeof t | |
| } | |
| #e(t) | |
| { | |
| return this.#t(t) && "string" == typeof t.ControlTagName | |
| } | |
| #o(t) | |
| { | |
| return this.#t(t) && "string" == typeof t.property | |
| } | |
| fieldLooksLikeDateField(t) | |
| { | |
| return !!(t.ControlLooksLikeDayField || t.ControlLooksLikeMonthField || t.ControlLooksLikeYearField) | |
| } | |
| #i(t) | |
| { | |
| let e = t.ControlMaxLength; | |
| return (void 0 === e || e < 0 || e > WBSFormControlMetadataDefaultMaxLength) && (e = WBSFormControlMetadataDefaultMaxLength), e | |
| } | |
| fieldLooksLikeItExpectsDataOfSize(t, e) | |
| { | |
| return (t.ControlSize ?? 0) <= e || this.#i(t) <= e | |
| } | |
| fieldCouldBeCreditCardNumberContinuation(t, e) | |
| { | |
| const o = 4; | |
| if (e.length >= o) | |
| return !1; | |
| if (!e[0]?.ControlLooksLikeCreditCardNumberField) | |
| return !1; | |
| const i = 2; | |
| if (t.ControlMaxLength === i) | |
| return !1; | |
| if (t.ControlLooksLikeCreditCardNumberField) | |
| return !0; | |
| if (t.ControlLooksLikeCreditCardSecurityCodeField) | |
| return !1; | |
| if (t.ControlLooksLikeCreditCardCompositeExpirationDateField) | |
| return !1; | |
| const n = 6; | |
| if (!this.fieldLooksLikeItExpectsDataOfSize(t, n)) | |
| return !1; | |
| const a = e.at(-1); | |
| return !(a && !this.fieldLooksLikeItExpectsDataOfSize(a, n)) | |
| } | |
| labelsCouldRepresentContinuation(t, e, o, i) | |
| { | |
| return !(!t || !o) && (t === o || !!e && (!i || e.property === i.property && (i.component && e.component === i.component))) | |
| } | |
| fieldCouldBePhoneNumberContinuation(t, e) | |
| { | |
| const o = 5; | |
| if (e.length >= o) | |
| return !1; | |
| if (e[0]?.AddressBookValueSpecifier?.property !== WBSABPhoneProperty) | |
| return !1; | |
| const i = 5; | |
| return !!this.fieldLooksLikeItExpectsDataOfSize(t, i) | |
| } | |
| fieldCouldBePostCodeContinuation(t, e) | |
| { | |
| const o = 3; | |
| if (e.length >= o) | |
| return !1; | |
| if (e[0]?.AddressBookValueSpecifier?.component != _WBSABAddressZIPKey) | |
| return !1; | |
| const i = 6; | |
| return !!this.fieldLooksLikeItExpectsDataOfSize(t, i) | |
| } | |
| fieldLooksLikeSameDataType(t, e) | |
| { | |
| const o = e.at(-1); | |
| return !!this.labelsCouldRepresentContinuation(o?.AddressBookLabel, o?.AddressBookValueSpecifier, t?.AddressBookLabel, t?.AddressBookValueSpecifier) || (!!(o && this.fieldLooksLikeDateField(o) && this.fieldLooksLikeDateField(t)) || (!!this.fieldCouldBePhoneNumberContinuation(t, e) || (!!this.fieldCouldBePostCodeContinuation(t, e) || !!this.fieldCouldBeCreditCardNumberContinuation(t, e)))) | |
| } | |
| #n(t) | |
| { | |
| return globalThis.DOMRect || (globalThis.DOMRect = class { | |
| constructor(t, e, o, i) | |
| { | |
| this.left = t, this.right = t + o, this.top = e, this.bottom = e + i, this.width = o, this.height = i | |
| } | |
| }), t.ControlRectLeft || t.ControlRectTop || t.ControlRectWidth || t.ControlRectHeight ? new DOMRect(t.ControlRectLeft, t.ControlRectTop, t.ControlRectWidth, t.ControlRectHeight) : globalThis.FormMetadataJS ? FormMetadataJS.formControlWithUniqueID(t.ControlUniqueID)?.getBoundingClientRect() | |
| : new DOMRect(0, 0, 0, 0) | |
| } | |
| fieldLooksLikeContinuation(t, e, o) | |
| { | |
| if (!t.ControlIsTextField && "SELECT" !== t.ControlTagName.toUpperCase()) | |
| return !1; | |
| if (!this.fieldLooksLikeSameDataType(t, e)) | |
| return !1; | |
| if (o) | |
| return !0; | |
| const i = this.#n(e.at(-1)), | |
| n = this.#n(t); | |
| if (Math.abs(i.top - n.top) > 3) | |
| return !1; | |
| let a, r; | |
| return i.left < n.left ? (a = i, r = n) : (a = n, r = i), !(r.left - a.right > 60) | |
| } | |
| continuingFieldsInFormControls(t, e, o, i) | |
| { | |
| const n = [ t[e] ]; | |
| for (let a = e + 1; a < t.length; ++a) { | |
| const e = t[a]; | |
| if (o && !e.ControlIsTextField) | |
| break; | |
| if (!this.fieldLooksLikeContinuation(e, n, i)) | |
| break; | |
| n.push(e) | |
| } | |
| return n | |
| } | |
| classifyControlsRelatedToNameParts(t, e) | |
| { | |
| const o = t[e]; | |
| o.ControlClassification = WBSContactNameClassificationToken, o.ControlOrderedParts = [ o.AddressBookValueSpecifier?.classification ]; | |
| const i = new Set([ o.AddressBookValueSpecifier?.classification ]), | |
| n = [ t[e] ]; | |
| for (let o = e + 1; o < t.length; ++o) { | |
| const e = t[o]; | |
| if (!e.ControlIsTextField) | |
| break; | |
| const a = e.AddressBookValueSpecifier?.classification; | |
| if (!a) | |
| break; | |
| if (!WBSContactNamePartsSet.has(a) || i.has(a)) | |
| break; | |
| e.ControlClassification = WBSContactNameClassificationToken, e.ControlOrderedParts = [ a ], i.add(a), n.push(e) | |
| } | |
| return n | |
| } | |
| identifyDateFields(t) | |
| { | |
| let e, o, i, n = !1; | |
| for (let a of t) | |
| if (a.ControlLooksLikeDayField) { | |
| if (e) | |
| return [ !1 ]; | |
| e = a, n = !0 | |
| } else if (a.ControlLooksLikeMonthField) { | |
| if (o) | |
| return [ !1 ]; | |
| o = a, n = !0 | |
| } else if (a.ControlLooksLikeYearField) { | |
| if (i) | |
| return [ !1 ]; | |
| i = a, n = !0 | |
| } | |
| return [ n, i, o, e ] | |
| } | |
| canonicalizedDateTemplate(t) | |
| { | |
| if (t && (t = t.replace(/\s/g, "")).length && !/[^dmyDMY\/.-]/g.test(t)) | |
| return t = (t = (t = t.replace(/D/g, "d")).replace(/m/g, "M")).replace(/Y/g, "y") | |
| } | |
| classifyDateFields(t, e, o, i, n, a, r) | |
| { | |
| if (t.length > 3) | |
| return !1; | |
| if (1 === t.length) { | |
| if (!t[0].ControlIsTextField) | |
| return !1; | |
| let a = t[0].ControlRequiredFormatForDateTimeInput; | |
| if (!a) { | |
| const e = n ? new Date(1999, 11, 30) : new Date(1999, 11); | |
| let o = this.#i(t[0]), | |
| i = this.canonicalizedDateTemplate(t[0].ControlPlaceholder), | |
| s = i?.length ? i : n ? "ddMMy" | |
| : "MMyy"; | |
| a = FormMetadataJSController.dateFormatFromTemplate(s, r); | |
| let l = FormMetadataJSController.stringFromDateFormat(a, e); | |
| if (l.length > o && (s = n ? "dMMyy" : "MMyy", a = FormMetadataJSController.dateFormatFromTemplate(s, r), l = FormMetadataJSController.stringFromDateFormat(a, e), l.length > o && (s = n ? "dMyy" : "Myy", a = FormMetadataJSController.dateFormatFromTemplate(s, r), l = FormMetadataJSController.stringFromDateFormat(a, e))), l.length > o) | |
| return !1 | |
| } | |
| const s = []; | |
| for (const t of a) { | |
| let e; | |
| "y" === t ? e = o : "M" === t ? e = i | |
| : "d" === t && (e = n), | |
| e && !s.includes(e) && s.push(e) | |
| } | |
| return t[0].ControlClassification = e, t[0].ControlOrderedParts = s, t[0].ControlRequiredFormatForDateTimeInput = a, !0 | |
| } | |
| let [s, l, C, d] = this.identifyDateFields(t); | |
| if (!s) | |
| return !1; | |
| if (d && !C) | |
| return !1; | |
| let c = 0; | |
| for (const r of t) | |
| r.ControlClassification = e, r.ControlContinuationID = a, r.ControlContinuationIndex = c++, r === d ? r.ControlOrderedParts = [ n ] : r === C ? r.ControlOrderedParts = [ i ] | |
| : r === l && (r.ControlOrderedParts = [ o ]); | |
| return !0 | |
| } | |
| classify(t) | |
| { | |
| const e = t.FormControls, | |
| o = e.length, | |
| i = t.AutoFillFormType === WBSAutoFillFormTypeNewAccount, | |
| n = t.AutoFillFormType === WBSAutoFillFormTypeChangePassword, | |
| a = t.UsernameElementUniqueID, | |
| r = t.PasswordElementUniqueID, | |
| s = t.OldPasswordElementUniqueID, | |
| l = t.ConfirmPasswordElementUniqueID; | |
| for (let t of e) | |
| (t.AutocompleteTokens || t.AddressBookLabel) && (t.AddressBookValueSpecifier = FormMetadataJSController.specifierForAutocompleteTokensAndAddressBookLabel(t.AutocompleteTokens, t.AddressBookLabel)); | |
| let C = !1, | |
| d = !1, | |
| c = !1, | |
| f = !1, | |
| k = !1, | |
| S = 0; | |
| for (let u = 0, T = 1; u < o; u += T, T = 1) { | |
| const o = e[u]; | |
| if (o.ControlLooksLikeIgnoredDataTypeField) { | |
| o.ControlClassification = WBSIgnoredClassificationToken; | |
| continue | |
| } | |
| const B = o.ControlUniqueID; | |
| if (B === r || B === l) { | |
| o.ControlClassification = i || n ? WBSCredentialNewPasswordClassificationToken : WBSCredentialCurrentPasswordClassificationToken; | |
| continue | |
| } | |
| if (B === s) { | |
| o.ControlClassification = WBSCredentialCurrentPasswordClassificationToken; | |
| continue | |
| } | |
| if (B === a) { | |
| o.ControlClassification = WBSCredentialUsernameClassificationToken; | |
| continue | |
| } | |
| if (!d && o.ControlLooksLikeCreditCardCardholderField) { | |
| d = !0, o.ControlClassification = WBSCreditCardHolderNameClassificationToken, o.ControlOrderedParts = WBSCreditCardHolderNameClassificationDefaultOrderedParts; | |
| continue | |
| } | |
| if (!C && o.ControlLooksLikeCreditCardNumberField) { | |
| C = !0; | |
| const t = this.continuingFieldsInFormControls(e, u, !0, !1); | |
| let o = 0, | |
| i = t.length > 1 ? ++S : 0; | |
| for (let e of t) | |
| e.ControlClassification = WBSCreditCardNumberClassificationToken, e.ControlContinuationID = i, e.ControlContinuationIndex = o++; | |
| T = t.length; | |
| continue | |
| } | |
| const h = this.fieldLooksLikeDateField(o) || o.ControlLooksLikeCreditCardCompositeExpirationDateField; | |
| if ((f || d || C) && !c && h) { | |
| c = !0; | |
| const t = this.continuingFieldsInFormControls(e, u, !1, !0); | |
| let o = t.length > 1 ? ++S : 0; | |
| this.classifyDateFields(t, WBSCreditCardExpirationClassificationToken, WBSCreditCardExpirationYearClassificationToken, WBSCreditCardExpirationMonthClassificationToken, void 0, o, WBSLocaleForCreditCardExpirationDate), T = t.length; | |
| continue | |
| } | |
| if (!k && o.ControlLooksLikeCreditCardSecurityCodeField) { | |
| k = !0, o.ControlClassification = WBSCreditCardSecurityCodeClassificationToken; | |
| continue | |
| } | |
| if (!f && o.ControlLooksLikeCreditCardTypeField) { | |
| f = !0, o.ControlClassification = WBSCreditCardTypeClassificationToken; | |
| continue | |
| } | |
| const m = o.AddressBookValueSpecifier?.classification; | |
| if (m) { | |
| const i = o.AddressBookValueSpecifier.classificationHint; | |
| if (m === WBSContactNameClassificationToken) { | |
| o.ControlClassification = m, o.ControlOrderedParts = WBSContactClassificationDefaultOrderedParts; | |
| continue | |
| } | |
| if (WBSContactNamePartsSet.has(m)) { | |
| const t = this.classifyControlsRelatedToNameParts(e, u); | |
| if (t.length > 1) { | |
| let e = ++S, | |
| o = 0; | |
| for (let i of t) | |
| i.ControlContinuationID = e, i.ControlContinuationIndex = o++ | |
| } | |
| T = t.length; | |
| continue | |
| } | |
| if (m === WBSContactPostalCodeClassificationToken) { | |
| const t = this.continuingFieldsInFormControls(e, u, !0, !1); | |
| let o = t.length > 1 ? ++S : 0, | |
| i = 0; | |
| for (let e of t) | |
| e.ControlClassification = WBSContactPostalCodeClassificationToken, e.ControlContinuationID = o, e.ControlContinuationIndex = i++; | |
| T = t.length; | |
| continue | |
| } | |
| if (m === WBSContactStreetAddressClassificationToken) { | |
| const t = this.continuingFieldsInFormControls(e, u, !0, !0); | |
| let o = t.length > 1 ? ++S : 0, | |
| i = 0; | |
| for (let e of t) | |
| e.ControlClassification = WBSContactStreetAddressClassificationToken, e.ControlContinuationID = o, e.ControlContinuationIndex = i++; | |
| 1 === t.length ? t[0].ControlOrderedParts = [ WBSContactStreetAddressLine1ClassificationToken, WBSContactStreetAddressLine2ClassificationToken, WBSContactStreetAddressLine3ClassificationToken ] : 2 === t.length ? (t[0].ControlOrderedParts = [ WBSContactStreetAddressLine1ClassificationToken ], t[1].ControlOrderedParts = [ WBSContactStreetAddressLine2ClassificationToken, WBSContactStreetAddressLine3ClassificationToken ]) | |
| : t.length >= 3 && (t[0].ControlOrderedParts = [ WBSContactStreetAddressLine1ClassificationToken ], t[1].ControlOrderedParts = [ WBSContactStreetAddressLine2ClassificationToken ], t[2].ControlOrderedParts = [ WBSContactStreetAddressLine3ClassificationToken ]), | |
| T = t.length; | |
| continue | |
| } | |
| if (m === WBSContactInstantMessageClassificationToken) { | |
| const t = this.continuingFieldsInFormControls(e, u, !0, !0); | |
| 1 === t.length && (t[0].ControlClassification = WBSContactInstantMessageClassificationToken, i && (t[0].ControlClassificationHints = [ i ])), T = t.length; | |
| continue | |
| } | |
| if (m.startsWith(WBSContactTelephoneClassificationToken)) { | |
| const t = this.continuingFieldsInFormControls(e, u, !0, !1); | |
| if (1 == t.length) { | |
| t[0].ControlClassification = WBSContactTelephoneClassificationToken, t[0].ControlOrderedParts = WBSContactTelephoneDefaultOrderedParts, i && (t[0].ControlClassificationHints = [ i ]); | |
| continue | |
| } | |
| let o = ++S, | |
| n = 0; | |
| for (let e of t) | |
| e.ControlClassification = WBSContactTelephoneClassificationToken, e.ControlContinuationID = o, e.ControlContinuationIndex = n++, i && (e.ControlClassificationHints = [ i ]); | |
| 2 === t.length ? (t[0].ControlOrderedParts = [ WBSContactTelephoneAreaCodeClassificationToken ], t[1].ControlOrderedParts = [ WBSContactTelephoneLocalPrefixClassificationToken, WBSContactTelephoneLocalSuffixClassificationToken ]) : 3 === t.length ? (t[0].ControlOrderedParts = [ WBSContactTelephoneAreaCodeClassificationToken ], t[1].ControlOrderedParts = [ WBSContactTelephoneLocalPrefixClassificationToken ], t[2].ControlOrderedParts = [ WBSContactTelephoneLocalSuffixClassificationToken ]) | |
| : 4 === t.length ? (t[0].ControlOrderedParts = [ WBSContactTelephoneCountryCodeClassificationToken ], t[1].ControlOrderedParts = [ WBSContactTelephoneAreaCodeClassificationToken ], t[2].ControlOrderedParts = [ WBSContactTelephoneLocalPrefixClassificationToken ], t[3].ControlOrderedParts = [ WBSContactTelephoneLocalSuffixClassificationToken ]) | |
| : (t[0].ControlOrderedParts = [ WBSContactTelephoneCountryCodeClassificationToken ], t[1].ControlOrderedParts = [ WBSContactTelephoneAreaCodeClassificationToken ], t[2].ControlOrderedParts = [ WBSContactTelephoneLocalPrefixClassificationToken ], t[3].ControlOrderedParts = [ WBSContactTelephoneLocalSuffixClassificationToken ], t[4].ControlOrderedParts = [ WBSContactTelephoneExtensionClassificationToken ]), | |
| T = t.length; | |
| continue | |
| } | |
| if (m === WBSContactBirthdayClassificationToken) { | |
| const o = this.continuingFieldsInFormControls(e, u, !1, !1), | |
| i = o.length > 1 ? ++S : void 0, | |
| n = t.RequestType === WBSFormMetadataRequestTesting ? "en_US" : void 0; | |
| this.classifyDateFields(o, WBSContactBirthdayClassificationToken, WBSContactBirthdayYearClassificationToken, WBSContactBirthdayMonthClassificationToken, WBSContactBirthdayDayClassificationToken, i, n), T = o.length; | |
| continue | |
| } | |
| o.ControlClassification = m | |
| } else | |
| ; | |
| } | |
| } | |
| } | |
| globalThis.FormMetadataClassificationJS = new FormMetadataClassification; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // # sourceURL=__InjectedScript_FormMetadata.js | |
| /* Copyright (c) 2024 Apple Inc. All rights reserved. */ | |
| function legacyPlaceholderInfoForInputElement(e) | |
| { | |
| if ("text" !== e.type) | |
| return null; | |
| if (doctypeLooksLikeHTML5) | |
| return null; | |
| var t = e.value.trim(); | |
| if (!t) | |
| return null; | |
| for (var o = !1, r = !0, n = e.attributes, i = n.length, l = 0; l < i; ++l) { | |
| var a = n[l]; | |
| if (t === a.value.trim() && (o = !0, "value" !== a.name.toLowerCase())) { | |
| r = !1; | |
| break | |
| } | |
| } | |
| return o ? { | |
| Text : t, | |
| AttributeMatchedWasValue : r | |
| } | |
| : null | |
| } | |
| function placeholderInfoForElement(e) | |
| { | |
| var t = e.getAttribute("placeholder"); | |
| if (t) | |
| return { | |
| Text : t, | |
| AttributeMatchedWasValue : !1 | |
| }; | |
| var o = e.getAttribute("data-placeholder"); | |
| return o && o.length ? { | |
| Text : o, | |
| AttributeMatchedWasValue : !1 | |
| } | |
| : isInputElement(e) ? legacyPlaceholderInfoForInputElement(e) | |
| : null | |
| } | |
| function sharedPrefixLength(e, t) | |
| { | |
| for (var o = 0, r = 0, n = e.length; r < n && e[r] === t[r]; ++r) | |
| o++; | |
| return o | |
| } | |
| function rowContainingLabelAboveRow(e) | |
| { | |
| for (var t = e.getBoundingClientRect(), o = e.previousElementSibling; o instanceof HTMLTableRowElement; o = o.previousElementSibling) { | |
| if (o.querySelector("input, select, textarea")) | |
| return null; | |
| var r = o.getBoundingClientRect(); | |
| if (t.top - r.bottom > t.height / 2) | |
| return null; | |
| if (o.innerText.match(/\S/)) | |
| return o | |
| } | |
| return null | |
| } | |
| function cellVisuallyAbove(e) | |
| { | |
| let t = e.parentElementIncludingShadowDOMHost(); | |
| if (!(t && t instanceof HTMLTableRowElement)) | |
| return null; | |
| var o = rowContainingLabelAboveRow(t); | |
| if (!o) | |
| return null; | |
| for (var r = e.getBoundingClientRect(), n = o.children, i = n.length, l = null, a = 0, s = 0; s < i; ++s) { | |
| var u = n[s], | |
| c = u.getBoundingClientRect(), | |
| d = Math.min(c.right, r.right) - Math.max(c.left, r.left); | |
| (!l || d > a) && (a = d, l = u) | |
| } | |
| return l | |
| } | |
| function couldBeFormSubmissionControl(e) | |
| { | |
| if (e instanceof HTMLButtonElement) | |
| return !0; | |
| if (e instanceof HTMLInputElement) { | |
| var t = e.type; | |
| return "submit" === t || "image" === t | |
| } | |
| return !1 | |
| } | |
| function isInputElement(e) | |
| { | |
| return e instanceof HTMLInputElement | |
| } | |
| function isDateTimeInputElement(e) | |
| { | |
| return !!isInputElement(e) && DateTimeInputTypes.includes(e.type) | |
| } | |
| function isRadioButtonElement(e) | |
| { | |
| return !!isInputElement(e) && "radio" === e.type | |
| } | |
| function anchorWithURLString(e) | |
| { | |
| var t = document.createElement("a"); | |
| return t.href = e, t | |
| } | |
| function pathComponentsForLocation(e) | |
| { | |
| var t = e.pathname.substring(1).split("/"); | |
| return t[t.length - 1] || t.pop(), t | |
| } | |
| function lastPathComponentFromAnchor(e) | |
| { | |
| var t = pathComponentsForLocation(e); | |
| return t.length ? t[t.length - 1] : null | |
| } | |
| function lastPathComponentForURLString(e) | |
| { | |
| return lastPathComponentFromAnchor(anchorWithURLString(e)) | |
| } | |
| function urlEncode(e) | |
| { | |
| return encodeURIComponent(e).replace(/%20/g, "+") | |
| } | |
| function isCheckboxOrRadioButtonInDefaultState(e) | |
| { | |
| return e.checked === e.defaultChecked | |
| } | |
| function isSelectInDefaultState(e) | |
| { | |
| for (var t = e.options, o = t.length, r = 0; r < o; ++r) { | |
| var n = t[r]; | |
| if (n.selected !== n.defaultSelected) { | |
| if (n.defaultSelected) | |
| return !1; | |
| if (e.multiple || r) | |
| return !1 | |
| } | |
| } | |
| return !0 | |
| } | |
| function formActionAsAnchorElement(e, t) | |
| { | |
| if (!(e instanceof HTMLFormElement)) | |
| return null; | |
| let o = e.getAttribute("action"); | |
| if (!o && t) | |
| return null; | |
| var r = document.createElement("a"); | |
| return r.href = o || "", r | |
| } | |
| function eventThatBubbles(e) | |
| { | |
| return new CustomEvent(e, { | |
| bubbles : !0 | |
| }) | |
| } | |
| function formControlHasBeenClassifiedInAnInterestingWay(e) | |
| { | |
| return e.ControlIsActiveElement || e.ControlIsSecureTextField || e.ControlLooksLikePasswordCredentialField || e.ControlLooksLikeCreditCardNumberField || e.ControlLooksLikeCreditCardSecurityCodeField || e.ControlLooksLikeCreditCardCardholderField || e.ControlLooksLikeCreditCardTypeField || e.AddressBookLabel || e.ControlLooksLikeDayField || e.ControlLooksLikeMonthField || e.ControlLooksLikeYearField || e.ControlLooksLikeOneTimeCodeField || e.ControlLooksLikeCreditCardCompositeExpirationDateField || e.ControlLooksLikeEIDField || e.ControlLooksLikeIMEIField | |
| } | |
| function isValidUsernameOrEmail(e) | |
| { | |
| const t = /^[a-z_][a-z0-9_.]{2,30}$/i, | |
| o = /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$/i; | |
| return !(!e || e.length < 3 || "true" === e || "false" === e) && (t.test(e) || o.test(e)) | |
| } | |
| function selectorForElement(e) | |
| { | |
| let t = e.localName, | |
| o = e.getAttribute("id"); | |
| o && (t += `#${o}`); | |
| let r = e.classList, | |
| n = r.length; | |
| for (let e = 0; e < n; e++) | |
| t += "." + r[e]; | |
| return t | |
| } | |
| function hasOwnProperties(e) | |
| { | |
| return Object.getOwnPropertyNames(e).length > 0 | |
| } | |
| function defaultOptionForSelectElement(e) | |
| { | |
| for (var t = e.options, o = t.length, r = 0; r < o; ++r) { | |
| var n = t[r]; | |
| if (n.defaultSelected) | |
| return n | |
| } | |
| return t[0] | |
| } | |
| function selectElementOptionsSequenceAnalysis(e, t) | |
| { | |
| for (var o = e.options, r = o.length, n = 0, i = -1, l = -1, a = 0, s = 0; s < r; ++s) { | |
| var u = o[s], | |
| c = parseInt(u[t]); | |
| isNaN(c) ? (a >= n && (n = a, i = l), l = -1, a = 0) : -1 === l ? (l = c, a = 1) | |
| : c === l + 1 && (l = c, a++) | |
| } | |
| return a >= n && (n = a, i = l), | |
| { | |
| lengthOfLongestSequence: n, | |
| lastNumberInSequence: i | |
| } | |
| } | |
| function isElementPositionedToBeEffectivelyInvisible(e) | |
| { | |
| var t = !1; | |
| for (let o = e; o; o = o.parentElementIncludingShadowDOMHost()) | |
| if ("fixed" === getComputedStyle(o).position) { | |
| t = !0; | |
| break | |
| } | |
| var o, r, n, i = e.getBoundingClientRect(); | |
| if (t) | |
| o = i, r = window.innerWidth, n = window.innerHeight; | |
| else { | |
| var l = window.scrollY, | |
| a = window.scrollX; | |
| o = { | |
| top : i.top + l, | |
| right : i.right + a, | |
| bottom : i.bottom + l, | |
| left : i.left + a, | |
| width : i.width, | |
| height : i.height | |
| }, | |
| r = document.documentElement.scrollWidth, n = Math.max(document.documentElement.scrollHeight, window.innerHeight) | |
| } | |
| return o.top >= n || o.right <= 0 || o.bottom <= 0 || o.left >= r | |
| } | |
| function rectIsWithinDocumentViewport(e) | |
| { | |
| return e.right >= 0 && e.bottom >= 0 && e.left <= window.innerWidth && e.top <= window.innerHeight | |
| } | |
| function isCredentialElementUniqueID(e, t) | |
| { | |
| return t === e.UsernameElementUniqueID || t === e.PasswordElementUniqueID || t === e.ConfirmPasswordElementUniqueID || t === e.OldPasswordElementUniqueID | |
| } | |
| function autocompleteTokens(e) | |
| { | |
| const t = [ "autocomplete", "autocompletetype", "x-autocompletetype" ]; | |
| let o = []; | |
| for (const r of t) | |
| e.hasAttribute(r) && o.push(e.getAttribute(r).trim().toLowerCase()); | |
| if (!o.length) | |
| return null; | |
| let r = o.join(" ").split(/\s+/).filter((function(e) { | |
| return e.length && "off" !== e && "on" !== e | |
| })); | |
| return r.length ? r : null | |
| } | |
| function elementIDOrAutocompleteTokensHasToken(e, t, o) | |
| { | |
| return !!e.id?.includes(o) || !!t?.includes(o) | |
| } | |
| function controlAppearsToBePartOfPhotoTaggingInterface(e) | |
| { | |
| const t = /photo.*tag/i; | |
| for (let o = e.parentElementIncludingShadowDOMHost(); o; o = o.parentElementIncludingShadowDOMHost()) | |
| if (t.test(o.className)) | |
| return !0; | |
| return !1 | |
| } | |
| function levenshteinDistance(e, t) | |
| { | |
| for (var o = e.length, r = t.length, n = new Array(o + 1), i = 0; i < o + 1; ++i) | |
| n[i] = new Array(r + 1), n[i][0] = i; | |
| for (var l = 0; l < r + 1; ++l) | |
| n[0][l] = l; | |
| for (l = 1; l < r + 1; ++l) | |
| for (i = 1; i < o + 1; ++i) | |
| if (e[i - 1] === t[l - 1]) | |
| n[i][l] = n[i - 1][l - 1]; | |
| else { | |
| var a = n[i - 1][l] + 1, | |
| s = n[i][l - 1] + 1, | |
| u = n[i - 1][l - 1] + 1; | |
| n[i][l] = Math.min(a, s, u) | |
| } | |
| return n[o][r] | |
| } | |
| function stringSimilarity(e, t) | |
| { | |
| var o = Math.max(e.length, t.length); | |
| return o ? (o - levenshteinDistance(e, t)) / o : 0 | |
| } | |
| function stripCommonPrefix(e, t) | |
| { | |
| const o = e.length, | |
| r = t.length, | |
| n = o < r ? o : r; | |
| let i = 0; | |
| for (; i < n && e[i] === t[i];) | |
| i++; | |
| return [ e.slice(i), t.slice(i) ] | |
| } | |
| function articleTitleAndSiteNameFromTitleString(e, t) | |
| { | |
| const o = [ " - ", " \u2013 ", " \u2014 ", ": ", " | ", " \xbb " ], | |
| r = o.length, | |
| n = .6; | |
| for (var i, l, a = e.replace(/^(www|m|secure)\./, ""), s = a.replace(/\.(com|info|net|org|edu|gov)$/, "").toLowerCase(), u = 0; u < r; ++u) { | |
| var c = t.split(o[u]); | |
| if (2 === c.length) { | |
| var d = c[0].trim(), | |
| h = c[1].trim(), | |
| m = d.toLowerCase(), | |
| F = h.toLowerCase(), | |
| f = Math.max(stringSimilarity(m, a), stringSimilarity(m, s)), | |
| g = Math.max(stringSimilarity(F, a), stringSimilarity(F, s)), | |
| p = Math.max(f, g); | |
| (!l || p > l) && (l = p, i = f > g ? { | |
| siteName : d, | |
| articleTitle : h | |
| } | |
| : { | |
| siteName : h, | |
| articleTitle : d | |
| }) | |
| } | |
| } | |
| return i && l >= n ? i : null | |
| } | |
| function documentTitleWithoutHostNamePrefix() | |
| { | |
| const e = document.title, | |
| t = articleTitleAndSiteNameFromTitleString(window.location.host, e); | |
| return t ? t.articleTitle : e | |
| } | |
| function querySelectorAllIncludingWithinShadowRoots(e, t) | |
| { | |
| let o = []; | |
| for (let r of e.querySelectorAll("*")) | |
| if (r.shadowRoot) { | |
| let e = querySelectorAllIncludingWithinShadowRoots(r.shadowRoot, t); | |
| e.length && (o = o.concat(e)) | |
| } else | |
| r.matches(t) && o.push(r); | |
| return o | |
| } | |
| function queryAllBySelector(e, t) | |
| { | |
| try { | |
| return window.collectMatchingElementsInFlatTree ? window.collectMatchingElementsInFlatTree(e, t) : querySelectorAllIncludingWithinShadowRoots(e, t) | |
| } catch (e) { | |
| return [] | |
| } | |
| } | |
| function getElementByID(e) | |
| { | |
| let t = queryAllBySelector(document, `[id='${e}']`); | |
| return t.length ? t[0] : null | |
| } | |
| function siblingsIncludingSelfForElement(e) | |
| { | |
| let t = e.parentElement; | |
| if (t) | |
| return t.children; | |
| let o = e; | |
| for (; o.previousElementSibling;) | |
| o = o.previousElementSibling; | |
| let r = [], | |
| n = o; | |
| for (; n;) | |
| r.push(n), n = n.nextElementSibling; | |
| return r | |
| } | |
| function regularExpressionFromUntrustedPatternAttributeString(e) | |
| { | |
| if (e.startsWith("/") && e.endsWith("/") && (e = e.slice(1, -1)), !e.length) | |
| return null; | |
| try { | |
| return new RegExp(e, "v"), new RegExp("^(?:" + e + ")$", "v") | |
| } catch (e) { | |
| return null | |
| } | |
| } | |
| function regularExpressionsFromStrings(e) | |
| { | |
| return e.map((e => new RegExp(e))) | |
| } | |
| function stringsMatchAnyRegularExpressions(e, t) | |
| { | |
| for (let o of t) | |
| for (let t of e) | |
| if (o.test(t.toLowerCase())) | |
| return !0; | |
| return !1 | |
| } | |
| function pathFromAnchorWithoutLeadingSlash(e) | |
| { | |
| let t = /\/(.*)/.exec(e.pathname); | |
| return t && 2 === t.length ? t[1] : null | |
| } | |
| function innermostActiveElement() | |
| { | |
| let e = document.activeElement, | |
| t = e; | |
| for (; t;) | |
| t = t?.shadowRoot?.activeElement, t && (e = t); | |
| return e | |
| } | |
| function elementAppearsToContinueCaptchaWidget(e) | |
| { | |
| return !!e.querySelector("iframe[title*=captcha i], input[type=hidden][name*=recaptcha]") | |
| } | |
| const WBSAutoFillFormTypeUndetermined = 0, | |
| WBSAutoFillFormTypeAutoFillableStandard = 1, | |
| WBSAutoFillFormTypeNonAutoFillable = 2, | |
| WBSAutoFillFormTypeAutoFillableLogin = 3, | |
| WBSAutoFillFormTypeNewAccount = 4, | |
| WBSAutoFillFormTypeChangePassword = 5, | |
| WBSFormMetadataRequestNormal = 0, | |
| WBSFormMetadataRequestPreFill = 1, | |
| WBSFormMetadataRequestTesting = 2, | |
| WBSFormMetadataRequestTextChange = 3, | |
| WBSFormMetadataRequestCollectMetadataFromDebugMenu = 4, | |
| ShouldStopAfterFirstMatch = { | |
| CollectAllMatches : 0, | |
| StopAfterFirstMatch : 1 | |
| }, | |
| ShouldFocus = { | |
| No : 0, | |
| Yes : 1 | |
| }, | |
| ShouldBlur = { | |
| No : 0, | |
| Yes : 1 | |
| }, | |
| ShouldAbandonCharacterByCharacterEntryIfTooSlow = { | |
| No : 0, | |
| Yes : 1 | |
| }, | |
| ShouldObscure = { | |
| No : 0, | |
| Yes : 1 | |
| }, | |
| ShouldSetAutoFilled = { | |
| No : 0, | |
| Yes : 1 | |
| }, | |
| ForceNonFormElementAsLogicalBackingElement = { | |
| No : !1, | |
| Yes : !0 | |
| }, | |
| LogicalFormCreationIsProvisional = { | |
| No : !1, | |
| Yes : !0 | |
| }, | |
| MatchCriteria = { | |
| Property : 0, | |
| Category : 1, | |
| Literal : 2 | |
| }, | |
| PageScanCharactersSearchedThreshold = 500, | |
| PageScanMaxCharactersSearched = 600, | |
| MaximumNumberOfCharactersToCollectForLanguageIdentification = 300, | |
| MinValueForMaxLengthAttributeToTreatAsPasswordField = 4, | |
| UsernameCandidateScoreForPlainTextField = 1, | |
| UsernameCandidateScoreForPlainTextFieldDirectlyBeforePasswordField = 2, | |
| UsernameCandidateScoreForEmailLabeledFieldBelowPasswordField = 3, | |
| UsernameCandidateScoreForUsernameLabeledFieldBelowPasswordField = 4, | |
| UsernameCandidateScoreForEmailLabeledFieldAbovePasswordField = 5, | |
| UsernameCandidateScoreForUsernameLabeledFieldAbovePasswordField = 6, | |
| UsernameCandidateScoreBonusForVisibleElement = .5, | |
| UsernameCandidateScorePenaltyForReadOnlyElement = .5, | |
| UsernameCandidateScorePenaltyForMatchingNonUsernameFieldLabelPattern = 2, | |
| UsernameCandidateScorePenaltyForMatchingSearchFieldLabelPattern = 1.5, | |
| UsernameCandidateScorePenaltyForAnonymousElement = 1, | |
| LowestScoreForUsernameFieldCandidate = UsernameCandidateScoreForPlainTextField, | |
| LowestScoreForLabeledUsernameFieldCandidate = UsernameCandidateScoreForEmailLabeledFieldBelowPasswordField, | |
| MaxLengthForFieldAboveWhichToTreatPotentialOneTimeCodeFieldAsRequiringHigherScrutiny = 10, | |
| DateTimeInputTypes = [ "date", "datetime-local", "month", "time", "week" ], | |
| DateTimeInputTypeFormats = { | |
| date : "yyyy-MM-dd", | |
| "datetime-local" : "yyyy-MM-dd'T'hh:mm", | |
| month : "yyyy-MM", | |
| time : "hh:mm", | |
| week : "yyyy-'W'ww" | |
| }, | |
| numberOfConsecutiveElementsWithoutSuccessfulPageScanAfterWhichPageScanIsAbandoned = 40; | |
| var mapOfFormTypeToProducerOfAssociatedKeywords = function() { | |
| var e = {}; | |
| return e[WBSAutoFillFormTypeNewAccount] = function() { | |
| return FormMetadataJSController.mapOfKeywordsIndicatingNewAccountFormTypeToScoreForMatching | |
| }, e[WBSAutoFillFormTypeAutoFillableLogin] = function() { | |
| return FormMetadataJSController.mapOfKeywordsIndicatingLoginFormTypeToScoreForMatching | |
| }, e[WBSAutoFillFormTypeChangePassword] = function() { | |
| return FormMetadataJSController.mapOfKeywordsIndicatingChangePasswordFormTypeToScoreForMatching | |
| }, e | |
| }(), visibilityCacheGeneration = 0; | |
| let doctypeLooksLikeHTML5 = "html" === document.doctype?.name && "" === document.doctype?.publicId && "" === document.doctype?.systemId; | |
| console.autofillDebugLog = function() { | |
| FormMetadataJSController.isDebugConsoleLoggingEnabled | |
| }, Node.prototype.traversePreviousNode = function(e) { | |
| if (this) { | |
| var t = this.previousSibling; | |
| if (e(t)) | |
| return null; | |
| for (; t && t.lastChild;) | |
| if (e(t = t.lastChild)) | |
| return null; | |
| return t || this.parentNode | |
| } | |
| }, Node.prototype.traverseNextNode = function(e) { | |
| if (this) { | |
| var t = this.firstChild; | |
| if (t) | |
| return t; | |
| if (e && this === e) | |
| return null; | |
| if (t = this.nextSibling) | |
| return t; | |
| for (t = this; t && !t.nextSibling && (!e || !t.parentNode || t.parentNode !== e);) | |
| t = t.parentNode; | |
| return t ? t.nextSibling : null | |
| } | |
| }, Node.prototype.isVisible = function() { | |
| let e = this; | |
| if (e._isVisible === visibilityCacheGeneration) | |
| return !0; | |
| if (e._isVisible === -visibilityCacheGeneration) | |
| return !1; | |
| let t = e.nodeType == Node.TEXT_NODE ? e.parentElementIncludingShadowDOMHost() : e, | |
| o = getComputedStyle(t, null); | |
| if (e._isVisible = -visibilityCacheGeneration, "none" === o.display || "visible" !== o.visibility) | |
| return !1; | |
| let r = 0 === parseFloat(o.opacity) ? 6 : 2; | |
| return !(t.offsetWidth < r) && (!(t.offsetHeight < r) && (e._isVisible = visibilityCacheGeneration, !0)) | |
| }, Object.defineProperty(Array.prototype, "joinFirstItems", { | |
| value : function(e, t) { | |
| t > this.length && (t = this.length); | |
| for (var o = "", r = 0; r < t; ++r) | |
| r > 0 && (o += e), o += this[r]; | |
| return o | |
| } | |
| }), | |
| DOMRect.prototype.isZeroRect = function() { | |
| return !(this.top || this.right || this.bottom || this.left) | |
| }, DOMRect.prototype.distanceToRect = function(e) { | |
| function t(e) | |
| { | |
| function t(e, t) | |
| { | |
| return Math.pow(e.x - t.x, 2) + Math.pow(e.y - t.y, 2) | |
| } | |
| var o = e[0], | |
| r = e[1]; | |
| return o[0].x >= r[0].x && o[0].x < r[1].x || r[0].x >= o[0].x && r[0].x < o[1].x ? Math.abs(o[0].y - r[0].y) : o[0].y >= r[0].y && o[0].y < r[1].y || r[0].y >= o[0].y && r[0].y < o[1].y ? Math.abs(o[0].x - r[0].x) | |
| : Math.sqrt(Math.min(t(o[0], r[1]), t(o[1], r[0]))) | |
| } | |
| var o = [ { | |
| x : this.left, | |
| y : this.top | |
| }, | |
| { | |
| x : this.right, | |
| y : this.top | |
| } ], | |
| r = [ { | |
| x : this.right, | |
| y : this.top | |
| }, | |
| { | |
| x : this.right, | |
| y : this.bottom | |
| } ], | |
| n = [ { | |
| x : this.left, | |
| y : this.bottom | |
| }, | |
| { | |
| x : this.right, | |
| y : this.bottom | |
| } ], | |
| i = [ { | |
| x : this.left, | |
| y : this.top | |
| }, | |
| { | |
| x : this.left, | |
| y : this.bottom | |
| } ], | |
| l = [ { | |
| x : e.left, | |
| y : e.top | |
| }, | |
| { | |
| x : e.right, | |
| y : e.top | |
| } ], | |
| a = [ { | |
| x : e.right, | |
| y : e.top | |
| }, | |
| { | |
| x : e.right, | |
| y : e.bottom | |
| } ], | |
| s = [ { | |
| x : e.left, | |
| y : e.bottom | |
| }, | |
| { | |
| x : e.right, | |
| y : e.bottom | |
| } ], | |
| u = [ { | |
| x : e.left, | |
| y : e.top | |
| }, | |
| { | |
| x : e.left, | |
| y : e.bottom | |
| } ], | |
| c = [ | |
| [ i, u ], | |
| [ i, a ], | |
| [ o, l ], | |
| [ o, s ], | |
| [ r, u ], | |
| [ r, a ], | |
| [ n, l ], | |
| [ n, s ] | |
| ].map(t); | |
| return Math.min.apply(Math, c) | |
| }, Node.prototype.parentElementIncludingShadowDOMHost = function() { | |
| let e = this.parentElement; | |
| if (e) | |
| return e; | |
| let t = this.getRootNode(); | |
| return t && t.host ? t.host : null | |
| }, Node.prototype.allAncestorsAndSelfIncludingShadowDOMHosts = function() { | |
| let e = [], | |
| t = this; | |
| for (; t;) | |
| e.push(t), t = t.parentElementIncludingShadowDOMHost(); | |
| return e | |
| }, HTMLElement.prototype.closestCommonAncestor = function(e) { | |
| let t = this.parentElement; | |
| for (; t;) { | |
| if (t.contains(e)) | |
| return t; | |
| t = t.parentElement | |
| } | |
| let o = this.allAncestorsAndSelfIncludingShadowDOMHosts().reverse(), | |
| r = e.allAncestorsAndSelfIncludingShadowDOMHosts().reverse(), | |
| n = Math.min(o.length, r.length), | |
| i = null; | |
| for (let e = 0; e < n; ++e) { | |
| if (!(o[e] === r[e])) | |
| break; | |
| i = o[e] | |
| } | |
| return i || null | |
| }, HTMLElement.prototype.isHiddenFromAccessibilityTree = function() { | |
| const e = 2; | |
| for (let o = 0, r = this; o <= e && r; ++o, r = r.parentElementIncludingShadowDOMHost()) { | |
| var t = r.getAttribute("aria-hidden"); | |
| if (t && "true" === t.toLowerCase()) | |
| return !0 | |
| } | |
| return !1 | |
| }, HTMLFormElement.prototype.isVisible = function() { | |
| if (Node.prototype.isVisible.call(this)) | |
| return !0; | |
| for (var e = this.elements, t = e.length, o = 0; o < t; ++o) | |
| if (e[o].isVisible()) | |
| return !0; | |
| return !1 | |
| }, LogicalForm = function(e, t, o) { | |
| let r = e.length; | |
| var n = e[0].form, | |
| i = n; | |
| !t && i || (i = 1 === r ? e[0] : e[0].closestCommonAncestor(e[r - 1])), n && n.contains(e[r - 1]) || (n = i); | |
| let l = FormMetadataJSController.nextFormUniqueID; | |
| i._logicalFormUniqueIDs || (i._logicalFormUniqueIDs = new Set), this._formUniqueID = l, i._logicalFormUniqueIDs.add(), this._metadata = {}, this._weakControls = Array.prototype.map.call(e, (e => new WeakRef(e))), this._weakFormElement = new WeakRef(n), this._weakBackingElement = new WeakRef(i), o || this.markElementsAsPartOfLogicalForm() | |
| }, LogicalForm.prototype = { | |
| get elements() { | |
| return this._weakControls.flatMap((e => e.deref())) | |
| }, | |
| get formElement() { | |
| return this._weakFormElement.deref() | |
| }, | |
| get backingElement() { | |
| return this._weakBackingElement.deref() | |
| }, | |
| get formUniqueID() { | |
| return this._formUniqueID | |
| }, | |
| get metadata() { | |
| return this._metadata | |
| }, | |
| set metadata(e) { | |
| this._metadata = e | |
| }, | |
| containsControl : function(e) { | |
| return "function" == typeof e._logicalFormUniqueIDs?.has ? e._logicalFormUniqueIDs.has(this.formUniqueID) : e.form === this.formElement | |
| }, | |
| radioButtonsWithName : function(e) { | |
| let t = queryAllBySelector(document.documentElement, `*[name="${e}"]`); | |
| return Array.prototype.filter.call(t, (function(e) { | |
| return (e.form === this.formElement || this.formElement?.contains(e)) && isRadioButtonElement(e) | |
| }), | |
| this) | |
| }, | |
| annotate : function(e) { | |
| let t = this.formElement; | |
| if (t) { | |
| var o = t._annotations; | |
| if (o) { | |
| for (var r in e) { | |
| var n = e[r]; | |
| n ? o[r] = n : delete o[r] | |
| } | |
| hasOwnProperties(o) || delete t._annotations | |
| } else | |
| t._annotations = e | |
| } | |
| }, | |
| markElementsAsPartOfLogicalForm : function() { | |
| let e = this._weakControls.length; | |
| for (let t = 0; t < e; t++) { | |
| let o = this._weakControls[t].deref(); | |
| o && (o._logicalFormUniqueIDs || (o._logicalFormUniqueIDs = new Set), o._logicalFormUniqueIDs.add(this.formUniqueID), t + 1 < e && (o._weakNextControlInLogicalForm = this._weakControls[t + 1]), t > 0 && (o._weakPreviousControlInLogicalForm = this._weakControls[t - 1])) | |
| } | |
| }, | |
| get annotations() { | |
| return this.formElement?._annotations | |
| }, | |
| get isAnnotated() { | |
| return !!this.annotations | |
| } | |
| }, | |
| LogicalFormCache = function() { | |
| this._logicalFormsByUniqueID = new Map | |
| }, LogicalFormCache.prototype = { | |
| get size() { | |
| return this._logicalFormsByUniqueID.size | |
| }, | |
| cleanupCache : function() { | |
| let e = new Set; | |
| for (let t of this._logicalFormsByUniqueID.values()) | |
| t.formElement || t.backingElement || e.add(t); | |
| for (let t of e) | |
| this._logicalFormsByUniqueID.delete(t.formUniqueID) | |
| }, | |
| logicalFormForControl : function(e) { | |
| this.cleanupCache(); | |
| for (let t of this._logicalFormsByUniqueID.values()) | |
| if (t.containsControl(e)) | |
| return t; | |
| return null | |
| }, | |
| allForms : function() { | |
| return this.cleanupCache(), Array.from(this._logicalFormsByUniqueID.values()) | |
| }, | |
| addOrUpdate : function(e) { | |
| this._logicalFormsByUniqueID.set(e.formUniqueID, e) | |
| }, | |
| clearCacheAndAdd : function(e) { | |
| this._logicalFormsByUniqueID.clear(); | |
| for (let t of e) | |
| this.addOrUpdate(t) | |
| }, | |
| logicalFormWithUniqueID : function(e) { | |
| return this._logicalFormsByUniqueID.get(e) | |
| } | |
| }, | |
| FormMetadata = function() { | |
| this._logicalFormsCache = new LogicalFormCache, this._elementsWithGeneratedPasswords = [], this._generatedPasswords = [], this._labels = queryAllBySelector(document, "label"), this._controlUniqueIDToWeakControlMap = new Map, this._mapOfFormTypeToExtraScoreProducer = function() { | |
| let e = {}; | |
| return e[WBSAutoFillFormTypeNewAccount] = function() { | |
| return 0 | |
| }, e[WBSAutoFillFormTypeAutoFillableLogin] = function(e) { | |
| const t = 2, | |
| o = function(e) { | |
| return "checkbox" === e.type && FormMetadataJS._labelsForElement(e).some((e => /(remember|keep) me/i.test(e.innerText.trim()) && e.isVisible())) | |
| }; | |
| return 1 === e.elements.filter((e => o(e))).length ? t : 0 | |
| }, e[WBSAutoFillFormTypeChangePassword] = function() { | |
| return 0 | |
| }, e | |
| }(), this._requiredFormatForDateTimeInput = DateTimeInputTypes.reduce((function(e, t) { | |
| let o = document.createElement("input"); | |
| o.type = t; | |
| let r = "a"; | |
| return o.value = r, e[t] = "" === o.value ? DateTimeInputTypeFormats[t] : "", e | |
| }), | |
| {}) | |
| }, FormMetadata.prototype = { | |
| _getTagName : function(e) { | |
| var t = e.tagName; | |
| return "string" == typeof t || "string" == typeof (t = e.nodeName) ? t : void 0 | |
| }, | |
| _getNameOrId : function(e) { | |
| return e.name && e.name.length ? e.name : e.id | |
| }, | |
| controlUniqueID : function(e) { | |
| if (e._controlUniqueID) | |
| return e._controlUniqueID; | |
| var t = "ControlID-" + FormMetadataJSController.nextControlUniqueID; | |
| e._controlUniqueID = t; | |
| this._controlUniqueIDToWeakControlMap.get(t); | |
| return this._controlUniqueIDToWeakControlMap.set(t, new WeakRef(e)), e._controlUniqueID | |
| }, | |
| _searchForLabelsAboveCell : function(e, t) { | |
| var o = window.getComputedStyle(t, null); | |
| if (!o || "table-cell" !== o.getPropertyValue("display")) | |
| return null; | |
| var r = cellVisuallyAbove(t); | |
| if (!r) | |
| return null; | |
| for (var n = 0, i = r.firstChild; i; i = i.traverseNextNode(r)) | |
| if (i.nodeType == Node.TEXT_NODE && i.isVisible()) { | |
| var l = i.nodeValue, | |
| a = e.searchReverse(l); | |
| if (a) | |
| return { | |
| Distance : n, | |
| Match : a[0], | |
| Property : a[1], | |
| Category : a[2], | |
| ParentProperty : a[3] | |
| }; | |
| n += l.length | |
| } | |
| return null | |
| }, | |
| _collectStringFromNodeForPageScan : function(e, t, o) { | |
| var r = e.nodeValue, | |
| n = r.length; | |
| return o + n > PageScanMaxCharactersSearched && (r = r.substr(-(PageScanCharactersSearchedThreshold - o)), n = PageScanCharactersSearchedThreshold - o), (r = r.trim()).length && t.push(r), o | |
| }, | |
| _dataForComputingMatchFromPageScanBeforeElement : function(e, t) { | |
| function o(e) | |
| { | |
| return e && e.nodeType == Node.ELEMENT_NODE && e.matches("nav") | |
| } | |
| var r, n = [], | |
| i = 0; | |
| let l = this._logicalFormsCache.logicalFormForControl(e); | |
| if (!l) | |
| return [ | |
| [], null | |
| ]; | |
| var a = l.formElement, | |
| s = a && a.isVisible(); | |
| t || (t = a); | |
| for (var u = e.traversePreviousNode(o); u && i < PageScanCharactersSearchedThreshold; u = u.traversePreviousNode(o)) { | |
| var c = u.localName; | |
| if (u === t) | |
| break; | |
| if (this._isRenderedFormControl(u)) { | |
| if (u.isVisible() || !s) | |
| break | |
| } else { | |
| if (this._isLabelElement(u) && u.isVisible()) | |
| break; | |
| if ("td" !== c || r) { | |
| if ("tr" === c && r) | |
| break; | |
| if ("ul" === c || "ol" === c || "dl" === c) | |
| break; | |
| if ("li" === c) { | |
| if (!u.parentNode.contains(e)) | |
| break | |
| } else | |
| u.nodeType == Node.TEXT_NODE && u.isVisible() && (i += this._collectStringFromNodeForPageScan(u, n, i)) | |
| } else | |
| r = u | |
| } | |
| } | |
| return [ n, r ] | |
| }, | |
| _matchFromPageScanBeforeElement : function(e, t, o) { | |
| var r = this._pageScanContext ? this._pageScanContext.backwardScanCache : null, | |
| n = this._pageScanDataForElementWithCacheAndDataProducer(t, r, this._dataForComputingMatchFromPageScanBeforeElement.bind(this), o), | |
| i = n[0], | |
| l = this._matchFromPatternMatcherAndStringsFromPageScan(e, i); | |
| if (l) | |
| return l; | |
| var a = n[1]; | |
| if (a) { | |
| var s = this._searchForLabelsAboveCell(e, a); | |
| if (s) | |
| return s.IsInCellAbove = !0, s | |
| } | |
| return null | |
| }, | |
| _isElementFollowedByForgotUserNameOrEmailAffordance : function(e, t) { | |
| this._forgotUserNameRegularExpressions || (this._forgotUserNameRegularExpressions = regularExpressionsFromStrings(FormMetadataJSController.regularExpressionsForForgotUserNameAffordance)), this._forgotEmailRegularExpressions || (this._forgotEmailRegularExpressions = regularExpressionsFromStrings(FormMetadataJSController.regularExpressionsForForgotEmailAffordance)); | |
| let o = this._stringsToEvaluateToDetermineIfElementIsFollowedByAffordance(e, t); | |
| return !!stringsMatchAnyRegularExpressions(o, this._forgotUserNameRegularExpressions) || !!stringsMatchAnyRegularExpressions(o, this._forgotEmailRegularExpressions) | |
| }, | |
| _isElementFollowedByForgotPasswordAffordance : function(e, t) { | |
| return this._forgotPasswordRegularExpressions || (this._forgotPasswordRegularExpressions = regularExpressionsFromStrings(FormMetadataJSController.regularExpressionsForForgotPasswordAffordance)), stringsMatchAnyRegularExpressions(this._stringsToEvaluateToDetermineIfElementIsFollowedByAffordance(e, t), this._forgotPasswordRegularExpressions) | |
| }, | |
| _numberOfForgotUserNameEmailOrPasswordAffordancesFollowingElement : function(e, t) { | |
| this._forgotEmailRegularExpressions || (this._forgotEmailRegularExpressions = regularExpressionsFromStrings(FormMetadataJSController.regularExpressionsForForgotEmailAffordance)), this._forgotPasswordRegularExpressions || (this._forgotPasswordRegularExpressions = regularExpressionsFromStrings(FormMetadataJSController.regularExpressionsForForgotPasswordAffordance)), this._forgotUserNameRegularExpressions || (this._forgotUserNameRegularExpressions = regularExpressionsFromStrings(FormMetadataJSController.regularExpressionsForForgotUserNameAffordance)); | |
| let o = this._stringsToEvaluateToDetermineIfElementIsFollowedByAffordance(e, t), | |
| r = 0; | |
| return stringsMatchAnyRegularExpressions(o, this._forgotUserNameRegularExpressions) && r++, stringsMatchAnyRegularExpressions(o, this._forgotEmailRegularExpressions) && r++, stringsMatchAnyRegularExpressions(o, this._forgotPasswordRegularExpressions) && r++, r | |
| }, | |
| _stringsToEvaluateToDetermineIfElementIsFollowedByAffordance : function(e, t) { | |
| let o = this._dataForComputingMatchFromPageScanAfterElement(e, "A"); | |
| if (!o.length) { | |
| const t = e.traverseNextNode(); | |
| if (t) { | |
| let e = t; | |
| t instanceof Node && (e = t.parentElementIncludingShadowDOMHost()); | |
| const r = e.querySelector("a"); | |
| if (r) { | |
| o.push(r.innerText); | |
| const e = pathFromAnchorWithoutLeadingSlash(r); | |
| e && o.push(e) | |
| } | |
| } | |
| } | |
| if (!o.length) | |
| for (let r of queryAllBySelector(t, "a")) { | |
| if (e.compareDocumentPosition(r) & Node.DOCUMENT_POSITION_FOLLOWING) { | |
| o.push(r.innerText); | |
| const e = pathFromAnchorWithoutLeadingSlash(r); | |
| e && o.push(e) | |
| } | |
| } | |
| const r = e._weakNextControlInLogicalForm?.deref(); | |
| return r && "button" === r.type && o.push(r.innerText), o | |
| }, | |
| _dataForComputingMatchFromPageScanAfterElement : function(e, t, o) { | |
| var r = [], | |
| n = 0, | |
| i = this._logicalFormsCache.logicalFormForControl(e); | |
| if (!i) | |
| return []; | |
| var l = i.formElement, | |
| a = l && l.isVisible(); | |
| let s = void 0 !== t; | |
| o || (o = l); | |
| for (var u = e.traverseNextNode(); u && n < PageScanCharactersSearchedThreshold; u = u.traverseNextNode()) { | |
| var c = u.localName; | |
| if (u === o) { | |
| var d = this._pageScanContext; | |
| d && !n && (d.forwardScanIsFutile = !0); | |
| break | |
| } | |
| if (this._isRenderedFormControl(u)) { | |
| if (u.isVisible() || !a) | |
| break | |
| } else { | |
| if (this._isLabelElement(u) && u.isVisible()) | |
| break; | |
| if ("tr" === c) | |
| break; | |
| if ("ul" === c || "ol" === c || "dl" === c) | |
| break; | |
| if (u.nodeType == Node.TEXT_NODE && u.isVisible()) { | |
| if (void 0 !== t && (!u.parentNode || u.parentNode.tagName !== t)) | |
| continue; | |
| if (n += this._collectStringFromNodeForPageScan(u, r, n), s) | |
| break | |
| } | |
| } | |
| } | |
| return r | |
| }, | |
| _matchFromPageScanAfterElement : function(e, t, o) { | |
| var r = this._pageScanContext ? this._pageScanContext.forwardScanCache : null, | |
| n = this._pageScanDataForElementWithCacheAndDataProducer(t, r, this._dataForComputingMatchFromPageScanAfterElement.bind(this), o); | |
| return this._matchFromPatternMatcherAndStringsFromPageScan(e, n) | |
| }, | |
| _pageScanDataForElementWithCacheAndDataProducer : function(e, t, o, r) { | |
| if (!t) | |
| return o(e, r); | |
| if (n = t.get(e)) | |
| return n; | |
| var n = o(e, r); | |
| return t.set(e, n), n | |
| }, | |
| _matchFromPatternMatcherAndStringsFromPageScan : function(e, t) { | |
| for (var o = t.length, r = 0, n = 0; n < o; ++n) { | |
| var i = t[n]; | |
| r += i.length; | |
| var l = e.searchReverse(i); | |
| if (l) | |
| return | |
| { | |
| Distance: r, | |
| Match: l[0], | |
| Property: l[1], | |
| Category: l[2], | |
| ParentProperty: l[3] | |
| } | |
| } | |
| return null | |
| }, | |
| _matchPatternAgainstString : function(e, t) { | |
| if (!t) | |
| return null; | |
| var o = t.replace(/[\d_.-]/g, " "); | |
| return o = o.replace(/[a-z][A-Z]/g, (function(e) { | |
| return e[0] + " " + e[1] | |
| })), | |
| e.longestMatch(o) | |
| }, | |
| _controlsAreAllButtons : function(e) { | |
| for (var t = e.length, o = 0; o < t; ++o) { | |
| if (!(e[o] instanceof HTMLButtonElement)) | |
| return !1 | |
| } | |
| return !0 | |
| }, | |
| _createLogicalFormsForControls : function(e, t, o) { | |
| if (this._controlsAreAllButtons(e)) | |
| return []; | |
| let r, n, i = e.map((function(e) { | |
| return e.getBoundingClientRect() | |
| })), | |
| l = e.length, | |
| a = 0; | |
| i[0].isZeroRect() ? (r = 0, n = null) : (r = 1, n = i[0]); | |
| for (let h = 1; h < l; ++h) { | |
| let m = i[h]; | |
| if (!m.isZeroRect()) { | |
| if (n) { | |
| let F = n.distanceToRect(m); | |
| F && (++r, a += F) | |
| } | |
| n = m | |
| } | |
| } | |
| if (1 === r) { | |
| function s(e) | |
| { | |
| return e.closest("header, footer, aside") | |
| } | |
| let f = [], | |
| g = 0; | |
| for (; g < l;) { | |
| let p = [ e[g] ], | |
| C = s(e[g]); | |
| for (let _ = g + 1; _ < l; ++_) { | |
| let A = e[_]; | |
| if (C !== s(e[_])) | |
| break; | |
| p.push(A) | |
| } | |
| f.push(new LogicalForm(p, t, o)), g += p.length | |
| } | |
| return f | |
| } | |
| let u = r ? a / r : 0, | |
| c = [], | |
| d = 0; | |
| for (; d < l;) { | |
| let b = [ e[d] ], | |
| y = !1, | |
| S = i[d].isZeroRect() ? null : i[d]; | |
| for (let T = d + 1; T < l; ++T) { | |
| let E = e[T], | |
| I = i[T]; | |
| if (!I.isZeroRect()) { | |
| if (y) { | |
| if (S && S.distanceToRect(I) > u) | |
| break | |
| } else | |
| y = couldBeFormSubmissionControl(E); | |
| S = I | |
| } | |
| b.push(E) | |
| } | |
| c.push(new LogicalForm(b, t, o)), d += b.length | |
| } | |
| return c | |
| }, | |
| _formLooksLikeAspnetForm : function(e) { | |
| const t = 3; | |
| var o = 0; | |
| "aspnetForm" === e.getAttribute("id") && ++o, "aspnetForm" === e.getAttribute("name") && ++o; | |
| for (var r = queryAllBySelector(e, "input"), n = 0, i = r.length; n < i; ++n) { | |
| var l = r[n], | |
| a = l.getAttribute("id"), | |
| s = l.getAttribute("name"); | |
| /ctl\d\d_/.test(a) && ++o, /ctl\d\d\$/.test(s) && ++o, "hidden" === l.getAttribute("type") && ("__VIEWSTATE" === s && "__VIEWSTATE" === a || "__EVENTTARGET" === s && "__EVENTTARGET" === a || "__EVENTARGUMENT" === s && "__EVENTARGUMENT" === a || "__LASTFOCUS" === s && "__LASTFOCUS" === a) && ++o | |
| } | |
| for (var u = queryAllBySelector(document, "script"), c = u.length, d = 0; d < c; ++d) { | |
| var h = anchorWithURLString(u[d].src); | |
| if (h.host === window.location.host) { | |
| var m = lastPathComponentFromAnchor(h); | |
| "WebResource.axd" !== m && "ScriptResource.axd" !== m || ++o | |
| } | |
| } | |
| return o >= t | |
| }, | |
| _anchorLooksLikeSubmitButton : function(e) { | |
| return /submit|button/i.test(e.getAttribute("id")) | |
| }, | |
| _visibleInputAndSelectElementsInForm : function(e) { | |
| let t = queryAllBySelector(e, "input:not([type='hidden']), select"), | |
| o = []; | |
| for (var r = 0, n = t.length; r < n; ++r) { | |
| let e = t[r]; | |
| e.isVisible() && o.push(e) | |
| } | |
| return o | |
| }, | |
| _elementsActingAsButtonsInForm : function(e) { | |
| let t = Array.prototype.slice.call(queryAllBySelector(e, "input[type='submit'], input[type='image']")), | |
| o = queryAllBySelector(e, "a"); | |
| for (var r = 0, n = o.length; r < n; ++r) { | |
| let e = o[r]; | |
| this._anchorLooksLikeSubmitButton(e) && e.isVisible() && t.push(e) | |
| } | |
| return t | |
| }, | |
| _logicalFormsForAspnetForm : function(e) { | |
| function t(e) | |
| { | |
| var o = e.length; | |
| if (o <= 1) | |
| a.push(new LogicalForm(e, ForceNonFormElementAsLogicalBackingElement.Yes)); | |
| else { | |
| var r = o - 1, | |
| n = e[r]; | |
| if (e[0].closestCommonAncestor(n) instanceof HTMLTableRowElement) { | |
| for (var i = 0; i < r; ++i) { | |
| if (!(e[i].closestCommonAncestor(n) instanceof HTMLTableRowElement)) | |
| return t(e.slice(0, i)), void t(e.slice(i)) | |
| } | |
| a.push(new LogicalForm(e, ForceNonFormElementAsLogicalBackingElement.Yes)) | |
| } else | |
| a.push(new LogicalForm(e, ForceNonFormElementAsLogicalBackingElement.Yes)) | |
| } | |
| } | |
| for (var o = this._visibleInputAndSelectElementsInForm(e), r = o.length, n = this._elementsActingAsButtonsInForm(e), i = n.length, l = 0; l < i; ++l) { | |
| (s = n[l]).getAttribute("id") && (s._aspNetIDComponents = s.getAttribute("id").split("_")) | |
| } | |
| n.sort((function(e, t) { | |
| var o = e._aspNetIDComponents || []; | |
| return (t._aspNetIDComponents || []).length - o.length | |
| })); | |
| var a = []; | |
| for (l = 0; l < i; ++l) { | |
| var s, u = (s = n[l])._aspNetIDComponents; | |
| if (u) { | |
| var c = u.length; | |
| if (!(c < 2)) { | |
| for (var d = u.joinFirstItems("_", c - 1) + "_", h = [], m = r - 1; m >= 0; --m) { | |
| var F = o[m], | |
| f = F.getAttribute("id"); | |
| f && (f.startsWith(d) && (h.push(F), o.splice(m, 1))) | |
| } | |
| if (h.length && t(h.reverse()), !(r = o.length)) | |
| break | |
| } | |
| } | |
| } | |
| return r && t(o), a | |
| }, | |
| _logicalFormsInPage : function(e, t) { | |
| let o = []; | |
| const r = document.querySelector("form form"); | |
| let n = {}, | |
| i = r ? document.forms : queryAllBySelector(document, "form"), | |
| l = 0, | |
| a = i.length, | |
| s = new Set; | |
| for (var u = 0; u < a; ++u) { | |
| let a = i[u], | |
| c = r ? a.elements : queryAllBySelector(a, "input, select, textarea, button, fieldset"); | |
| for (let e of c) | |
| s.add(e); | |
| if (c.length) { | |
| if (l++, e && l >= e) | |
| return o; | |
| if (t) { | |
| let e = [ a.method, a.name, a.action, a.className ].join("|"), | |
| o = n[e] || 0; | |
| if (o > t) | |
| continue; | |
| n[e] = o + 1 | |
| } | |
| this._formLooksLikeAspnetForm(a) ? o = o.concat(this._logicalFormsForAspnetForm(a)) : o.push(new LogicalForm(c)) | |
| } | |
| } | |
| let c = [], | |
| d = queryAllBySelector(document, "input, select, textarea, button"), | |
| h = d.length; | |
| for (let e = 0; e < h; ++e) { | |
| let t = d[e]; | |
| if (s.has(t)) { | |
| if (!c.length) | |
| continue; | |
| o = o.concat(this._createLogicalFormsForControls(c)), c = [] | |
| } else | |
| (this._isRenderedFormControl(t) || autocompleteTokens(t)) && c.push(t) | |
| } | |
| c.length && (o = o.concat(this._createLogicalFormsForControls(c))); | |
| let m = o.length; | |
| for (u = 0; u < m - 1; ++u) { | |
| let e = o[u], | |
| t = e.backingElement, | |
| r = t.getBoundingClientRect(), | |
| n = o[u + 1], | |
| i = n.backingElement, | |
| l = i.getBoundingClientRect(); | |
| const a = 40; | |
| if (t.nextElementSibling === i && t.action === i.action && r.height && l.height && r.x === l.x && r.width === l.width && r.bottom + a >= l.top) { | |
| let t = 1 === e.elements.filter((function(e) { | |
| return e.isVisible() | |
| })) | |
| .length, | |
| r = e.elements.includes((function(e) { | |
| return e.matches("input[type=submit], button") && e.isVisible() | |
| })); | |
| if (t && !r) { | |
| let t = e.elements.concat(n.elements), | |
| r = this._createLogicalFormsForControls(t, ForceNonFormElementAsLogicalBackingElement.Yes, LogicalFormCreationIsProvisional.Yes); | |
| if (1 === r.length) { | |
| let e = r[0]; | |
| e.markElementsAsPartOfLogicalForm(), o.splice(u, 2, e), m-- | |
| } | |
| } | |
| } | |
| } | |
| return o | |
| }, | |
| _matchPatternAgainstElement : function(e, t, o) { | |
| function r(e, t) | |
| { | |
| if (!e) | |
| return null; | |
| var r = o[t], | |
| n = sharedPrefixLength(r, e[t]); | |
| return n ? r.substr(n) : null | |
| } | |
| function n(e, t) | |
| { | |
| if (!t) | |
| return null; | |
| const o = t.text; | |
| if (/^-.+-$/.test(o)) | |
| return o; | |
| if (!t.value.length && o.length) { | |
| const r = e.options, | |
| n = r.length; | |
| let i = !0; | |
| for (let e = 0; e < n; ++e) { | |
| const o = r[e]; | |
| if (o !== t && !o.value.length) { | |
| i = !1; | |
| break | |
| } | |
| } | |
| if (i) | |
| return o | |
| } | |
| return null | |
| } | |
| this._logicalFormsCache.logicalFormForControl(o); | |
| var i = o._weakPreviousControlInLogicalForm?.deref(), | |
| l = o._weakNextControlInLogicalForm?.deref(); | |
| const a = [ "name", "id" ], | |
| s = a.length; | |
| for (var u = new Array(s), c = new Array(s), d = 0; d < s; ++d) { | |
| var h = a[d]; | |
| u[d] = r(i, h), c[d] = r(l, h) | |
| } | |
| const m = t.length; | |
| for (var F = 0; F < m; ++F) { | |
| var f, g = t[F]; | |
| for (d = 0; d < s && !(f = this._matchPatternAgainstString(g, u[d])) && !(f = this._matchPatternAgainstString(g, c[d])) && !(f = this._matchPatternAgainstString(g, o[a[d]])); ++d) | |
| ; | |
| const r = "select" === this._getTagName(o).toLowerCase(); | |
| if (!f && r) { | |
| const e = r ? defaultOptionForSelectElement(o) : null, | |
| t = r ? o.options[0] : null; | |
| let i = n(o, e); | |
| i || e === t || (i = n(o, t)), f = this._matchPatternAgainstString(g, i) | |
| } | |
| f && e.push({ | |
| FoundByPageScan : !1, | |
| Match : f[0].toLowerCase(), | |
| Property : f[1], | |
| Category : f[2], | |
| ParentProperty : f[3], | |
| Priority : F | |
| }) | |
| } | |
| }, | |
| _labelsForElement : function(e) { | |
| if (e._cachedLabels) | |
| return e._cachedLabels; | |
| e._cachedLabels = []; | |
| let t = e.getAttribute("aria-labelledby"); | |
| if (t && t.length) { | |
| let r = t.split(" "); | |
| for (var o = 0; o < r.length; o++) { | |
| let t = getElementByID(r[o]); | |
| t && e._cachedLabels.push(t) | |
| } | |
| } | |
| if (e._cachedLabels.length) | |
| return e._cachedLabels; | |
| let r = function(e) { | |
| return e.replace(/[^a-zA-Z0-9]+/g, "") | |
| }; | |
| for (let t of [e.getAttribute("id"), e.getAttribute("name")]) { | |
| if (!t || !t.length) | |
| continue; | |
| let o = [], | |
| n = e.form; | |
| for (let i of this._labels) { | |
| if (n === i.closest("form")) { | |
| let n = i.getAttribute("for"); | |
| if (n === t) | |
| e._cachedLabels.push(i); | |
| else if (n) { | |
| let e = r(n); | |
| e.length > 0 && e === r(t) && o.push(i) | |
| } | |
| } | |
| } | |
| if (0 === e._cachedLabels.length && 1 === o.length && (e._cachedLabels = o), e._cachedLabels.length) | |
| return e._cachedLabels | |
| } | |
| let n = this._logicalFormsCache.logicalFormForControl(e)?.formElement; | |
| for (let t = e.parentElementIncludingShadowDOMHost(); t && t !== n; t = t.parentElementIncludingShadowDOMHost()) | |
| if (this._isLabelElement(t)) { | |
| e._cachedLabels.push(t); | |
| break | |
| } | |
| return e._cachedLabels | |
| }, | |
| _matchesForElement : function(e, t, o = !1) { | |
| function r(e, o) | |
| { | |
| for (var r = 0; r < l; ++r) { | |
| var n = t[r].searchReverse(e); | |
| if (n && (i.push({ | |
| FoundByPageScan : !1, | |
| Match : n[0].toLowerCase(), | |
| Property : n[1], | |
| Category : n[2], | |
| ParentProperty : n[3], | |
| Priority : r | |
| }), | |
| o === ShouldStopAfterFirstMatch.StopAfterFirstMatch)) | |
| return | |
| } | |
| } | |
| function n(e, t) | |
| { | |
| return e && e.Match.length && (!t || !e.IsInCellAbove && t.IsInCellAbove || e.IsInCellAbove == t.IsInCellAbove && e.Distance < t.Distance) ? { | |
| FoundByPageScan : !0, | |
| Match : _.Match.toLowerCase(), | |
| Property : _.Property, | |
| Category : _.Category, | |
| ParentProperty : _.ParentProperty, | |
| Priority : y | |
| } | |
| : t | |
| } | |
| var i = [], | |
| l = t.length; | |
| this._matchPatternAgainstElement(i, t, e); | |
| for (var a = !1, s = this._labelsForElement(e), u = 0; u < s.length; ++u) { | |
| var c = s[u].innerText; | |
| c && (a = !0, r(c, ShouldStopAfterFirstMatch.StopAfterFirstMatch)) | |
| } | |
| let d = placeholderInfoForElement(e); | |
| d && !d.AttributeMatchedWasValue && r(d.Text, ShouldStopAfterFirstMatch.StopAfterFirstMatch); | |
| var h = e.getAttribute("title"); | |
| h && r(h, ShouldStopAfterFirstMatch.StopAfterFirstMatch); | |
| var m = this._labelForElementIfElementAndLabelAreOnlyElementsOfTheirKindAmongSiblingElements(e); | |
| m?.innerText.length && (a = !0, r(m.innerText, ShouldStopAfterFirstMatch.CollectAllMatches)); | |
| let F = this._ariaLabelForElementOrParentOfElement(e); | |
| F && r(F, ShouldStopAfterFirstMatch.StopAfterFirstMatch); | |
| var f = e.getAttribute("formcontrolname"); | |
| f && f.length && r(f, ShouldStopAfterFirstMatch.StopAfterFirstMatch); | |
| var g = this._pageScanContext, | |
| p = !0, | |
| C = !1; | |
| if (g && (g.shouldUsePageScan && (p = g.shouldUsePageScan()), g.reportPageScanUsedSuccessfully && (C = !0)), !p) | |
| return i; | |
| if (a) | |
| return C && g.reportPageScanUsedSuccessfully(!1), i; | |
| if (!0 === o) | |
| return i; | |
| for (var _, A = null, b = null, y = 0; y < l; ++y) | |
| A = n(_ = this._matchFromPageScanBeforeElement(t[y], e), A), g && g.forwardScanIsFutile || (b = n(_ = this._matchFromPageScanAfterElement(t[y], e), b)); | |
| var S = !1; | |
| if (A && (i.push(A), S = !0), b) | |
| for (var T = 0, E = i.length; T < E; ++T) { | |
| var I = i[T]; | |
| if (b.Priority === I.Priority) { | |
| i.push(b), S = !0; | |
| break | |
| } | |
| } | |
| return C && g.reportPageScanUsedSuccessfully(S), i.length && d && d.AttributeMatchedWasValue && r(d.Text, ShouldStopAfterFirstMatch.StopAfterFirstMatch), i | |
| }, | |
| _bestMatchFromMatches : function(e) { | |
| function t(e, t) | |
| { | |
| for (var o = e.length, r = {}, n = 0; n < o; ++n) { | |
| var i, l = e[n]; | |
| switch (t) { | |
| case MatchCriteria.Property: | |
| i = l.Property || l.Match; | |
| break; | |
| case MatchCriteria.Category: | |
| i = l.Category || l.Match; | |
| break; | |
| case MatchCriteria.Literal: | |
| i = l.Match | |
| } | |
| r[i] ? r[i].Frequency += 1 : r[i] = { | |
| Frequency : 1, | |
| FirstMatchObject : l | |
| } | |
| } | |
| var a = []; | |
| for (var s in r) | |
| a.push(r[s]); | |
| var u = a.sort((function(e, t) { | |
| return t.Frequency - e.Frequency | |
| })), | |
| c = u.length; | |
| if (c <= 1) | |
| return null; | |
| if (t === MatchCriteria.Property) | |
| for (n = 0; n < c; ++n) { | |
| if (u[n].FirstMatchObject.ParentProperty in r) | |
| return u[n].FirstMatchObject | |
| } | |
| return u[0].Frequency > u[1].Frequency ? u[0].FirstMatchObject : void 0 | |
| } | |
| var o = e.length; | |
| if (0 === o) | |
| return null; | |
| if (1 === o) | |
| return e[0]; | |
| var r = t(e, MatchCriteria.Property); | |
| return r || ((r = t(e, MatchCriteria.Category)) ? r : e.sort((function(e, t) { | |
| return e.Priority - t.Priority | |
| }))[0]) | |
| }, | |
| _bestMatchForElement : function(e, t, o = !1) { | |
| if (!e) | |
| return null; | |
| var r = this._matchesForElement(e, t, o); | |
| return this._bestMatchFromMatches(r, e, t) | |
| }, | |
| _labelForElementIfElementAndLabelAreOnlyElementsOfTheirKindAmongSiblingElements : function(e) { | |
| for (var t = null, o = e.tagName, r = siblingsIncludingSelfForElement(e), n = r.length, i = 0; i < n; ++i) { | |
| var l = r[i]; | |
| if (e !== l) { | |
| if (o === l.tagName) | |
| return null; | |
| if (this._isLabelElement(l)) { | |
| if (t) | |
| return null; | |
| t = l | |
| } | |
| } | |
| } | |
| return t | |
| }, | |
| _ariaLabelForElementOrParentOfElement : function(e) { | |
| var t = e; | |
| let o = 3; | |
| for (var r = 0; r < o && t; ++r) { | |
| let e = t.getAttribute("aria-label"); | |
| if (e && !t.isHiddenFromAccessibilityTree()) | |
| return e; | |
| t = t.parentElementIncludingShadowDOMHost() | |
| } | |
| return null | |
| }, | |
| _cachedOneTimeCodePatternMatcher : function() { | |
| return this._cachedPatternMatchers("oneTimeCodeFieldLabelPatternMatchers")[0] | |
| }, | |
| _cachedPatternMatchers : function(e) { | |
| let t = "_" + e, | |
| o = this[t]; | |
| return o || (this[t] = FormMetadataJSController[e], o = this[t]), o | |
| }, | |
| _cachedElementPatternMatch : function(e, t, o) { | |
| var r = t + "_wasVisible", | |
| n = e[r]; | |
| if (!0 === n) | |
| return e[t]; | |
| var i = e.isVisible(); | |
| if (n === i) | |
| return e[t]; | |
| e[r] = i; | |
| let l = this._cachedPatternMatchers(o); | |
| return e[t] = this._bestMatchForElement(e, l), e[t] | |
| }, | |
| _isLabeledUsernameField : function(e) { | |
| return !!this._isAutoFillableTextField(e) && null !== this._cachedElementPatternMatch(e, "_usernameFieldPatternMatch", "usernameFieldLabelPatternMatchers") | |
| }, | |
| _isLabeledLoginField : function(e) { | |
| return !!this._isAutoFillableTextField(e) && null !== this._cachedElementPatternMatch(e, "_loginFieldPatternMatch", "loginFormTypePatternMatchers") | |
| }, | |
| _isLabeledSignUpField : function(e) { | |
| return !!this._isAutoFillableTextField(e) && null !== this._cachedElementPatternMatch(e, "_signUpFieldPatternMatch", "newAccountFormTypePatternMatchers") | |
| }, | |
| _isLabeledEmailField : function(e) { | |
| return !!this._isAutoFillableTextField(e) && ("email" === e.type || null !== this._cachedElementPatternMatch(e, "_emailFieldPatternMatch", "emailFieldLabelPatternMatchers")) | |
| }, | |
| _addressBookLabelForElement : function(e) { | |
| if (!this._isAutoFillableTextField(e) && !this._isAutoFillableSelectElement(e) && !this._isAutoFillableTextAreaElement(e)) | |
| return null; | |
| var t = this._cachedElementPatternMatch(e, "_addressBookPatternMatch", "addressBookFieldLabelPatternMatchers"); | |
| return t ? t.Match : null | |
| }, | |
| _elementDisallowsAutocomplete : function(e) { | |
| var t = e.getAttribute("autocomplete"); | |
| return t && "off" === t.toLowerCase() | |
| }, | |
| _isTextArea : function(e) { | |
| return e instanceof HTMLTextAreaElement | |
| }, | |
| _isSelectElement : function(e) { | |
| return e instanceof HTMLSelectElement | |
| }, | |
| _isLabelElement : function(e) { | |
| return e instanceof HTMLLabelElement | |
| }, | |
| _isRenderedFormControl : function(e) { | |
| var t = e.localName; | |
| if (!t) | |
| return !1; | |
| return t in { | |
| button : !0, | |
| isindex : !0, | |
| fieldset : !0, | |
| legend : !0, | |
| meter : !0, | |
| optgroup : !0, | |
| option : !0, | |
| progress : !0, | |
| select : !0, | |
| textarea : !0 | |
| } | |
| || e instanceof HTMLInputElement && (!!this._isElementAHiddenUsername(e) || (!e.type || "hidden" !== e.type)) | |
| }, | |
| _isEditablePlainTextField : function(e) { | |
| return !!isInputElement(e) && (!e.disabled && !e.readOnly && (!e.type || "text" === e.type)) | |
| }, | |
| _isTextField : function(e) { | |
| if (this._isTextArea(e)) | |
| return !0; | |
| if (!isInputElement(e)) | |
| return !1; | |
| const t = { | |
| date : !0, | |
| "datetime-local" : !0, | |
| email : !0, | |
| isindex : !0, | |
| month : !0, | |
| number : !0, | |
| password : !0, | |
| search : !0, | |
| tel : !0, | |
| telephone : !0, | |
| text : !0, | |
| time : !0, | |
| url : !0, | |
| week : !0 | |
| }; | |
| var o = e.type; | |
| return !o || o in t | |
| }, | |
| _isAutofocusedTextField : function(e) { | |
| return !!this._isTextField(e) && !0 === e.autofocus | |
| }, | |
| _isAutoFilledTextField : function(e) { | |
| return !!this._isTextField(e) && e.matches(":-webkit-autofill") | |
| }, | |
| _isSecureTextField : function(e) { | |
| if (!isInputElement(e)) | |
| return !1; | |
| if (e._wasPreviouslySecureTextField) | |
| return !0; | |
| try { | |
| if (e.matches(":-webkit-autofill-strong-password")) | |
| return e._wasPreviouslySecureTextField = !0, !0 | |
| } catch (e) { | |
| } | |
| const t = getComputedStyle(e, null).getPropertyValue("-webkit-text-security"), | |
| o = e.type; | |
| if ("none" !== t || "password" === o) | |
| return e._wasPreviouslySecureTextField = !0, !0; | |
| if (o && "text" !== o) | |
| return !1; | |
| const r = e._weakNextControlInLogicalForm?.deref(); | |
| return !(!r || !this._looksLikeShowHidePasswordButton(r)) && (!!this._matchesPasswordFieldLabelPattern(e) && (e._wasPreviouslySecureTextField = !0, !0)) | |
| }, | |
| _isVerticalWritingMode : function(e) { | |
| const t = getComputedStyle(e).writingMode; | |
| return !("horizontal-tb" === t || "horizontal-bt" === t) | |
| }, | |
| _looksLikePasswordCredentialField : function(e) { | |
| if (!this._isSecureTextField(e)) | |
| return !1; | |
| var t = e.getAttribute("maxlength"); | |
| return !(t && parseInt(t) < MinValueForMaxLengthAttributeToTreatAsPasswordField) && null === this._cachedElementPatternMatch(e, "_nonAccountPasswordSecureTextEntryFieldPatternMatch", "nonAccountPasswordSecureTextEntryFieldLabelPatternMatchers") | |
| }, | |
| _looksLikeShowHidePasswordButton : function(e) { | |
| return !(!this._isCustomFormButton(e) && !this._isCheckboxInputElement(e)) && !!this._cachedElementPatternMatch(e, "_showHideButtonPatternMatch", "showHideButtonLabelPatternMatchers") | |
| }, | |
| _isAutoFillable : function(e) { | |
| return !e.disabled && !e.readOnly | |
| }, | |
| _isAutoFillableSelectElement : function(e) { | |
| return this._isAutoFillable(e) && this._isSelectElement(e) | |
| }, | |
| _isAutoFillableTextAreaElement : function(e) { | |
| return this._isAutoFillable(e) && this._isTextArea(e) | |
| }, | |
| _isAutoFillableTextField : function(e) { | |
| return this._isAutoFillable(e) && this._isTextField(e) | |
| }, | |
| _looksLikeCreditCardNumberField : function(e, t) { | |
| if (!this._isAutoFillableTextField(e)) | |
| return !1; | |
| if (this._cachedElementPatternMatch(e, "_nonCreditCardNumberPatternMatch", "nonCreditCardCardNumberFieldLabelPatternMatchers")) | |
| return !1; | |
| if (this._matchesCreditCardCompositeExpirationDateFieldLabelPatternMatchers(e)) | |
| return !1; | |
| if (elementIDOrAutocompleteTokensHasToken(e, t, "cc-number")) | |
| return !0; | |
| const o = e.placeholder; | |
| let r = new RegExp("[0-9]{4}[ -][0-9]{4}[ -][0-9]{4}[ -][0-9]{4}"); | |
| if (o && r.test(o)) | |
| return !0; | |
| let n = e.getAttribute("data-val-regex-pattern"); | |
| if (n) { | |
| let e = regularExpressionFromUntrustedPatternAttributeString(n); | |
| if (e && !e.test("12345")) | |
| return !1 | |
| } | |
| return null !== this._cachedElementPatternMatch(e, "_creditCardNumberPatternMatch", "creditCardNumberFieldLabelPatternMatchers") | |
| }, | |
| _looksLikeCreditCardSecurityCodeField : function(e, t) { | |
| if (!this._isAutoFillableTextField(e)) | |
| return !1; | |
| if (elementIDOrAutocompleteTokensHasToken(e, t, "cc-csc")) | |
| return !0; | |
| let o = e.getAttribute("pattern"); | |
| if (o) { | |
| let e = regularExpressionFromUntrustedPatternAttributeString(o); | |
| if (e && !e.test("123") && !e.test("1234")) | |
| return !1 | |
| } | |
| return null !== this._cachedElementPatternMatch(e, "_creditCardSecurityCodePatternMatch", "creditCardSecurityCodeFieldLabelPatternMatchers") | |
| }, | |
| _looksLikeCreditCardCardholderField : function(e, t) { | |
| return !!this._isEditablePlainTextField(e) && (!!elementIDOrAutocompleteTokensHasToken(e, t, "cc-name") || null !== this._cachedElementPatternMatch(e, "_creditCardCardholderPatternMatch", "creditCardCardholderFieldLabelPatternMatchers")) | |
| }, | |
| _looksLikeCreditCardCompositeExpirationDateField : function(e, t) { | |
| return !(!this._isAutoFillableTextField(e) || this._isSecureTextField(e)) && (!!elementIDOrAutocompleteTokensHasToken(e, t, "cc-exp") || this._matchesCreditCardCompositeExpirationDateFieldLabelPatternMatchers(e)) | |
| }, | |
| _matchesCreditCardCompositeExpirationDateFieldLabelPatternMatchers : function(e) { | |
| return null !== this._cachedElementPatternMatch(e, "_creditCardCompositeExpirationDateFieldPatternMatch", "creditCardCompositeExpirationDateFieldLabelPatternMatchers") | |
| }, | |
| _looksLikeCreditCardTypeField : function(e, t) { | |
| return !(!this._isSelectElement(e) && !isRadioButtonElement(e)) && (!!elementIDOrAutocompleteTokensHasToken(e, t, "cc-type") || null !== this._cachedElementPatternMatch(e, "_creditCardTypePatternMatch", "creditCardTypeFieldLabelPatternMatchers")) | |
| }, | |
| _looksLikeEIDField : function(e, t) { | |
| return !!elementIDOrAutocompleteTokensHasToken(e, t, "device-eid") | |
| }, | |
| _looksLikeIMEIField : function(e, t) { | |
| return !!elementIDOrAutocompleteTokensHasToken(e, t, "device-imei") | |
| }, | |
| _looksLikeDayField : function(e) { | |
| return !(!this._isAutoFillableTextField(e) && !this._isAutoFillableSelectElement(e)) && null !== this._cachedElementPatternMatch(e, "_dayFieldPatternMatch", "dayFieldLabelPatternMatchers") | |
| }, | |
| _looksLikeMonthField : function(e, t) { | |
| if (!this._isAutoFillableTextField(e) && !this._isAutoFillableSelectElement(e)) | |
| return !1; | |
| if (elementIDOrAutocompleteTokensHasToken(e, t, "cc-exp-month")) | |
| return !0; | |
| if (null !== this._cachedElementPatternMatch(e, "_monthFieldPatternMatch", "monthFieldLabelPatternMatchers")) | |
| return !0; | |
| if ("select" !== this._getTagName(e).toLowerCase()) | |
| return !1; | |
| var o = e.options.length; | |
| if (12 === o || 13 === o) | |
| for (var r = [ selectElementOptionsSequenceAnalysis(e, "text"), selectElementOptionsSequenceAnalysis(e, "value") ], n = r.length, i = 0; i < n; i++) { | |
| var l = r[i], | |
| a = l.lengthOfLongestSequence, | |
| s = l.lastNumberInSequence; | |
| if (a >= 11 && 12 === s) | |
| return !0 | |
| } | |
| return !1 | |
| }, | |
| _looksLikeYearField : function(e, t) { | |
| if (!this._isAutoFillableTextField(e) && !this._isAutoFillableSelectElement(e)) | |
| return !1; | |
| if (elementIDOrAutocompleteTokensHasToken(e, t, "cc-exp-year")) | |
| return !0; | |
| if (null !== this._cachedElementPatternMatch(e, "_yearFieldPatternMatch", "yearFieldLabelPatternMatchers")) | |
| return !0; | |
| if ("select" !== this._getTagName(e).toLowerCase()) | |
| return !1; | |
| var o = selectElementOptionsSequenceAnalysis(e, "text"), | |
| r = o.lengthOfLongestSequence, | |
| n = o.lastNumberInSequence; | |
| const i = 3; | |
| return r >= e.options.length - i && 1e3 < n && n < 3e3 | |
| }, | |
| _looksLikeOneTimeCodeField : function(e, t, o, r, n, i) { | |
| if (!this._isAutoFillableTextField(e) && !this._isAutoFillableSelectElement(e)) | |
| return !1; | |
| if (elementIDOrAutocompleteTokensHasToken(e, t, "one-time-code")) | |
| return !0; | |
| const l = e.type; | |
| if ("password" === l) { | |
| if (/^(.+\.)?chase\.com\.?$/.test(document.location.hostname)) | |
| return !1; | |
| if (this._matchesPasswordFieldLabelPattern(e)) | |
| return !1 | |
| } | |
| if (/^(.+\.)?amazon\.(com|ae|com\.au|com\.br|ca|fr|de|in|it|com\.mx|nl|es|com\.tr|co\.uk|sa|sg|se|pl)\.?$/.test(document.location.hostname)) { | |
| const t = /claim|promo/i; | |
| if (t.test(e.id) || t.test(e.name)) | |
| return !1 | |
| } | |
| if (null !== this._cachedElementPatternMatch(e, "_oneTimeCodePatternMatch", "oneTimeCodeFieldLabelPatternMatchers")) | |
| return !0; | |
| var a = e.getAttribute("maxlength"); | |
| if (a && parseInt(a) > MaxLengthForFieldAboveWhichToTreatPotentialOneTimeCodeFieldAsRequiringHigherScrutiny) { | |
| if (!n) | |
| return !1; | |
| if (i.ControlLooksLikeIgnoredDataTypeField || i.ControlLooksLikeCreditCardCardholderField || i.ControlLooksLikeCreditCardNumberField || i.ControlLooksLikeCreditCardSecurityCodeField || i.ControlLooksLikeCreditCardTypeField || i.AddressBookLabel) | |
| return !1 | |
| } | |
| let s = e.pattern; | |
| if (s) { | |
| let e = regularExpressionFromUntrustedPatternAttributeString(s); | |
| if (e && (e.test("1234") || e.test("123456") || e.test("12345678")) && !e.test("a") && !e.test("A")) | |
| return !0 | |
| } | |
| const u = "number" === l || "tel" === l, | |
| c = a ? parseInt(a) : void 0; | |
| if (1 === c) { | |
| if (u || o || r) | |
| return !0; | |
| const t = this._cachedOneTimeCodePatternMatcher(), | |
| n = e.closest("fieldset"), | |
| i = n?.querySelector("legend"), | |
| l = n ? Array.from(n.querySelectorAll("input")) : [], | |
| a = e === l[0]; | |
| if (i && a && this._matchPatternAgainstString(t, i.innerText)) | |
| return !0; | |
| const s = l.length; | |
| if ((6 === s || 8 === s) && a && l.every((e => 1 === parseInt(e.maxLength)))) | |
| return !0 | |
| } | |
| const d = null !== this._cachedElementPatternMatch(e, "_weakOneTimeCodePatternMatch", "weakOneTimeCodeFieldLabelPatternMatchers"); | |
| if (u && d) | |
| return !0; | |
| const h = e.placeholder; | |
| if (h && d && /^[#]+$/.test(h.replace(/ /g, ""))) | |
| return !0; | |
| if ((4 === c || 6 === c) && d) | |
| return !0; | |
| if (7 === c && h && /\d{3} \d{3}/.test(h)) | |
| return !0; | |
| if (this._isAutofocusedTextField(e)) { | |
| if (d) | |
| return !0; | |
| if ("0" === e.min && "9" === e.max) | |
| return !0 | |
| } | |
| if (n) { | |
| let t = 0; | |
| d && t++, o && t++, r && t++; | |
| const n = this._cachedOneTimeCodePatternMatcher(), | |
| i = this._logicalFormsCache.logicalFormForControl(e); | |
| if (i) { | |
| const e = i.backingElement; | |
| if (e) { | |
| const o = e.querySelector("h1, h2, h3"); | |
| if (o && this._matchPatternAgainstString(n, o.innerText)) | |
| t++; | |
| else { | |
| const o = e.closest("section")?.querySelector("h1, h2, h3"); | |
| o && this._matchPatternAgainstString(n, o.innerText) && t++ | |
| } | |
| } | |
| } | |
| const l = e.dataset.valRequired; | |
| if ("string" == typeof l && this._matchPatternAgainstString(n, l) && t++, t >= 2) | |
| return !0; | |
| const a = function(e) { | |
| if (this._matchPatternAgainstString(n, e)) | |
| return !0; | |
| const t = e.replaceAll("-", " "); | |
| return e !== t && this._matchPatternAgainstString(n, t) | |
| }.bind(this), s = window.location.protocol, u = "http:" === s || "https:" === s, c = lastPathComponentFromAnchor(window.location); | |
| if (u && c && a(c)) | |
| return !0; | |
| { | |
| const e = document.querySelector("link[rel=canonical]"), | |
| t = e ? lastPathComponentForURLString(e.href) : null; | |
| if (t && a(t)) | |
| return !0 | |
| } | |
| if (this._matchFromPageScanBeforeElement(n, e, document.body)) | |
| return !0 | |
| } | |
| return !1 | |
| }, | |
| _looksLikeIgnoredDataTypeField : function(e, t) { | |
| return !!this._isAutoFillableTextField(e) && (!t?.length && null !== this._cachedElementPatternMatch(e, "_ignoredDataTypePatternMatch", "ignoredDataTypeFieldLabelPatternMatchers")) | |
| }, | |
| _collectTextSample : function(e) { | |
| if (!e) | |
| return ""; | |
| var t, o = "", | |
| r = e; | |
| do { | |
| t = (o = r.innerText.replace(/\s+/g, " ").trim()).length, r = r.parentElementIncludingShadowDOMHost() | |
| } while (t < MaximumNumberOfCharactersToCollectForLanguageIdentification && r); | |
| return t > MaximumNumberOfCharactersToCollectForLanguageIdentification && (o = o.substr(0, MaximumNumberOfCharactersToCollectForLanguageIdentification)), o | |
| }, | |
| _explicitMaxLength : function(e) { | |
| var t = e.getAttribute("maxlength"); | |
| return t ? parseInt(t) : void 0 | |
| }, | |
| _explicitMinLength : function(e) { | |
| let t = e.getAttribute("minlength"); | |
| return t ? parseInt(t) : void 0 | |
| }, | |
| _observedMaxLength : function(e) { | |
| const t = 20; | |
| if ("password" !== e.type) | |
| return null; | |
| const o = e.getAttribute("ng-pattern"); | |
| if (!o) | |
| return null; | |
| if (!o.startsWith("/") || !o.endsWith("/")) | |
| return null; | |
| let r = regularExpressionFromUntrustedPatternAttributeString(o); | |
| if (!r) | |
| return null; | |
| let n, i = "a1Abbb", | |
| l = !1; | |
| for (; i.length <= t;) { | |
| let e = r.test(i); | |
| if (l && !e) | |
| return n; | |
| e && (l = !0, n = i.length), i += "b" | |
| } | |
| return null | |
| }, | |
| _collectControlMetadata : function(e, t, o, r, n, i, l) { | |
| var a = { | |
| ControlTagName : this._getTagName(e), | |
| ControlFieldName : this._getNameOrId(e), | |
| ControlUniqueID : this.controlUniqueID(e) | |
| }; | |
| e === innermostActiveElement() && (a.ControlIsActiveElement = !0), this._isAutoFilledTextField(e) && (a.ControlIsAutoFilledTextField = !0), e.disabled && (a.ControlIsDisabled = !0), e.readOnly && (a.ControlIsReadOnly = !0), this._isTextField(e) && (a.ControlIsTextField = !0), this._isSecureTextField(e) && (a.ControlIsSecureTextField = !0), this._isLabeledUsernameField(e) && (a.ControlIsLabeledUsernameField = !0), this._elementDisallowsAutocomplete(e) && (a.DisallowsAutocomplete = !0), this._isAutofocusedTextField(e) && (a.ControlIsAutofocusedTextField = !0); | |
| const s = e.className; | |
| s && s.length && (a.ControlFieldClass = s); | |
| const u = e.id; | |
| u && u.length && (a.ControlFieldID = u); | |
| const c = e.value; | |
| c && (a.ControlValue = c); | |
| const d = this._associatedUsernameForControl(e); | |
| d && (a.ControlAssociatedUsername = d); | |
| const h = e.maxLength; | |
| if (-1 !== h) | |
| a.ControlMaxLength = h; | |
| else { | |
| const t = this._observedMaxLength(e); | |
| t && (a.ControlMaxLength = t) | |
| } | |
| const m = this._explicitMinLength(e); | |
| m && m > 0 && (a.ControlMinLength = m); | |
| const F = e.size; | |
| F > 0 && (a.ControlSize = F), e.isVisible() && (a.IsVisible = !0), isDateTimeInputElement(e) && (a.ControlRequiredFormatForDateTimeInput = this._requiredFormatForDateTimeInput[e.type]); | |
| var f = autocompleteTokens(e); | |
| f && (a.AutocompleteTokens = f, -1 !== f.indexOf("username") ? a.ControlClaimsToBeUsernameViaAutocompleteAttribute = !0 : -1 !== f.indexOf("current-password") ? a.ControlClaimsToBeCurrentPasswordViaAutocompleteAttribute = !0 | |
| : -1 !== f.indexOf("new-password") && (a.ControlClaimsToBeNewPasswordViaAutocompleteAttribute = !0)), | |
| this._looksLikePasswordCredentialField(e) && (a.ControlLooksLikePasswordCredentialField = !0, "function" == typeof this._collectExtraControlMetadata && this._collectExtraControlMetadata(e, a), a.IsVisible && !o && (a.IsVisible = !isElementPositionedToBeEffectivelyInvisible(e))); | |
| let g = t === WBSFormMetadataRequestPreFill, | |
| p = a.ControlIsActiveElement || !g; | |
| if (p) { | |
| const t = this._collectSelectElementInfo(e); | |
| t && (a.SelectElementInfo = t), this._isVerticalWritingMode(e) && (a.ControlIsVerticalWritingMode = !0); | |
| var C = placeholderInfoForElement(e); | |
| C && !C.AttributeMatchedWasValue && (a.ControlPlaceholder = C.Text) | |
| } | |
| if (this._looksLikeIgnoredDataTypeField(e, f) ? a.ControlLooksLikeIgnoredDataTypeField = !0 : this._looksLikeCreditCardCardholderField(e, f) ? a.ControlLooksLikeCreditCardCardholderField = !0 | |
| : this._looksLikeCreditCardNumberField(e, f) ? a.ControlLooksLikeCreditCardNumberField = !0 | |
| : this._looksLikeCreditCardSecurityCodeField(e, f) ? a.ControlLooksLikeCreditCardSecurityCodeField = !0 | |
| : this._looksLikeCreditCardTypeField(e, f) && (a.ControlLooksLikeCreditCardTypeField = !0), | |
| p && (this._looksLikeMonthField(e, f) ? a.ControlLooksLikeMonthField = !0 : this._looksLikeYearField(e, f) ? a.ControlLooksLikeYearField = !0 | |
| : this._looksLikeDayField(e) ? a.ControlLooksLikeDayField = !0 | |
| : !a.ControlLooksLikeCreditCardSecurityCodeField && this._looksLikeCreditCardCompositeExpirationDateField(e, f) && (a.ControlLooksLikeCreditCardCompositeExpirationDateField = !0)), | |
| g || (this._looksLikeEIDField(e, f) ? a.ControlLooksLikeEIDField = !0 : this._looksLikeIMEIField(e, f) && (a.ControlLooksLikeIMEIField = !0)), g || a.ControlLooksLikeIgnoredDataTypeField || a.ControlIsSecureTextField || a.ControlLooksLikeCreditCardNumberField || a.ControlLooksLikeCreditCardSecurityCodeField || a.ControlLooksLikeCreditCardTypeField || a.ControlLooksLikeCreditCardCompositeExpirationDateField || a.ControlLooksLikeEIDField || a.ControlLooksLikeIMEIField || (a.AddressBookLabel = this._addressBookLabelForElement(e)), a.ControlIsActiveElement || t === WBSFormMetadataRequestTesting || l) { | |
| let t = i && a.IsVisible; | |
| this._looksLikeOneTimeCodeField(e, f, r, n, t, a) && (a.ControlLooksLikeOneTimeCodeField = !0) | |
| } | |
| return a | |
| }, | |
| _usesGeneratedPassword : function(e) { | |
| for (var t = !1, o = this._elementsWithGeneratedPasswords.length, r = 0; r < o; ++r) { | |
| var n = this._elementsWithGeneratedPasswords[r]; | |
| if (e.containsControl(n)) { | |
| if (n.value !== this._generatedPasswords[r]) | |
| return !1; | |
| t = !0 | |
| } | |
| } | |
| return t | |
| }, | |
| _associatedUsernameForControl : function(e) { | |
| return this._isAutoFillableTextField(e) ? e.getAttribute("data-username") : null | |
| }, | |
| _collectSelectElementInfo : function(e) { | |
| if (!this._isAutoFillableSelectElement(e)) | |
| return null; | |
| if (!e.options.length) | |
| return null; | |
| for (var t = [], o = e.options, r = o.length, n = 0; n < r; ++n) { | |
| var i = o[n]; | |
| i.disabled || (i.label || i.text) && t.push([ n, i.label ? i.label : i.text ]) | |
| } | |
| return t.length ? t : null | |
| }, | |
| _stringsToInspectForDeterminingFormType : function(e) { | |
| let t = [], | |
| o = e.formElement, | |
| r = o.getAttribute("id"), | |
| n = o.getAttribute("name"); | |
| r && t.push(r), n && t.push(n); | |
| let i = queryAllBySelector(o, "legend"); | |
| 1 === i.length && t.push(i[0].innerText); | |
| let l = 0; | |
| for (let e of this._logicalFormsCache.allForms()) | |
| e.formElement.isVisible() && l++; | |
| const a = .8; | |
| if (1 === l && o.isVisible() && !o.ownerDocument.defaultView.frameElement && o.getBoundingClientRect().top < a * document.documentElement.clientHeight) { | |
| let e = documentTitleWithoutHostNamePrefix(); | |
| e && t.push(e); | |
| const o = lastPathComponentFromAnchor(window.location); | |
| o && o.length && t.push(o) | |
| } | |
| let s = []; | |
| if (o.isVisible()) { | |
| const e = function(e, t) { | |
| return t.left <= e.left && e.right <= t.right && e.distanceToRect(t) < 100 || e.left - t.left == t.right - e.right && e.distanceToRect(t) < 200 | |
| }; | |
| let r = o.getBoundingClientRect(), | |
| n = !1; | |
| for (let i = 0, l = o; i <= 2 && l; ++i, l = l.parentElementIncludingShadowDOMHost()) { | |
| let o = Array.prototype.slice.call(queryAllBySelector(l, "h1, h2, h3, [class*='header' i], [class*='heading' i]")), | |
| i = [ | |
| [], | |
| [], | |
| [], | |
| [] | |
| ]; | |
| for (headerElement of o) { | |
| let e = headerElement.tagName; | |
| "H1" === e ? i[0].push(headerElement) : "H2" === e ? i[1].push(headerElement) | |
| : "H3" === e ? i[2].push(headerElement) | |
| : i[3].push(headerElement) | |
| } | |
| let a = !0; | |
| for (headerElementsOfType of i) { | |
| let o = headerElementsOfType.length; | |
| if (0 === o) { | |
| a = !1; | |
| continue | |
| } | |
| if (o > 1) | |
| break; | |
| let i = headerElementsOfType[0]; | |
| if (!i.isVisible()) | |
| break; | |
| e(i.getBoundingClientRect(), r) && (t.push(i.innerText), n = !0); | |
| break | |
| } | |
| if (a) | |
| break | |
| } | |
| if (!n) { | |
| let o = queryAllBySelector(document.documentElement, "h1"); | |
| if (1 === o.length) { | |
| let n = o[0]; | |
| e(n.getBoundingClientRect(), r) && t.push(n.innerText) | |
| } | |
| } | |
| for (let e = 0, t = o; e <= 2 && t; ++e, t = t.parentElementIncludingShadowDOMHost()) { | |
| let e = Array.prototype.slice.call(queryAllBySelector(t, "button, input[type=submit]")).filter((function(e) { | |
| if (!e.isVisible()) | |
| return !1; | |
| let t = e.getBoundingClientRect(); | |
| return t.top > r.bottom && !o.contains(e) && r.left <= t.left && t.right <= r.right && t.distanceToRect(r) < 100 | |
| })); | |
| if (e.length) { | |
| s = e; | |
| break | |
| } | |
| } | |
| } | |
| let u = !1, | |
| c = [], | |
| d = e.elements.concat(s); | |
| for (const e of d) { | |
| const o = e.type; | |
| "password" === o && (u = !0), "submit" !== o && "button" !== o || u && (e.isVisible() ? this._addInterestingStringsForButton(e, t) : c.push(e)) | |
| } | |
| if (0 === t.length) | |
| for (control of c) | |
| this._addInterestingStringsForButton(control, t); | |
| return t | |
| }, | |
| _addInterestingStringsForButton : function(e, t) { | |
| const o = e.getAttribute("id"); | |
| o && t.push(o); | |
| const r = e.getAttribute("value"); | |
| r && t.push(r); | |
| const n = e.innerText; | |
| n && n.length > 0 && t.push(n) | |
| }, | |
| _autoFillFormTypeOfTypesUsingKeywordMatching : function(e, t, o, r) { | |
| for (var n = t.length, i = [], l = 0; l < n; ++l) { | |
| var a = (0, mapOfFormTypeToProducerOfAssociatedKeywords[t[l]])(); | |
| i.push(a) | |
| } | |
| var s = this._stringsToInspectForDeterminingFormType(e), | |
| u = this._keywordsIndicatingNonAutoFillableFormType; | |
| u || (u = FormMetadataJSController.keywordsIndicatingNonAutoFillableFormType, this._keywordsIndicatingNonAutoFillableFormType = u); | |
| var c = u.length, | |
| d = []; | |
| for (l = 0; l < n; ++l) | |
| d.push(0); | |
| if (r) | |
| for (const [e, o] of Object.entries(r)) | |
| d[t.indexOf(parseInt(e))] += o; | |
| for (var h = s.length, m = 0; m < h; ++m) { | |
| for (var F = s[m].toLowerCase(), f = 0; f < c; ++f) | |
| if (-1 !== F.indexOf(u[f])) | |
| return WBSAutoFillFormTypeNonAutoFillable; | |
| for (l = 0; l < n; ++l) { | |
| a = i[l]; | |
| for (var g in a) | |
| -1 !== F.indexOf(g) && (d[l] += a[g]) | |
| } | |
| } | |
| for (let o = 0; o < n; ++o) { | |
| const r = this._mapOfFormTypeToExtraScoreProducer[t[o]]; | |
| d[o] += r(e) | |
| } | |
| for (l = 0; l < n; ++l) | |
| 0 !== d[l] && 0; | |
| var p = formActionAsAnchorElement(e.formElement, !0); | |
| if (p) { | |
| var C = p.pathname.toLowerCase() + p.search.toLowerCase(); | |
| for (l = 0; l < n; ++l) { | |
| a = i[l]; | |
| for (var g in a) | |
| -1 !== C.indexOf(g) && (d[l] += a[g]) | |
| } | |
| } | |
| var _ = [], | |
| A = 0; | |
| for (l = 0; l < n; ++l) { | |
| var b = d[l]; | |
| b > 0 && (b >= A ? (A = b, _.unshift(l)) : _.push(l)) | |
| } | |
| if (1 === _.length) | |
| return t[_[0]]; | |
| if (_.length > 1) { | |
| var y = _[0]; | |
| if (d[y] > d[_[1]]) | |
| return t[y] | |
| } | |
| return o | |
| }, | |
| _matchesNonUsernameFieldLabelPattern : function(e) { | |
| if (this._nonUsernameFieldPatternMatchers || (this._nonUsernameFieldPatternMatchers = FormMetadataJSController.nonUsernameFieldLabelPatternMatchers), this._bestMatchForElement(e, this._nonUsernameFieldPatternMatchers)) | |
| return !0; | |
| const t = e.value; | |
| if (!e.id && !e.name && t && e.disabled) | |
| for (const e of this._nonUsernameFieldPatternMatchers) | |
| if (this._matchPatternAgainstString(e, t)) | |
| return !0; | |
| return !1 | |
| }, | |
| _matchSearchFieldLabelPattern : function(e) { | |
| if (this._searchFieldLabelPatternMatchers || (this._searchFieldLabelPatternMatchers = FormMetadataJSController.searchFieldLabelPatternMatchers), this._bestMatchForElement(e, this._searchFieldLabelPatternMatchers, !0)) | |
| return !0; | |
| const t = e.value; | |
| if (!e.id && !e.name && t && e.disabled) | |
| for (const e of this._searchFieldLabelPatternMatchers) | |
| if (this._matchPatternAgainstString(e, t)) | |
| return !0; | |
| return !1 | |
| }, | |
| _matchesNonEmailFieldLabelPattern : function(e) { | |
| return this._nonEmailFieldPatternMatchers || (this._nonEmailFieldPatternMatchers = FormMetadataJSController.nonEmailFieldLabelPatternMatchers), !!this._bestMatchForElement(e, this._nonEmailFieldPatternMatchers) | |
| }, | |
| _scoreForUsernameFieldCandidateFromLabelingAndPositionOfField : function(e, t, o) { | |
| return this._isLabeledUsernameField(e) ? t ? UsernameCandidateScoreForUsernameLabeledFieldBelowPasswordField : UsernameCandidateScoreForUsernameLabeledFieldAbovePasswordField : this._isLabeledEmailField(e) && !this._matchesNonEmailFieldLabelPattern(e) ? t ? UsernameCandidateScoreForEmailLabeledFieldBelowPasswordField : UsernameCandidateScoreForEmailLabeledFieldAbovePasswordField | |
| : o ? UsernameCandidateScoreForPlainTextFieldDirectlyBeforePasswordField | |
| : UsernameCandidateScoreForPlainTextField | |
| }, | |
| _scoreForUsernameFieldCandidate : function(e, t, o) { | |
| var r = this._scoreForUsernameFieldCandidateFromLabelingAndPositionOfField(e, t, o); | |
| return e.isVisible() && (r += UsernameCandidateScoreBonusForVisibleElement), this._matchesNonUsernameFieldLabelPattern(e) && (r -= UsernameCandidateScorePenaltyForMatchingNonUsernameFieldLabelPattern), this._matchSearchFieldLabelPattern(e) && (r -= UsernameCandidateScorePenaltyForMatchingSearchFieldLabelPattern), e.readOnly && (r -= UsernameCandidateScorePenaltyForReadOnlyElement), e.id || e.name || (r -= UsernameCandidateScorePenaltyForAnonymousElement), r | |
| }, | |
| _matchesPasswordFieldLabelPattern : function(e) { | |
| return this._passwordFieldPatternMatchers || (this._passwordFieldPatternMatchers = FormMetadataJSController.passwordFieldLabelPatternMatchers), !!this._bestMatchForElement(e, this._passwordFieldPatternMatchers) | |
| }, | |
| _matchesConfirmPasswordFieldLabelPattern : function(e, t = !1) { | |
| return this._confirmPasswordFieldPatternMatchers || (this._confirmPasswordFieldPatternMatchers = FormMetadataJSController.confirmPasswordFieldLabelPatternMatchers), !!this._bestMatchForElement(e, this._confirmPasswordFieldPatternMatchers, t) | |
| }, | |
| _matchesConfirmEmailFieldLabelPattern : function(e) { | |
| return !!this._isLabeledEmailField(e) && (this._confirmEmailFieldPatternMatchers || (this._confirmEmailFieldPatternMatchers = FormMetadataJSController.confirmEmailFieldLabelPatternMatchers), !!this._bestMatchForElement(e, this._confirmEmailFieldPatternMatchers)) | |
| }, | |
| _collectRadioButtonInfo : function(e, t) { | |
| function o(e, t) | |
| { | |
| var o = e.trim(); | |
| o && t.push(o) | |
| } | |
| function r(e, t) | |
| { | |
| o(e.alt, t), o(e.title, t), o(lastPathComponentForURLString(e.src), t) | |
| } | |
| function n(e) | |
| { | |
| let t = []; | |
| o(e.innerText, t); | |
| let n = queryAllBySelector(e, "img"), | |
| i = n.length; | |
| for (let e = 0; e < i; ++e) | |
| r(n[e], t); | |
| return t.length ? t : null | |
| } | |
| for (var i = e.radioButtonsWithName(t), l = i.length, a = !1, s = {}, u = 0; u < l; ++u) { | |
| s[(f = i[u]).value] = [ f.value ]; | |
| for (var c = this._labelsForElement(f), d = c.length, h = 0; h < d; ++h) { | |
| a = !0; | |
| var m = n(c[h]); | |
| m && (s[f.value] = s[f.value].concat(m)) | |
| } | |
| } | |
| if (a) | |
| return s; | |
| const F = 64; | |
| for (u = 0; u < l; ++u) { | |
| for (var f, g = "", p = (f = i[u]).traverseNextNode(); p && !this._isRenderedFormControl(p); p = p.traverseNextNode()) { | |
| var C = p.localName; | |
| if ("td" === C || "tr" === C || "ul" === C || "ol" === C || "dl" === C) | |
| break; | |
| if (p instanceof HTMLImageElement) | |
| r(p, s[f.value]); | |
| else if (p.nodeType === Node.TEXT_NODE) { | |
| var _ = p.nodeValue.trim(); | |
| if (_ && (g += _.substr(0, F - g.length)), g.length >= F) | |
| break | |
| } | |
| } | |
| g && s[f.value].push(g) | |
| } | |
| return s | |
| }, | |
| _bestUsernameFieldCandidate : function(e, t, o) { | |
| var r = t.FormControls, | |
| n = r.filter((function(e) { | |
| return e.ControlClaimsToBeUsernameViaAutocompleteAttribute | |
| })); | |
| if (1 === n.length) | |
| return n[0]; | |
| for (var i = 0, l = [], a = !1, s = r.indexOf(o), u = r.length, c = 0; c < u; ++c) { | |
| var d = r[c]; | |
| if (d === o) { | |
| a = !0; | |
| continue | |
| } | |
| if (!d.ControlIsTextField || d.ControlIsSecureTextField) | |
| continue; | |
| if (t.IsVisible && !r[c].IsVisible && !d.ControlValue) | |
| continue; | |
| const n = 100; | |
| let F = e[c]; | |
| if (!(F.value.length > n)) { | |
| var h = c + 1 < u && c + 1 === s, | |
| m = this._scoreForUsernameFieldCandidate(F, a, h); | |
| m > i ? (l = [ c ], i = m) : m === i && l.push(c) | |
| } | |
| } | |
| var F = l.length; | |
| if (i < LowestScoreForLabeledUsernameFieldCandidate && F > 1) | |
| return null; | |
| if (i < LowestScoreForUsernameFieldCandidate) | |
| return null; | |
| switch (F) { | |
| case 0: | |
| return null; | |
| case 1: | |
| return r[l[0]]; | |
| default: | |
| var f = e[s].getBoundingClientRect(), | |
| g = {}; | |
| return l.forEach((function(t) { | |
| g[t] = f.distanceToRect(e[t].getBoundingClientRect()) | |
| })), | |
| r[l.sort((function(e, t) { | |
| return g[e] - g[t] | |
| }))[0]] | |
| } | |
| }, | |
| _autoFillFormTypeFromCandidateFormTypes : function(e, t, o) { | |
| switch (t.length) { | |
| case 1: | |
| return t[0]; | |
| case 2: | |
| return this._autoFillFormTypeOfTypesUsingKeywordMatching(e, [ t[0], t[1] ], o); | |
| default: | |
| return WBSAutoFillFormTypeAutoFillableStandard | |
| } | |
| }, | |
| _shouldTrustElementThatClaimsToBeCurrentPasswordViaAutocompleteAttribute : function(e) { | |
| return !e.dataset.valRegexPattern | |
| }, | |
| _identifyFormTypeAndPasswordFieldIndicesFromAutocompleteAttributes : function(e, t) { | |
| const o = [ null, null ]; | |
| if (/^(.+\.)?roll20\.net\.?$/.test(document.location.hostname)) | |
| return o; | |
| var r = t.length; | |
| if (r > 3) | |
| return o; | |
| for (var n = [], i = [], l = 0; l < r; ++l) { | |
| var a = t[l]; | |
| a.ControlClaimsToBeCurrentPasswordViaAutocompleteAttribute && this._shouldTrustElementThatClaimsToBeCurrentPasswordViaAutocompleteAttribute(e[l]) ? n.push(l) : a.ControlClaimsToBeNewPasswordViaAutocompleteAttribute && i.push(l) | |
| } | |
| var s = n.length, | |
| u = i.length; | |
| if (s + u !== r) | |
| return o; | |
| switch (r) { | |
| case 0: | |
| return o; | |
| case 1: | |
| if (s) | |
| return [ | |
| [ WBSAutoFillFormTypeAutoFillableLogin ], { | |
| PasswordFieldIndex : n[0] | |
| } | |
| ]; | |
| if (u) | |
| return [ null, null, WBSAutoFillFormTypeNewAccount ]; | |
| case 2: | |
| if (1 === s && 1 === u) | |
| return [ | |
| [ WBSAutoFillFormTypeChangePassword ], { | |
| OldPasswordFieldIndex : n[0], | |
| PasswordFieldIndex : i[0] | |
| } | |
| ]; | |
| if (0 === s && 2 === u) | |
| return [ | |
| [ WBSAutoFillFormTypeNewAccount, WBSAutoFillFormTypeChangePassword ], { | |
| PasswordFieldIndex : i[0], | |
| ConfirmationFieldIndex : i[1] | |
| } | |
| ]; | |
| break; | |
| case 3: | |
| if (1 === s && 2 === u) | |
| return [ | |
| [ WBSAutoFillFormTypeChangePassword ], { | |
| OldPasswordFieldIndex : n[0], | |
| PasswordFieldIndex : i[0], | |
| ConfirmationFieldIndex : i[1] | |
| } | |
| ] | |
| } | |
| return o | |
| }, | |
| _identifyPasswordFieldIndices : function(e, t) { | |
| var o = e.length; | |
| if (0 === o) | |
| return {}; | |
| if (1 === o) | |
| return { | |
| PasswordFieldIndex : 0 | |
| }; | |
| if (this._oldPasswordPatternMatchers || (this._oldPasswordPatternMatchers = FormMetadataJSController.oldPasswordFieldLabelPatternMatchers), 2 === o) { | |
| return this._bestMatchForElement(t[0], this._oldPasswordPatternMatchers) ? { | |
| OldPasswordFieldIndex : 0, | |
| PasswordFieldIndex : 1 | |
| } | |
| : this._bestMatchForElement(t[1], this._oldPasswordPatternMatchers) ? { | |
| OldPasswordFieldIndex : 1, | |
| PasswordFieldIndex : 0 | |
| } | |
| : { | |
| PasswordFieldIndex : 0, | |
| ConfirmationFieldIndex : 1 | |
| } | |
| } | |
| return this._bestMatchForElement(t[o - 1], this._oldPasswordPatternMatchers) ? { | |
| PasswordFieldIndex : o - 3, | |
| ConfirmationFieldIndex : o - 2, | |
| OldPasswordFieldIndex : o - 1 | |
| } | |
| : { | |
| PasswordFieldIndex : o - 2, | |
| ConfirmationFieldIndex : o - 1, | |
| OldPasswordFieldIndex : o - 3 | |
| } | |
| }, | |
| _removePlaceholderTextForFormMetadata : function(e, t) { | |
| for (var o = e.length, r = 0; r < o; ++r) { | |
| var n = t.FormControls[r]; | |
| if (n.ControlValue && n.ControlIsTextField && !n.ControlIsSecureTextField && !n.ControlIsReadOnly) { | |
| var i = legacyPlaceholderInfoForInputElement(e[r]); | |
| i && (i.AttributeMatchedWasValue && n.ControlUniqueID === t.UsernameElementUniqueID || (n.ControlValue = "")) | |
| } | |
| } | |
| }, | |
| _isPasswordConfirmPair : function(e, t) { | |
| var o = this._matchesPasswordFieldLabelPattern(e), | |
| r = this._matchesConfirmPasswordFieldLabelPattern(t); | |
| return o && r | |
| }, | |
| _trailingArgumentsForCollectControlMetadataFunction : function(e, t, o) { | |
| let r = isElementPositionedToBeEffectivelyInvisible(e.backingElement), | |
| n = !1, | |
| i = !1; | |
| if (innermostActiveElement() || t === WBSFormMetadataRequestTesting) { | |
| let e = this._cachedOneTimeCodePatternMatcher(); | |
| if (n = !!this._matchPatternAgainstString(e, documentTitleWithoutHostNamePrefix()), o) { | |
| let t = location.pathname.split("/"), | |
| r = stripCommonPrefix(o.pathname.split("/"), t)[0].join("/"); | |
| r.length && (i = !!this._matchPatternAgainstString(e, r)) | |
| } | |
| } | |
| let l = !1; | |
| for (let t of e.elements) | |
| if (this._isTextField(t) && t.isVisible()) { | |
| if (l) { | |
| l = !1; | |
| break | |
| } | |
| l = !0 | |
| } | |
| return [ r, i, n, l ] | |
| }, | |
| _collectFormMetadata : function(e, t) { | |
| var o, r, n = (r = 0, { | |
| backwardScanCache : new WeakMap, | |
| forwardScanCache : new WeakMap, | |
| shouldUsePageScan : function() { | |
| return r < numberOfConsecutiveElementsWithoutSuccessfulPageScanAfterWhichPageScanIsAbandoned | |
| }, | |
| willStartCollectingMetadataForControl : function() { | |
| o = null | |
| }, | |
| reportPageScanUsedSuccessfully : function(e) { | |
| o = !(!e && !o) | |
| }, | |
| didFinishCollectingMetadataForControl : function() { | |
| !0 === o ? r = 0 : !1 === o && r++ | |
| } | |
| }); | |
| this._pageScanContext = n; | |
| var i = e.formElement, | |
| l = { | |
| FormID : e.formUniqueID, | |
| ContainsActiveElement : !1, | |
| FormControls : [], | |
| AutoFillFormType : WBSAutoFillFormTypeAutoFillableStandard, | |
| UsernameElementUniqueID : void 0, | |
| OldPasswordElementUniqueID : void 0, | |
| PasswordElementUniqueID : void 0, | |
| ConfirmPasswordElementUniqueID : void 0, | |
| UsesGeneratedPassword : this._usesGeneratedPassword(e), | |
| FirstCreditCardCardholderFieldOrCreditCardNumberFieldUniqueID : void 0, | |
| IsVisible : i.isVisible(), | |
| TextSample : void 0, | |
| RequestType : t | |
| }; | |
| this._elementDisallowsAutocomplete(i) && (l.DisallowsAutocomplete = !0), i instanceof HTMLFormElement && (l.FormIsSearchForm = this._isSearchForm(i, !0)), e.isAnnotated && (l.Annotations = e.annotations); | |
| var a = i.getAttribute("rel"); | |
| a && "async" === a.toLowerCase() && (l.FormUsesRelAsync = !0); | |
| let s = formActionAsAnchorElement(i); | |
| if (s && s.href && (l.FormAction = s.href), t == WBSFormMetadataRequestCollectMetadataFromDebugMenu || t == WBSFormMetadataRequestTesting) { | |
| let e = selectorForElement(i); | |
| e && e.length && (l.LogicalFormElementSelector = e) | |
| } | |
| var u = e.elements, | |
| c = !u.some(this._isSecureTextField.bind(this)); | |
| let [d, h, m, F] = this._trailingArgumentsForCollectControlMetadataFunction(e, t, s); | |
| var f = 0, | |
| g = !1, | |
| p = [], | |
| C = [], | |
| _ = [], | |
| A = [], | |
| b = void 0, | |
| y = void 0, | |
| S = void 0, | |
| T = void 0, | |
| E = !1, | |
| I = !1, | |
| v = {}, | |
| P = []; | |
| let w = !1; | |
| for (var L = u.length, M = 0; M < L; ++M) { | |
| var x = u[M]; | |
| if (c && !x.isVisible() && !x._relatesToCredentials) | |
| continue; | |
| var k = isRadioButtonElement(x), | |
| B = x.name; | |
| if (k && v[B]) | |
| continue; | |
| n.willStartCollectingMetadataForControl(); | |
| const o = !w; | |
| var U = this._collectControlMetadata(x, t, d, h, m, F, o); | |
| if (n.didFinishCollectingMetadataForControl(), w = !0, M + 1 < L && (U.ControlNextFieldUniqueID = this.controlUniqueID(u[M + 1])), l.FormControls.push(U), P.push(x), U.IsVisible || !l.IsVisible || x._relatesToCredentials) | |
| if (U.ControlIsActiveElement && (l.ContainsActiveElement = !0), B && k) | |
| v[B] = 1, U.ControlValue = "", U.RadioButtonInfo = this._collectRadioButtonInfo(e, B); | |
| else if (U.ControlIsTextField || U.SelectElementInfo) | |
| if (!I && U.ControlLooksLikeCreditCardSecurityCodeField && (I = !0), E || !U.ControlLooksLikeCreditCardCardholderField && !U.ControlLooksLikeCreditCardNumberField) { | |
| if (!(U.ControlLooksLikeDayField || U.ControlLooksLikeMonthField || U.ControlLooksLikeYearField || U.ControlLooksLikeCreditCardCompositeExpirationDateField)) { | |
| if (U.ControlLooksLikePasswordCredentialField) { | |
| if (U.ControlLooksLikeCreditCardSecurityCodeField || U.ControlLooksLikeCreditCardNumberField || U.ControlLooksLikeIgnoredDataTypeField) | |
| continue; | |
| x.isHiddenFromAccessibilityTree() ? (_.push(x), A.push(U)) : (p.push(x), C.push(U)) | |
| } | |
| if (this._isLabeledEmailField(x)) { | |
| if (++f > 2) { | |
| g = !1; | |
| continue | |
| } | |
| if (!(M + 1 < L && this._matchesConfirmEmailFieldLabelPattern(u[M + 1]))) | |
| continue; | |
| g = !0 | |
| } | |
| } | |
| } else | |
| E = !0, l.FirstCreditCardCardholderFieldOrCreditCardNumberFieldUniqueID = U.ControlUniqueID | |
| } | |
| !p.length && _.length && (p = _, C = A); | |
| var D, W, N = this._identifyFormTypeAndPasswordFieldIndicesFromAutocompleteAttributes(p, C), | |
| q = N[0], | |
| O = N[1], | |
| R = N[2], | |
| V = O || this._identifyPasswordFieldIndices(C, p); | |
| if (void 0 !== V.PasswordFieldIndex && (b = C[V.PasswordFieldIndex], l.PasswordElementUniqueID = b.ControlUniqueID, y = this._explicitMaxLength(p[V.PasswordFieldIndex])), void 0 !== V.ConfirmationFieldIndex && (S = C[V.ConfirmationFieldIndex], l.ConfirmPasswordElementUniqueID = S.ControlUniqueID, T = this._explicitMaxLength(p[V.ConfirmationFieldIndex])), void 0 !== V.OldPasswordFieldIndex) { | |
| var H = C[V.OldPasswordFieldIndex]; | |
| l.OldPasswordElementUniqueID = H.ControlUniqueID | |
| } | |
| if (b && (D = this._bestUsernameFieldCandidate(P, l, b)), D ? l.UsernameElementUniqueID = D.ControlUniqueID : W = this._findHiddenUsernameElement(e, l, P), q) | |
| l.AutoFillFormType = this._autoFillFormTypeFromCandidateFormTypes(e, q, q[0]); | |
| else if (1 === p.length && g) | |
| l.AutoFillFormType = this._autoFillFormTypeOfTypesUsingKeywordMatching(e, [ WBSAutoFillFormTypeNewAccount, WBSAutoFillFormTypeChangePassword ], WBSAutoFillFormTypeNewAccount); | |
| else if (l.UsernameElementUniqueID) | |
| switch (p.length) { | |
| case 0: | |
| break; | |
| case 1: | |
| if (I && l.UsernameElementUniqueID === l.FirstCreditCardCardholderFieldOrCreditCardNumberFieldUniqueID && C[0].ControlLooksLikeCreditCardNumberField) | |
| break; | |
| if (this._matchesConfirmPasswordFieldLabelPattern(p[0])) { | |
| let t = {}; | |
| this._isElementFollowedByForgotPasswordAffordance(x, i) && (t[WBSAutoFillFormTypeAutoFillableLogin] = 2), l.AutoFillFormType = this._autoFillFormTypeOfTypesUsingKeywordMatching(e, [ WBSAutoFillFormTypeNewAccount, WBSAutoFillFormTypeChangePassword ], R || WBSAutoFillFormTypeAutoFillableLogin, t) | |
| } else { | |
| let t = p[0], | |
| o = {}, | |
| r = 2 * this._numberOfForgotUserNameEmailOrPasswordAffordancesFollowingElement(t, i); | |
| r && (o[WBSAutoFillFormTypeAutoFillableLogin] = r), l.AutoFillFormType = this._autoFillFormTypeOfTypesUsingKeywordMatching(e, [ WBSAutoFillFormTypeNewAccount, WBSAutoFillFormTypeAutoFillableLogin ], R || WBSAutoFillFormTypeAutoFillableLogin, o) | |
| } | |
| break; | |
| case 2: | |
| y === T ? l.AutoFillFormType = this._autoFillFormTypeOfTypesUsingKeywordMatching(e, [ WBSAutoFillFormTypeNewAccount, WBSAutoFillFormTypeChangePassword ], WBSAutoFillFormTypeNewAccount) : T ? this._isPasswordConfirmPair(p[0], p[1]) ? l.AutoFillFormType = this._autoFillFormTypeOfTypesUsingKeywordMatching(e, [ WBSAutoFillFormTypeNewAccount, WBSAutoFillFormTypeChangePassword ], WBSAutoFillFormTypeNonAutoFillable) : l.AutoFillFormType = WBSAutoFillFormTypeNonAutoFillable | |
| : l.AutoFillFormType = this._autoFillFormTypeOfTypesUsingKeywordMatching(e, [ WBSAutoFillFormTypeNewAccount, WBSAutoFillFormTypeChangePassword ], WBSAutoFillFormTypeNonAutoFillable); | |
| break; | |
| case 3: | |
| y === T || !T || this._isPasswordConfirmPair(p[V.PasswordFieldIndex], p[V.ConfirmationFieldIndex]) ? l.AutoFillFormType = WBSAutoFillFormTypeChangePassword : l.AutoFillFormType = WBSAutoFillFormTypeNonAutoFillable; | |
| break; | |
| default: | |
| l.AutoFillFormType = WBSAutoFillFormTypeNonAutoFillable | |
| } | |
| else if (2 === p.length || 3 === p.length) | |
| if (y !== T && T) | |
| 2 === p.length ? this._isPasswordConfirmPair(p[0], p[1]) ? l.AutoFillFormType = this._autoFillFormTypeOfTypesUsingKeywordMatching(e, [ WBSAutoFillFormTypeNewAccount, WBSAutoFillFormTypeChangePassword ], WBSAutoFillFormTypeNonAutoFillable) : l.AutoFillFormType = WBSAutoFillFormTypeNonAutoFillable : this._isPasswordConfirmPair(p[V.PasswordFieldIndex], p[V.ConfirmationFieldIndex]) ? l.AutoFillFormType = WBSAutoFillFormTypeChangePassword | |
| : l.AutoFillFormType = WBSAutoFillFormTypeNonAutoFillable; | |
| else { | |
| let t = {}; | |
| this._isPasswordConfirmPair(p[V.PasswordFieldIndex], p[V.ConfirmationFieldIndex]) && (t[WBSAutoFillFormTypeChangePassword] = 2), l.AutoFillFormType = this._autoFillFormTypeOfTypesUsingKeywordMatching(e, [ WBSAutoFillFormTypeNewAccount, WBSAutoFillFormTypeChangePassword ], WBSAutoFillFormTypeChangePassword, t) | |
| } | |
| else if (1 === p.length) { | |
| var Y = p[0]; | |
| if (this._matchesConfirmPasswordFieldLabelPattern(Y, !0)) { | |
| let t = {}; | |
| this._isElementFollowedByForgotPasswordAffordance(x, i) && (t[WBSAutoFillFormTypeAutoFillableLogin] = 2), l.AutoFillFormType = this._autoFillFormTypeOfTypesUsingKeywordMatching(e, [ WBSAutoFillFormTypeAutoFillableLogin, WBSAutoFillFormTypeChangePassword ], WBSAutoFillFormTypeChangePassword, t) | |
| } else if (this._matchesPasswordFieldLabelPattern(Y)) | |
| if (this._isElementFollowedByForgotPasswordAffordance(Y, i)) | |
| l.AutoFillFormType = WBSAutoFillFormTypeAutoFillableLogin; | |
| else { | |
| var J = [ WBSAutoFillFormTypeNewAccount, WBSAutoFillFormTypeAutoFillableLogin, WBSAutoFillFormTypeChangePassword ]; | |
| l.AutoFillFormType = this._autoFillFormTypeOfTypesUsingKeywordMatching(e, J, WBSAutoFillFormTypeNonAutoFillable), l.AutoFillFormType === WBSAutoFillFormTypeNonAutoFillable && W && (l.AutoFillFormType = WBSAutoFillFormTypeNewAccount) | |
| } | |
| else | |
| l.AutoFillFormType = WBSAutoFillFormTypeNonAutoFillable | |
| } else | |
| 0 !== p.length && (l.AutoFillFormType = WBSAutoFillFormTypeNonAutoFillable); | |
| if (l.AutoFillFormType === WBSAutoFillFormTypeAutoFillableStandard) { | |
| var G = null, | |
| K = null, | |
| z = null, | |
| $ = 0, | |
| j = P.length; | |
| for (M = 0; M < j; ++M) { | |
| x = P[M]; | |
| var Z = l.FormControls[M], | |
| X = Z.IsVisible; | |
| if (X && Z.ControlIsTextField && $++, $ > 1) | |
| break; | |
| if (x.closest("footer")) | |
| continue; | |
| let t = {}; | |
| this._isElementFollowedByForgotUserNameOrEmailAffordance(x, i) && (t[WBSAutoFillFormTypeAutoFillableLogin] = 2); | |
| var Q = this._isLabeledEmailField(x); | |
| if (X && (Z.ControlClaimsToBeUsernameViaAutocompleteAttribute || Z.ControlIsLabeledUsernameField || Q || this._isLabeledLoginField(x)) && !this._matchesNonUsernameFieldLabelPattern(x) && !this._matchSearchFieldLabelPattern(x) && !x.readOnly && "INPUT" === x.tagName && !this._isLabeledSignUpField(x)) { | |
| let t = {}; | |
| this._isElementFollowedByForgotUserNameOrEmailAffordance(x, i) && (t[WBSAutoFillFormTypeAutoFillableLogin] = 2), this._autoFillFormTypeOfTypesUsingKeywordMatching(e, [ WBSAutoFillFormTypeNewAccount, WBSAutoFillFormTypeAutoFillableLogin ], Q ? WBSAutoFillFormTypeNewAccount : WBSAutoFillFormTypeAutoFillableLogin, t) === WBSAutoFillFormTypeAutoFillableLogin && (G = x, K = Z, z = WBSAutoFillFormTypeAutoFillableLogin) | |
| } | |
| const o = Z.AutocompleteTokens; | |
| if (o) { | |
| const r = o.includes("username"), | |
| n = o.includes("webauthn"); | |
| if (r && n) { | |
| G = x, K = Z, z = WBSAutoFillFormTypeAutoFillableLogin; | |
| continue | |
| } | |
| r && Q && (G = x, K = Z, z = this._autoFillFormTypeOfTypesUsingKeywordMatching(e, [ WBSAutoFillFormTypeNewAccount, WBSAutoFillFormTypeAutoFillableLogin ], WBSAutoFillFormTypeAutoFillableLogin, t)) | |
| } | |
| } | |
| 1 === $ && K && z && !controlAppearsToBePartOfPhotoTaggingInterface(G) && (l.AutoFillFormType = z, l.UsernameElementUniqueID = K.ControlUniqueID) | |
| } | |
| l.AutoFillFormType === WBSAutoFillFormTypeNewAccount && l.FirstCreditCardCardholderFieldOrCreditCardNumberFieldUniqueID === l.UsernameElementUniqueID && (l.UsernameElementUniqueID = void 0), !l.UsernameElementUniqueID && W && this._extractMetadataForHiddenUsernameElement(W, l, P), l.AutoFillFormType != WBSAutoFillFormTypeAutoFillableLogin && l.AutoFillFormType != WBSAutoFillFormTypeNewAccount && l.AutoFillFormType != WBSAutoFillFormTypeChangePassword && (l.UsernameElementUniqueID = void 0, l.OldPasswordElementUniqueID = void 0, l.PasswordElementUniqueID = void 0, l.ConfirmPasswordElementUniqueID = void 0), l.IsVisible || l.AutoFillFormType == WBSAutoFillFormTypeAutoFillableLogin || l.AutoFillFormType == WBSAutoFillFormTypeNewAccount || l.AutoFillFormType == WBSAutoFillFormTypeChangePassword || (l.AutoFillFormType = WBSAutoFillFormTypeNonAutoFillable), t !== WBSFormMetadataRequestPreFill && (l.TextSample = this._collectTextSample(e.formElement)), l.FormIsEligibleForAutomaticLogin = this._formIsEligibleForAutomaticLogin(l, e.backingElement); | |
| for (let e of l.FormControls) | |
| if (e.ControlLooksLikeOneTimeCodeField && this._oneTimeCodeIsEligibleForAutomaticLogin(e, l)) { | |
| e.OneTimeCodeIsEligibleForAutomaticLogin = !0; | |
| break | |
| } | |
| var ee = FormMetadataJSController.shouldIncludeNonEmptyFields; | |
| if (l.IsVisible) | |
| for (M = (j = P.length) - 1; M >= 0; --M) | |
| this._shouldIncludeControlMetadata(ee, l, P[M], l.FormControls[M]) || (t !== WBSFormMetadataRequestCollectMetadataFromDebugMenu ? (l.FormControls.splice(M, 1), P.splice(M, 1)) : l.FormControls[M].WOULD_NORMALLY_NOT_BE_SENT_TO_UI_PROCESS = !0); | |
| return this._removePlaceholderTextForFormMetadata(P, l), delete this._pageScanContext, t !== WBSFormMetadataRequestPreFill && globalThis.FormMetadataClassificationJS && globalThis.FormMetadataClassificationJS.classify(l), l | |
| }, | |
| _formIsEligibleForAutomaticLogin : function(e, t) { | |
| if (e.AutoFillFormType !== WBSAutoFillFormTypeAutoFillableLogin) | |
| return !1; | |
| let o = !1; | |
| for (const t of e.FormControls) { | |
| const r = t.ControlUniqueID; | |
| if (r === e.UsernameElementUniqueID || r === e.PasswordElementUniqueID) | |
| continue; | |
| if (t.ControlIsDisabled) | |
| continue; | |
| if (t.ControlIsReadOnly) | |
| continue; | |
| if (!t.IsVisible) | |
| continue; | |
| const n = this.formControlWithUniqueID(r); | |
| if (!n) | |
| continue; | |
| if (this._isTextArea(n)) | |
| return !1; | |
| if (this._isSelectElement(n)) | |
| return !1; | |
| if (this._isSubmitButton(n)) | |
| continue; | |
| if (this._looksLikeShowHidePasswordButton(n)) | |
| continue; | |
| if (!isInputElement(n)) | |
| continue; | |
| const i = n.type; | |
| if ("button" !== i && "reset" !== i && "submit" !== i && "image" !== i) { | |
| if (!this._isCheckboxInputElement(n)) | |
| return !1; | |
| if (o) | |
| return !1; | |
| o = !0 | |
| } | |
| } | |
| return !t || !elementAppearsToContinueCaptchaWidget(t) | |
| }, | |
| _oneTimeCodeIsEligibleForAutomaticLogin : function(e, t) { | |
| for (const e of t.FormControls) { | |
| if (e.ControlLooksLikeOneTimeCodeField) | |
| continue; | |
| if (e.ControlIsDisabled) | |
| continue; | |
| if (e.ControlIsReadOnly) | |
| continue; | |
| if (!e.IsVisible) | |
| continue; | |
| const t = this.formControlWithUniqueID(e.ControlUniqueID); | |
| if (!t) | |
| continue; | |
| if (this._isTextArea(t)) | |
| return !1; | |
| if (this._isSelectElement(t)) | |
| return !1; | |
| if (this._isSubmitButton(t)) | |
| continue; | |
| if (this._looksLikeShowHidePasswordButton(t)) | |
| continue; | |
| if (!isInputElement(t)) | |
| continue; | |
| const o = t.type; | |
| if ("button" !== o && "reset" !== o && "submit" !== o && "image" !== o) | |
| return !1 | |
| } | |
| return !0 | |
| }, | |
| _shouldIncludeControlMetadata : function(e, t, o, r) { | |
| if (o._relatesToCredentials) | |
| return !0; | |
| if (r.IsVisible) { | |
| if (formControlHasBeenClassifiedInAnInterestingWay(r)) | |
| return !0; | |
| if (e && r.ControlValue) | |
| return !0 | |
| } | |
| return !(!t.UsernameElementUniqueID || r.ControlUniqueID !== t.UsernameElementUniqueID) | |
| }, | |
| _isElementAHiddenUsername : function(e) { | |
| const t = /user|email/i; | |
| return "hidden" === e.type && (!(!t.test(e.getAttribute("id")) && !t.test(e.getAttribute("name"))) && !!isValidUsernameOrEmail(e.value)) | |
| }, | |
| _findHiddenUsernameElement : function(e) { | |
| var t = e.formElement; | |
| if (!(t instanceof HTMLElement)) | |
| return; | |
| let o = queryAllBySelector(t, "input"), | |
| r = o.length; | |
| for (let e = 0; e < r; ++e) { | |
| let t = o[e]; | |
| if (this._isElementAHiddenUsername(t)) | |
| return t | |
| } | |
| return null | |
| }, | |
| _extractMetadataForHiddenUsernameElement : function(e, t, o) { | |
| var r = { | |
| ControlTagName : this._getTagName(e), | |
| ControlFieldName : this._getNameOrId(e), | |
| ControlUniqueID : this.controlUniqueID(e), | |
| ControlIsReadOnly : !0, | |
| ControlValue : e.value | |
| }; | |
| t.UsernameElementUniqueID = r.ControlUniqueID, t.FormControls.push(r), o.push(e) | |
| }, | |
| _usernameFieldForPasswordField : function(e) { | |
| let t = FormMetadataJS._cachedMetadataForLogicalForm(this._logicalFormsCache.logicalFormForControl(e)); | |
| return t && t.UsernameElementUniqueID ? FormMetadataJS.formControlWithUniqueID(t.UsernameElementUniqueID) : null | |
| }, | |
| _cachedMetadataForLogicalForm : function(e) { | |
| var t = e.metadata, | |
| o = t?.FormControls, | |
| r = o?.length ?? 0; | |
| if (!r) | |
| return null; | |
| const n = innermostActiveElement(); | |
| for (var i = 0; i < r; ++i) { | |
| var l = o[i], | |
| a = this.formControlWithUniqueID(l.ControlUniqueID); | |
| a && (l.ControlIsActiveElement = a === n, l.ControlValue = a.value, l.ControlIsAutoFilledTextField = this._isAutoFilledTextField(a)) | |
| } | |
| return t.UsesGeneratedPassword = this._usesGeneratedPassword(e), t.Annotations = e.annotations, t | |
| }, | |
| _markFormIsBestForPageLevelAutoFill : function() { | |
| function e(e) | |
| { | |
| switch (e) { | |
| case WBSAutoFillFormTypeAutoFillableLogin: | |
| return 30; | |
| case WBSAutoFillFormTypeNewAccount: | |
| case WBSAutoFillFormTypeChangePassword: | |
| return 20; | |
| case WBSAutoFillFormTypeAutoFillableStandard: | |
| return 10; | |
| case WBSAutoFillFormTypeUndetermined: | |
| case WBSAutoFillFormTypeNonAutoFillable: | |
| return 0 | |
| } | |
| return -100 | |
| } | |
| function t(e) | |
| { | |
| return e ? 50 : 0 | |
| } | |
| let o = this._logicalFormWithHighestScoreIfGreaterThanZero((function(o) { | |
| var r = o.PasswordElementUniqueID ? 0 : -1; | |
| return e(o.AutoFillFormType) + t(o.IsVisible) + r | |
| })); | |
| null !== o && (o.metadata.FormIsBestForPageLevelAutoFill = !0) | |
| }, | |
| _markFormIsBestForStreamlinedLogin : function() { | |
| let e = this._logicalFormWithHighestScoreIfGreaterThanZero((function(e, t) { | |
| if (!e.IsVisible) | |
| return 0; | |
| let o = t.getBoundingClientRect(); | |
| if (!rectIsWithinDocumentViewport(o)) | |
| return 0; | |
| if (o.bottom + window.scrollY < 80) { | |
| let e = !(location.hash || location.pathname && "/" !== location.pathname || location.search), | |
| t = o.width / o.height; | |
| if (!e && t > 4) | |
| return 0 | |
| } | |
| if (t.closest("footer")) | |
| return 0; | |
| let r = e.AutoFillFormType === WBSAutoFillFormTypeAutoFillableLogin, | |
| n = 0, | |
| i = e.FormControls, | |
| l = i.length; | |
| for (var a = 0; a < l; ++a) { | |
| let t = i[a]; | |
| if (r) { | |
| t.ControlIsAutofocusedTextField && (n += 1); | |
| let o = t.ControlUniqueID; | |
| if (o === e.UsernameElementUniqueID || o === e.PasswordElementUniqueID) { | |
| n += 10; | |
| continue | |
| } | |
| } | |
| t.OneTimeCodeIsEligibleForAutomaticLogin && (n += 5) | |
| } | |
| return n | |
| })); | |
| null !== e && (e.metadata.FormIsBestForStreamlinedLogin = !0) | |
| }, | |
| _logicalFormWithHighestScoreIfGreaterThanZero : function(e) { | |
| let t = null, | |
| o = null; | |
| for (let n of this._logicalFormsCache.allForms()) { | |
| var r = e(n.metadata, n.backingElement); | |
| (null === t || r > t) && (o = n, t = r) | |
| } | |
| return t > 0 ? o : null | |
| }, | |
| isAnyFormAnnotated : function() { | |
| return this._logicalFormsCache.allForms().some((e => e.isAnnotated)) | |
| }, | |
| clearAnnotationsForFormWithID : function(e) { | |
| let t = this._logicalFormsCache.logicalFormWithUniqueID(e); | |
| t && t.clearAnnotations() | |
| }, | |
| annotateFormWithID : function(e, t) { | |
| let o = this._logicalFormsCache.logicalFormWithUniqueID(e); | |
| o && o.annotate(t) | |
| }, | |
| _collectMetadata : function(e) { | |
| const t = 100, | |
| o = 10; | |
| var r = this._logicalFormsInPage(t, o); | |
| this._logicalFormsCache.clearCacheAndAdd(r); | |
| for (var n = r.length, i = 0; i < n; ++i) { | |
| e === WBSFormMetadataRequestTesting && "function" == typeof willCollectFormMetadata && willCollectFormMetadata(); | |
| let t = this._collectFormMetadata(r[i], e); | |
| e === WBSFormMetadataRequestTesting && "function" == typeof evaluateCustomJavaScript && (t.ResultFromEvaluatingCustomJavaScript = evaluateCustomJavaScript(r[i], t)), r[i].metadata = t | |
| } | |
| this._markFormIsBestForPageLevelAutoFill(), e !== WBSFormMetadataRequestNormal && this._markFormIsBestForStreamlinedLogin() | |
| }, | |
| _collectAndCacheFormMetadata : function(e, t) { | |
| let o = this._collectFormMetadata(e, t), | |
| r = this._logicalFormsCache.logicalFormWithUniqueID(e.formUniqueID); | |
| return r ? r.metadata = o : (e.metadata = o, this._logicalFormsCache.addOrUpdate(e)), o | |
| }, | |
| _metadataForFormWithID : function(e) { | |
| return this._logicalFormsCache.logicalFormWithUniqueID(e)?.metadata | |
| }, | |
| _recollectMetadataForFormWithID : function(e) { | |
| const t = this._logicalFormsCache.logicalFormWithUniqueID(e); | |
| return t ? this._collectAndCacheFormMetadata(t, WBSFormMetadataRequestNormal) : null | |
| }, | |
| _fillControlWithGeneratedPassword : function(e, t) { | |
| var o = this._elementsWithGeneratedPasswords.indexOf(e); | |
| -1 === o && (this._elementsWithGeneratedPasswords.push(e), o = this._elementsWithGeneratedPasswords.length - 1), this._generatedPasswords[o] = t, this._autoFillControlWithValueWithSingleValueUpdate(e, t, ShouldFocus.Yes, ShouldBlur.Yes, ShouldSetAutoFilled.Yes) | |
| }, | |
| fillFormWithPassword : function(e, t, o) { | |
| var r = this._metadataForFormWithID(e); | |
| if (null === r) | |
| return null; | |
| const n = r.PasswordElementUniqueID, | |
| i = n ? this.formControlWithUniqueID(n) : void 0, | |
| l = o ? this.formControlWithUniqueID(o) : void 0; | |
| var a = i || l; | |
| const s = n || o; | |
| if (!a) | |
| return null; | |
| this._fillControlWithGeneratedPassword(a, t); | |
| let u = r.ConfirmPasswordElementUniqueID; | |
| u || r.AutoFillFormType !== WBSAutoFillFormTypeChangePassword && r.AutoFillFormType !== WBSAutoFillFormTypeNewAccount || (u = (r = this._recollectMetadataForFormWithID(e) || r).ConfirmPasswordElementUniqueID); | |
| let c = u ? this.formControlWithUniqueID(u) : null; | |
| return c ? (this._fillControlWithGeneratedPassword(c, t), [ s, u ]) : [ s ] | |
| }, | |
| fillFieldWithGeneratedPassword : function(e, t) { | |
| var o = this.formControlWithUniqueID(e); | |
| o && this._isTextField(o) && this._fillControlWithGeneratedPassword(o, t) | |
| }, | |
| clearField : function(e) { | |
| var t = this.formControlWithUniqueID(e); | |
| this._clearFormField(t) | |
| }, | |
| _clearFormField : function(e, t) { | |
| if (e) | |
| if (this._isSelectElement(e)) | |
| e.selectedIndex = 0; | |
| else if (isDateTimeInputElement(e)) | |
| e.value = ""; | |
| else if (isRadioButtonElement(e)) { | |
| let t = this._logicalFormsCache.logicalFormForControl(e).radioButtonsWithName(e.name), | |
| o = t.length; | |
| for (let e = 0; e < o; ++e) | |
| t[e].checked = !1 | |
| } else if (this._isTextField(e) && e.value.length) { | |
| var o = e.matches(":focus"); | |
| o || e.dispatchEvent(new Event("focus")), e.dispatchEvent(eventThatBubbles("keydown")), e.value = "", e.dispatchEvent(eventThatBubbles("input")), e.dispatchEvent(eventThatBubbles("keyup")), e.dispatchEvent(eventThatBubbles("change")), o || t === ShouldBlur.No || e.dispatchEvent(new Event("blur")) | |
| } | |
| }, | |
| focusFormForStreamlinedLogin : function(e) { | |
| function t(e) | |
| { | |
| for (const t of e.FormControls) { | |
| const o = t.ControlUniqueID; | |
| if (o === e.UsernameElementUniqueID || o === e.PasswordElementUniqueID || t.ControlLooksLikeOneTimeCodeField) | |
| return o | |
| } | |
| } | |
| var o = this._metadataForFormWithID(e); | |
| if (null !== o) { | |
| var r = t(o); | |
| if (r) { | |
| var n = this.formControlWithUniqueID(r); | |
| rectIsWithinDocumentViewport(n.getBoundingClientRect()) && n.focus() | |
| } | |
| } | |
| }, | |
| formsAndMetadata : function(e) { | |
| visibilityCacheGeneration++, this._collectMetadata(e); | |
| let t = [], | |
| o = []; | |
| for (let e of this._logicalFormsCache.allForms()) | |
| t.push(e.formElement), o.push(e.metadata); | |
| return [ t, o ] | |
| }, | |
| formControlWithUniqueID : function(e) { | |
| let t = this._controlUniqueIDToWeakControlMap.get(e)?.deref(); | |
| return t | |
| }, | |
| formElementWithFormID : function(e) { | |
| return this._logicalFormsCache.logicalFormWithUniqueID(e)?.formElement | |
| }, | |
| selectIfTextField : function(e) { | |
| this._isTextField(e) && e.select() | |
| }, | |
| _getOrCreateCachedMetadataForLogicalForm : function(e, t) { | |
| var o = this._cachedMetadataForLogicalForm(e); | |
| return !o || null != t && o.RequestType === WBSFormMetadataRequestPreFill && t !== WBSFormMetadataRequestPreFill ? this._collectAndCacheFormMetadata(e, t) : o | |
| }, | |
| _getOrCreateLogicalFormForTextFieldOrSelectElement : function(e) { | |
| let t = this._logicalFormsCache.logicalFormForControl(e); | |
| if (t) | |
| for (var o = t.metadata, r = o?.FormControls, n = r?.length ?? 0, i = e._controlUniqueID, l = 0; l < n; ++l) | |
| if (r[l].ControlUniqueID === i) | |
| return t; | |
| var a = this._logicalFormsInPage(), | |
| s = a.length; | |
| for (l = 0; l < s; ++l) { | |
| var u = a[l]; | |
| if (u.containsControl(e)) | |
| return this._logicalFormsCache.addOrUpdate(u), u.metadata = this._collectFormMetadata(u, WBSFormMetadataRequestNormal), u | |
| } | |
| return null | |
| }, | |
| _cachedMetadataForFormWithTextFieldOrSelectElement : function(e, t) { | |
| if (!this._isTextField(e) && !this._isSelectElement(e)) | |
| return null; | |
| var o = this._getOrCreateLogicalFormForTextFieldOrSelectElement(e); | |
| return o ? this._getOrCreateCachedMetadataForLogicalForm(o, t) : null | |
| }, | |
| _isAnyPasswordElementUniqueID : function(e, t) { | |
| return e.PasswordElementUniqueID === t || e.ConfirmPasswordElementUniqueID === t || e.OldPasswordElementUniqueID === t | |
| }, | |
| _isCurrentPasswordElementUniqueID : function(e, t) { | |
| switch (e.AutoFillFormType) { | |
| case WBSAutoFillFormTypeNewAccount: | |
| case WBSAutoFillFormTypeChangePassword: | |
| return e.OldPasswordElementUniqueID === t; | |
| default: | |
| return e.PasswordElementUniqueID === t | |
| } | |
| }, | |
| _isNewPasswordElementUniqueID : function(e, t) { | |
| switch (e.AutoFillFormType) { | |
| case WBSAutoFillFormTypeNewAccount: | |
| case WBSAutoFillFormTypeChangePassword: | |
| return e.PasswordElementUniqueID === t || e.ConfirmPasswordElementUniqueID === t; | |
| default: | |
| return !1 | |
| } | |
| }, | |
| _updateAnnotationsForField : function(e) { | |
| var t = this._getOrCreateLogicalFormForTextFieldOrSelectElement(e); | |
| if (t) { | |
| var o = this._getOrCreateCachedMetadataForLogicalForm(t); | |
| if (o) { | |
| var r = e._controlUniqueID; | |
| this._isCurrentPasswordElementUniqueID(o, r) ? t.annotate({ | |
| CurrentPassword : e.value | |
| }) | |
| : this._isNewPasswordElementUniqueID(o, r) ? t.annotate({ | |
| NewPassword : e.value | |
| }) | |
| : o.UsernameElementUniqueID === r && t.annotate({ | |
| Username : e.value | |
| }), | |
| isCredentialElementUniqueID(o, r) && (e._relatesToCredentials = "" !== e.value) | |
| } | |
| } | |
| }, | |
| textFieldOrSelectElementMetadata : function(e, t, o) { | |
| visibilityCacheGeneration++, this._logicalFormsCache.cleanupCache(); | |
| var r = [ null, null ], | |
| n = this._cachedMetadataForFormWithTextFieldOrSelectElement(e, t); | |
| if (!n) | |
| return r; | |
| this._pageScanContext = { | |
| backwardScanCache : new WeakMap, | |
| forwardScanCache : new WeakMap | |
| }; | |
| let i = this._logicalFormsCache.logicalFormWithUniqueID(n.FormID), | |
| l = formActionAsAnchorElement(i.formElement), | |
| [ a, s, u, c ] = this._trailingArgumentsForCollectControlMetadataFunction(i, t, l); | |
| const d = !0; | |
| var h = this._collectControlMetadata(e, WBSFormMetadataRequestNormal, a, s, u, c, d); | |
| if (delete this._pageScanContext, h.ControlLooksLikeOneTimeCodeField && this._oneTimeCodeIsEligibleForAutomaticLogin(h, n) && (h.OneTimeCodeIsEligibleForAutomaticLogin = !0), h.SelectionStart = e.selectionStart, h.SelectionLength = e.selectionEnd - e.selectionStart, t === WBSFormMetadataRequestTextChange && (!n.UsernameElementUniqueID && this._isAnyPasswordElementUniqueID(n, h.ControlUniqueID) && i.isAnnotated && i.annotate({ | |
| Username : null | |
| }), | |
| this._updateAnnotationsForField(e)), | |
| n.RequestType !== WBSFormMetadataRequestPreFill) | |
| for (let e of n.FormControls) | |
| if (h.ControlUniqueID === e.ControlUniqueID) { | |
| h.ControlClassification = e.ControlClassification, h.ControlClassificationHints = e.ControlClassificationHints, h.ControlOrderedParts = e.ControlOrderedParts, h.ControlContinuationID = e.ControlContinuationID, h.ControlContinuationIndex = e.ControlContinuationIndex; | |
| break | |
| } | |
| if (o) { | |
| for (const e of n.FormControls) | |
| e.ControlUniqueID == h.ControlUniqueID && (e.ControlValue = null); | |
| const e = JSON.stringify(n); | |
| this._cachedFormMetadata == e ? n = null : this._cachedFormMetadata = e | |
| } | |
| return r[0] = h, r[1] = n, r | |
| }, | |
| clearTextFieldOrSelectElementMetadataCache : function() { | |
| this._cachedFormMetadata = null | |
| }, | |
| disableSpellCheckInFieldIfNeeded : function(e) { | |
| if (e) { | |
| var t = this.formControlWithUniqueID(e); | |
| t && this._isAutoFillableTextField(t) && FormMetadataJSController.setInputElementSpellCheckEnabled(t, !1) | |
| } | |
| }, | |
| selectionRangeInField : function(e) { | |
| var t = this.formControlWithUniqueID(e); | |
| return t && this._isTextField(t) ? [ t.selectionStart, t.selectionEnd - t.selectionStart ] : null | |
| }, | |
| setFormFieldSelection : function(e, t, o) { | |
| var r = this.formControlWithUniqueID(e); | |
| r && this._isTextField(r) && (r.selectionStart = t, r.selectionEnd = t + o) | |
| }, | |
| replaceFormFieldRangeAndSelectTail : function(e, t, o, r, n) { | |
| var i = this.formControlWithUniqueID(e); | |
| if (i && this._isTextField(i)) { | |
| var l = i.value, | |
| a = l.substr(0, t) + r + l.substr(t + o); | |
| i.value = a, i.selectionStart = n, i.selectionEnd = a.length, i.dispatchEvent(eventThatBubbles("input")), i.dispatchEvent(eventThatBubbles("change")) | |
| } | |
| }, | |
| _collectVisibleNonEmptyTextFieldsAndTextAreasInForm : function(e, t, o) { | |
| visibilityCacheGeneration++; | |
| for (var r = e.elements, n = r.length, i = 0; i < n; ++i) { | |
| var l = r[i]; | |
| l.isVisible() && (null != l.value && l.value.length && (this._isTextField(l) ? t.push(l) : this._isTextArea(l) && o.push(l))) | |
| } | |
| }, | |
| visibleNonEmptyFormTextControls : function() { | |
| var e = [], | |
| t = []; | |
| let o = queryAllBySelector(document, "form"); | |
| for (let r = 0; r < o.length; ++r) | |
| this._collectVisibleNonEmptyTextFieldsAndTextAreasInForm(o[r], e, t); | |
| return [ e, t ] | |
| }, | |
| visibleNonEmptyFormTextControlsInForm : function(e) { | |
| var t = [], | |
| o = []; | |
| return this._collectVisibleNonEmptyTextFieldsAndTextAreasInForm(e, t, o), [ t, o ] | |
| }, | |
| _autoFillRadioButton : function(e, t, o) { | |
| var r = this._logicalFormsCache.logicalFormForControl(e), | |
| n = r?.radioButtonsWithName(e.name) ?? []; | |
| for (let e of n) | |
| if (e.value === t) | |
| return e.dispatchEvent(eventThatBubbles("click")), e.checked = !0, void FormMetadataJSController.setInputElementAutofilled(e, o) | |
| }, | |
| _autoFillControlWithValueWithSingleValueUpdate : function(e, t, o, r, n, i, l) { | |
| o === ShouldFocus.Yes && e.dispatchEvent(new Event("focus")), e.dispatchEvent(eventThatBubbles("keydown")), e.value = t, this._updateAnnotationsForField(e), l || e.dispatchEvent(eventThatBubbles("input")), e.dispatchEvent(eventThatBubbles("keyup")), l || e.dispatchEvent(eventThatBubbles("change")), r === ShouldBlur.Yes && e.dispatchEvent(new Event("blur")), i === ShouldObscure.Yes ? FormMetadataJSController.setInputElementAutofilledAndObscured(e, t.length && n === ShouldSetAutoFilled.Yes) : FormMetadataJSController.setInputElementAutofilled(e, t.length && n === ShouldSetAutoFilled.Yes) | |
| }, | |
| _autoFillControlWithValueCharacterByCharacter : function(e, t, o, r, n, i, l) { | |
| let a = t.split(""), | |
| s = a.length, | |
| u = Date.now(), | |
| c = !e; | |
| const d = 100, | |
| h = () => { | |
| this._autoFillControlWithValueWithSingleValueUpdate(e, t, ShouldFocus.Yes, ShouldBlur.Yes, o, r), i?.() | |
| }; | |
| let m = F => { | |
| try { | |
| if (F >= s) | |
| return void i?.(); | |
| c && (e = innermostActiveElement()); | |
| let f = e.value, | |
| g = a[F], | |
| p = f.slice(-1); | |
| if (p === g && F && !t.slice(F - 1).startsWith(p + g)) | |
| return void setTimeout(m, 0, F + 1); | |
| let C = 0 === F ? ShouldFocus.Yes : ShouldFocus.No, | |
| _ = F === s - 1, | |
| A = _ ? ShouldBlur.Yes : ShouldBlur.No, | |
| b = _ ? o : ShouldSetAutoFilled.No, | |
| y = _ ? r : ShouldObscure.No, | |
| S = f + g, | |
| T = !_; | |
| if (l && (T = !1), this._autoFillControlWithValueWithSingleValueUpdate(e, S, C, A, b, y, T), !c && !this._controlContainsAllCharactersFromFilling(e.value, t.substring(0, F + 1))) | |
| return void h(); | |
| const E = Date.now() - u; | |
| if (u = Date.now(), E > d && n === ShouldAbandonCharacterByCharacterEntryIfTooSlow.Yes) | |
| return void h(); | |
| setTimeout(m, 0, F + 1) | |
| } catch (e) { | |
| } | |
| }; | |
| m(0) | |
| }, | |
| _controlContainsAllCharactersFromFilling : function(e, t) { | |
| if (e.length < t.length) | |
| return !1; | |
| var o = t; | |
| for (let r = 0; r < t.length; r++) { | |
| -1 !== e.indexOf(t[r]) && (e = e.replace(t[r], ""), o = o.replace(t[r], "")) | |
| } | |
| return !o.length | |
| }, | |
| _autoFillControlWithValueRecursively : function(e, t, o, r, n) { | |
| if (isRadioButtonElement(e)) | |
| return this._autoFillRadioButton(e, t, o === ShouldSetAutoFilled.Yes), void (n && n()); | |
| if (this._isSelectElement(e)) | |
| return this._autoFillSelectWithOptionIndex(e, t, o === ShouldSetAutoFilled.Yes), void (n && n()); | |
| let i = this._logicalFormsCache.logicalFormForControl(e), | |
| l = FormMetadataJS._cachedMetadataForLogicalForm(i); | |
| if (!this._isTextField(e) || l && isCredentialElementUniqueID(l, e._controlUniqueID)) | |
| return this._autoFillControlWithValueWithSingleValueUpdate(e, t, ShouldFocus.Yes, ShouldBlur.Yes, o, r), void (n && n()); | |
| this._clearFormField(e, ShouldBlur.No); | |
| let a = () => { | |
| this._controlContainsAllCharactersFromFilling(e.value, t) || this._autoFillControlWithValueWithSingleValueUpdate(e, t, ShouldFocus.Yes, ShouldBlur.Yes, o, r), n && n() | |
| }; | |
| this._autoFillControlWithValueCharacterByCharacter(e, t, o, r, ShouldAbandonCharacterByCharacterEntryIfTooSlow.Yes, a) | |
| }, | |
| _autoFillSelectWithOptionIndex : function(e, t, o) { | |
| e.dispatchEvent(eventThatBubbles("mousedown")), e.dispatchEvent(new Event("focus")), e.selectedIndex !== t && (e.selectedIndex = t, e.dispatchEvent(eventThatBubbles("input")), e.dispatchEvent(eventThatBubbles("change"))), e.dispatchEvent(eventThatBubbles("mouseup")), e.dispatchEvent(eventThatBubbles("click")), e.dispatchEvent(new Event("blur")), FormMetadataJSController.setInputElementAutofilled(e, o) | |
| }, | |
| autoFillOneTimeCodeFieldsWithValue : function(e, t) { | |
| let o = innermostActiveElement(); | |
| if (!this._isAutoFillableTextField(o)) | |
| return; | |
| this._clearFormField(o); | |
| let r = () => { | |
| FormMetadataJSController.finishedAutoFillingOneTimeCode(e, t) | |
| }, n = !0; | |
| this._autoFillControlWithValueCharacterByCharacter(null, e, ShouldSetAutoFilled.Yes, ShouldObscure.No, ShouldAbandonCharacterByCharacterEntryIfTooSlow.No, r, n) | |
| }, | |
| _removeGeneratedPasswordForElement : function(e) { | |
| let t = this._elementsWithGeneratedPasswords.indexOf(e); | |
| -1 !== t && (this._elementsWithGeneratedPasswords.splice(t, 1), this._generatedPasswords.splice(t, 1)) | |
| }, | |
| _shouldSelectElementAfterFillingForm : function(e) { | |
| if (!/(^|\.)etrade\.com/.test(document.location.hostname)) | |
| return !0; | |
| var t = this._cachedMetadataForLogicalForm(e); | |
| return !t || t.AutoFillFormType !== WBSAutoFillFormTypeAutoFillableLogin | |
| }, | |
| autoFillControlsByID : function(e, t, o, r, n, i) { | |
| let l = arguments[arguments.length - 1], | |
| a = o ? ShouldSetAutoFilled.Yes : ShouldSetAutoFilled.No, | |
| s = r; | |
| if (s) { | |
| let e = s.getAttribute("onfocus"); | |
| e && e.length && /this\.value/.test(e) && (s = null) | |
| } else | |
| s = innermostActiveElement(); | |
| var u = null; | |
| for (let t in e) { | |
| let e = this.formControlWithUniqueID(t)._logicalFormUniqueIDs; | |
| for (let t of e) | |
| u ||= this._logicalFormsCache.logicalFormWithUniqueID(t); | |
| if (u) | |
| break | |
| } | |
| var c = function() { | |
| n ? innermostActiveElement().blur() : s && this._shouldSelectElementAfterFillingForm(u) && this.selectIfTextField(s), u?.backingElement && elementAppearsToContinueCaptchaWidget(u.backingElement) && (l = !1), FormMetadataJSController.finishedAutoFillingControlsInForm(this._getOrCreateCachedMetadataForLogicalForm(u), l) | |
| }.bind(this); | |
| if (t) { | |
| var d = []; | |
| for (var h in e) | |
| e.hasOwnProperty(h) && d.push([ this.formControlWithUniqueID(h), e[h] ]); | |
| this._synchronouslyAutoFillControls(d, a, c) | |
| } else | |
| this._asynchronouslyAutoFillControls(e, u, a, i, c) | |
| }, | |
| _synchronouslyAutoFillControls : function(e, t, o) { | |
| for (var r = e.length, n = 0; n < r; ++n) { | |
| var i = e[n][0], | |
| l = e[n][1]; | |
| this._autoFillControlWithValueRecursively(i, l, t) | |
| } | |
| o() | |
| }, | |
| _asynchronouslyAutoFillControls : function(e, t, o, r, n) { | |
| var i = t.elements, | |
| l = i.length, | |
| a = function(t) { | |
| if (t >= l) | |
| return void n(); | |
| var s = i[t], | |
| u = e[s._controlUniqueID]; | |
| let c = () => { | |
| a(t + 1) | |
| }; | |
| if (void 0 !== u) { | |
| let e = r.some((e => s._controlUniqueID.includes(e))) ? ShouldObscure.Yes : ShouldObscure.No; | |
| this._autoFillControlWithValueRecursively(s, u, o, e, c) | |
| } else | |
| c() | |
| }.bind(this); | |
| a(0) | |
| }, | |
| _isInputAllowedInSearchForm : function(e, t) { | |
| var o = this._getTagName(e).toLowerCase(); | |
| if ("button" === o || "fieldset" === o) | |
| return !0; | |
| if ("select" === o) | |
| return !t || isSelectInDefaultState(e); | |
| if ("input" !== o && !this._textAreaElementLookLikeItIsPartOfASearchForm(e)) | |
| return !1; | |
| var r = e.type; | |
| return "radio" === r || "checkbox" === r ? !t || isCheckboxOrRadioButtonInDefaultState(e) : "hidden" === r || "reset" === r || "submit" === r || "button" === r || "image" === r || this._isTextField(e) && !this._isSecureTextField(e) | |
| }, | |
| _isSearchForm : function(e, t) { | |
| if ("get" !== e.method) | |
| return !1; | |
| for (var o = e.elements, r = o.length, n = 0; n < r; ++n) | |
| if (!this._isInputAllowedInSearchForm(o[n], t)) | |
| return !1; | |
| return !0 | |
| }, | |
| _textAreaElementLookLikeItIsPartOfASearchForm : function(e) { | |
| return !!this._isTextArea(e) && ("search" === e.getAttribute("type") || ("search" === e.inputMode || "search" === e.getAttribute("enterkeyhint"))) | |
| }, | |
| _shouldInputBeIncludedInSearchURLQuery : function(e) { | |
| if (e.disabled) | |
| return !1; | |
| if (!e.name.length) | |
| return !1; | |
| if (!e.value.length) | |
| return !1; | |
| if (this._isSelectElement(e)) | |
| return !0; | |
| var t = this._getTagName(e).toLowerCase(), | |
| o = e.type; | |
| return "button" === t ? "submit" === o : "input" === t && ("submit" === o || ("checkbox" === o || "radio" === o ? e.checked : "hidden" === o || this._isTextField(e))) | |
| }, | |
| _isSubmitButton : function(e) { | |
| return (e instanceof HTMLButtonElement || e instanceof HTMLInputElement) && (e.type && "submit" === e.type) | |
| }, | |
| _isCustomFormButton : function(e) { | |
| return "button" === e.type && (e instanceof HTMLButtonElement || e instanceof HTMLInputElement) | |
| }, | |
| _isCheckboxInputElement : function(e) { | |
| return "checkbox" === e.type && e instanceof HTMLInputElement | |
| }, | |
| _setQueryString : function(e, t) { | |
| var o = document.createElement("a"); | |
| return o.href = e, o.search = t, o.href | |
| }, | |
| searchTextFieldFormSubmissionURLString : function(e, t) { | |
| if (visibilityCacheGeneration++, !this._isTextField(e) || this._isSecureTextField(e) || !e.isVisible()) | |
| return null; | |
| var o = e.form; | |
| if (!o) | |
| return null; | |
| var r = o.getAttribute("action"); | |
| if (!r || !r.length) | |
| return null; | |
| if (!/^https?:/i.test(o.action)) | |
| return null; | |
| if (!this._isSearchForm(o, t)) | |
| return null; | |
| for (var n = null, i = "", l = o.elements, a = l.length, s = 0; s < a; ++s) { | |
| var u = l[s]; | |
| if ((u === e || this._shouldInputBeIncludedInSearchURLQuery(u)) && (!this._isSubmitButton(u) || (n || (n = u), u === n))) { | |
| i.length && (i += "&"); | |
| var c = u === e ? "{searchTerms}" : urlEncode(u.value); | |
| i += urlEncode(u.name) + "=" + c | |
| } | |
| } | |
| return this._setQueryString(o.action, i) | |
| } | |
| }; | |
| var FormMetadataJS = new FormMetadata; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <title>Grant Permissions for Web Extension?</title> | |
| <style> | |
| @media (prefers-color-scheme: dark) { | |
| :root { | |
| color-scheme: dark !important; | |
| } | |
| body { | |
| background: rgb(30, 30, 30) !important; | |
| --font-color: hsl(0, 0%, 85%) !important; | |
| --title-color: rgb(224, 225, 225) !important; | |
| } | |
| .alert-container { | |
| background-color: rgb(56, 57, 59) !important; | |
| box-shadow: 0 6px 12px rgba(0, 0, 0, .24) !important; | |
| } | |
| } | |
| body { | |
| --font-color: #434343; | |
| --horizontal-padding: 32px; | |
| --border-radius: 6px; | |
| --title-color: #444; | |
| } | |
| * { | |
| padding: 0; | |
| margin: 0; | |
| font-family: -apple-system-font; | |
| } | |
| :root { | |
| color-scheme: light; | |
| } | |
| html, body { | |
| height: 100%; | |
| width: 100%; | |
| } | |
| body { | |
| font-size: 13px; | |
| background: linear-gradient(30deg, #dfdfdf 0%, #fafafb 100%); | |
| background-repeat: no-repeat; | |
| background-attachment: fixed; | |
| cursor: default; | |
| -webkit-user-select: none; | |
| overflow: hidden; | |
| } | |
| .vertical-flex-container { | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| flex-direction: column; | |
| flex-wrap: nowrap; | |
| align-content: stretch; | |
| padding-top: 156px; | |
| } | |
| @media (max-height: 30rem) { | |
| .vertical-flex-container { | |
| padding-top: min(calc(60vh - 150px), 156px); | |
| } | |
| } | |
| .alert-container { | |
| background-color: white; | |
| min-width: 320px; | |
| max-width: 672px; | |
| position: relative; | |
| margin: 0 auto; | |
| padding-top: 24px; | |
| border-radius: var(--border-radius); | |
| box-shadow: 0px 6px 10px rgba(0, 0, 0, 0.14); | |
| } | |
| .alert-container h1 { | |
| overflow: hidden; | |
| color: var(--title-color); | |
| padding-top: 3px; | |
| } | |
| .alert-body { | |
| display: block; | |
| margin: 21px 0 0 0; | |
| padding-left: var(--horizontal-padding); | |
| padding-right: var(--horizontal-padding); | |
| padding-bottom: 28px; | |
| color: var(--font-color); | |
| } | |
| .alert-body p:first-of-type { | |
| margin-bottom: 15px; | |
| margin-top: 20px; | |
| } | |
| .alert-body p:last-of-type { | |
| margin-bottom: 0; | |
| } | |
| .button-bar { | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| flex-direction: row; | |
| flex-wrap: wrap; | |
| align-content: stretch; | |
| margin-top: 1.3em; | |
| } | |
| .button-bar button { | |
| font-size: 13px; | |
| line-height: 21px; | |
| min-width: 90px; | |
| margin: 4px; | |
| vertical-align: bottom; | |
| padding: 0 12px; | |
| color: var(--font-color); | |
| cursor: pointer; | |
| } | |
| .hidden { | |
| display: none; | |
| } | |
| a { | |
| color: inherit; | |
| text-decoration: underline; | |
| cursor: pointer; | |
| } | |
| h1 { | |
| font-size: 1.5em; | |
| font-weight: 700; | |
| line-height: 30px; | |
| padding: 0 var(--horizontal-padding); | |
| margin-bottom: 1em; | |
| } | |
| p { | |
| font-size: 14px; | |
| line-height: 19px; | |
| margin-bottom: 1em; | |
| word-wrap: break-word; | |
| } | |
| </style> | |
| <script> | |
| // Note: these values are synonymous with the values of enum class Inspector::ExtensionError. | |
| WI = { | |
| WebInspectorExtension: { | |
| ErrorCode: { | |
| ContextDestroyed: "ContextDestroyed", | |
| InternalError: "InternalError", | |
| InvalidRequest: "InvalidRequest", | |
| RegistrationFailed: "RegistrationFailed", | |
| NotImplemented: "NotImplemented", | |
| } | |
| } | |
| }; | |
| function addButtonEventListener(elementID, callback) | |
| { | |
| let button = document.getElementById(elementID); | |
| if (!button) | |
| return false; | |
| button.addEventListener("click", callback); | |
| return true; | |
| } | |
| // Note: this is expected to return a promise that fulfills when | |
| // one of the buttons is clicked. The promise will be rejected if | |
| // there are no buttons specified, and also just before the main | |
| // frame navigates. | |
| async function waitForPolicyDecision() | |
| { | |
| if (window._waitForPolicyDecisionPromiseData) | |
| return window._waitForPolicyDecisionPromiseData.promise; | |
| window._waitForPolicyDecisionPromiseData = {}; | |
| window._waitForPolicyDecisionPromiseData.promise = new Promise((resolve, reject) => { | |
| window._waitForPolicyDecisionPromiseData.resolve = resolve; | |
| window._waitForPolicyDecisionPromiseData.reject = reject; | |
| }); | |
| let buttonNames = ["policy-1", "policy-2", "policy-3"]; | |
| let addedButtonsCount = buttonNames.filter((id) => addButtonEventListener(id, handlePolicyDecision)).length; | |
| if (!addedButtonsCount) | |
| window._waitForPolicyDecisionPromiseData.reject?.(WI.WebInspectorExtension.ErrorCode.InvalidRequest); | |
| window.addEventListener("pagehide", () => { | |
| window._waitForPolicyDecisionPromiseData.reject?.(WI.WebInspectorExtension.ErrorCode.ContextDestroyed); | |
| }); | |
| return window._waitForPolicyDecisionPromiseData.promise; | |
| } | |
| function handlePolicyDecision(event) | |
| { | |
| if (!window._waitForPolicyDecisionPromiseData) | |
| return; | |
| // On the first button click, pull out the resolve and reject callbacks. | |
| let {resolve, reject, promise} = window._waitForPolicyDecisionPromiseData; | |
| if (!resolve || !reject) | |
| return; | |
| window._waitForPolicyDecisionPromiseData = { promise }; | |
| // One of 'policy-1', 'policy-2', 'policy-3'. | |
| resolve(event.target.id); | |
| } | |
| function receivePayload(payload) | |
| { | |
| for (let placeholderID of ['titleText', 'descriptionText', 'policy-1', 'policy-2', 'policy-3']) { | |
| let placeholderElement = document.getElementById(placeholderID); | |
| if (!placeholderElement) { | |
| console.error("Couldn't find placeholder element for placeholderID: " + placeholderID); | |
| continue; | |
| } | |
| let payloadValue = payload[placeholderID]; | |
| placeholderElement.textContent = payloadValue ?? "LOCALIZED STRING NOT FOUND"; | |
| placeholderElement.classList.toggle("hidden", !payloadValue); | |
| } | |
| let anyButtonIsVisible = payload['policy-1'] || payload['policy-2'] || payload['policy-3']; | |
| let bottomBarElement = document.getElementsByClassName('button-bar')[0]; | |
| bottomBarElement.classList.toggle("hidden", !anyButtonIsVisible); | |
| } | |
| </script> | |
| </head> | |
| <body> | |
| <div class="vertical-flex-container"> | |
| <div id="alert-container" class="alert-container"> | |
| <h1 id="titleText">An extension would like to access this website</h1> | |
| </h1> | |
| <div class="alert-body"> | |
| <p id="descriptionText">The extension would be able to read and alter webpages and see your browsing history on this website. This could include sensitive information, including passwords, phone numbers, and credit cards.</p> | |
| <div class="button-bar"> | |
| <button type="button" id="policy-1">Allow for One Day</button> | |
| <button type="button" id="policy-2">Always Allow on This Website</button> | |
| <button type="button" id="policy-3">Always Allow on Every Website...</button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </body> | |
| </html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <title>Grant Permissions for Web Extension?</title> | |
| <style> | |
| @media (prefers-color-scheme: dark) { | |
| :root { | |
| color-scheme: dark; | |
| } | |
| body { | |
| background: rgb(30, 30, 30) !important; | |
| --font-color: hsl(0, 0%, 85%) !important; | |
| --title-color: rgb(224, 225, 225) !important; | |
| } | |
| .alert { | |
| background-color: rgb(56, 57, 59) !important; | |
| box-shadow: 0 6px 12px rgba(0, 0, 0, .24) !important; | |
| } | |
| } | |
| body { | |
| --font-color: #434343; | |
| --horizontal-padding: 32px; | |
| --border-radius: 6px; | |
| --title-color: #444; | |
| } | |
| * { | |
| padding: 0; | |
| margin: 0; | |
| font-family: -apple-system-font; | |
| } | |
| :root { | |
| color-scheme: light; | |
| } | |
| html, body { | |
| height: 100%; | |
| width: 100%; | |
| } | |
| body { | |
| font-size: 13px; | |
| background: linear-gradient(30deg, #dfdfdf 0%, #fafafb 100%); | |
| background-repeat: no-repeat; | |
| background-attachment: fixed; | |
| cursor: default; | |
| -webkit-user-select: none; | |
| } | |
| .alert { | |
| background-color: white; | |
| min-width: 320px; | |
| max-width: 672px; | |
| position: relative; | |
| margin: 0 auto; | |
| padding-top: 24px; | |
| border-radius: var(--border-radius); | |
| box-shadow: 0px 6px 10px rgba(0, 0, 0, 0.14); | |
| } | |
| .alert h1 { | |
| overflow: hidden; | |
| color: var(--title-color); | |
| padding-top: 3px; | |
| } | |
| .alert-body { | |
| margin: 21px 0 0 0; | |
| padding-left: var(--horizontal-padding); | |
| padding-right: var(--horizontal-padding); | |
| padding-bottom: 28px; | |
| color: var(--font-color); | |
| } | |
| .alert-body p:first-of-type { | |
| margin-bottom: 15px; | |
| margin-top: 20px; | |
| } | |
| .alert-body p:last-of-type { | |
| margin-bottom: 0; | |
| } | |
| .bottom-bar { | |
| margin-top: 1.3em; | |
| height: 22px; | |
| } | |
| .bottom-bar button { | |
| font-size: 13px; | |
| line-height: 21px; | |
| min-width: 90px; | |
| margin: 0 4px; | |
| vertical-align: bottom; | |
| padding: 0 12px; | |
| color: var(--font-color); | |
| cursor: pointer; | |
| } | |
| a { | |
| color: inherit; | |
| text-decoration: underline; | |
| cursor: pointer; | |
| } | |
| h1 { | |
| font-size: 1.5em; | |
| font-weight: 700; | |
| line-height: 30px; | |
| padding: 0 var(--horizontal-padding); | |
| margin-bottom: 1em; | |
| } | |
| p { | |
| font-size: 14px; | |
| line-height: 19px; | |
| margin-bottom: 1em; | |
| word-wrap: break-word; | |
| } | |
| .hidden { | |
| display: none; | |
| } | |
| /* RTL support */ | |
| html[dir="rtl"] .bottom-bar button { | |
| float: right; | |
| } | |
| </style> | |
| <script> | |
| // Note: this is expected to return a promise that fulfills when | |
| // one of the buttons is clicked. | |
| async function waitForPolicyDecision() | |
| { | |
| if (window._waitForPolicyDecisionPromiseData) | |
| return window._waitForPolicyDecisionPromiseData.promise; | |
| window._waitForPolicyDecisionPromiseData = {}; | |
| window._waitForPolicyDecisionPromiseData.promise = new Promise((resolve, reject) => { | |
| window._waitForPolicyDecisionPromiseData.resolve = resolve; | |
| window._waitForPolicyDecisionPromiseData.reject = reject; | |
| }); | |
| ["policy-1", "policy-2", "policy-3"].forEach((id) => { addButtonEventListener(id, handlePolicyDecision); }); | |
| return window._waitForPolicyDecisionPromiseData.promise; | |
| } | |
| function receivePayload(payload) | |
| { | |
| for (let placeholderID of ['titleText', 'descriptionText', 'policy-1', 'policy-2', 'policy-3']) { | |
| let placeholderElement = document.getElementById(placeholderID); | |
| if (!placeholderElement) { | |
| console.error("Couldn't find placeholder element for placeholderID: " + placeholderID); | |
| continue; | |
| } | |
| let payloadValue = payload[placeholderID]; | |
| placeholderElement.textContent = payloadValue ?? "LOCALIZED STRING NOT FOUND"; | |
| placeholderElement.classList.toggle("hidden", !payloadValue); | |
| } | |
| let anyButtonIsVisible = payload['policy-1'] || payload['policy-2'] || payload['policy-3']; | |
| let bottomBarElement = document.getElementsByClassName('bottom-bar')[0]; | |
| bottomBarElement.classList.toggle("hidden", !anyButtonIsVisible); | |
| } | |
| function addButtonEventListener(elementID, callback) | |
| { | |
| let button = document.getElementById(elementID); | |
| if (!button) | |
| return; | |
| button.addEventListener("click", callback); | |
| } | |
| function handlePolicyDecision(event) | |
| { | |
| if (!window._waitForPolicyDecisionPromiseData) | |
| return; | |
| // On the first button click, pull out the resolve and reject callbacks. | |
| let {resolve, reject, promise} = window._waitForPolicyDecisionPromiseData; | |
| if (!resolve || !reject) | |
| return; | |
| window._waitForPolicyDecisionPromiseData = { promise }; | |
| // One of 'policy-1', 'policy-2', 'policy-3'. | |
| resolve(event.target.id); | |
| } | |
| function pageLoaded() | |
| { | |
| window.addEventListener("resize", performLayout); | |
| performLayout(); | |
| } | |
| function performLayout() | |
| { | |
| const minimumMarginTop = 22; | |
| const maximumMarginTop = 156; | |
| let alertElement = document.getElementById("alert"); | |
| let alertElementHeight = alertElement.getBoundingClientRect().height; | |
| let viewportHeight = window.innerHeight; | |
| if (viewportHeight > alertElementHeight + 2 * maximumMarginTop) | |
| alertElement.style.top = maximumMarginTop + "px"; | |
| else | |
| alertElement.style.top = Math.max(minimumMarginTop, (viewportHeight - alertElementHeight) / 2) + "px"; | |
| } | |
| window.addEventListener("load", () => { pageLoaded(); }); | |
| </script> | |
| </head> | |
| <body> | |
| <div id="alert" class="alert"> | |
| <h1 id="titleText">An extension would like to access this website</h1> | |
| </h1> | |
| <div class="alert-body"> | |
| <p id="descriptionText">The extension would be able to read and alter webpages and see your browsing history on this website. This could include sensitive information, including passwords, phone numbers, and credit cards.</p> | |
| <div class="bottom-bar"> | |
| <button type="button" id="policy-1">Allow for One Day</button> | |
| <button type="button" id="policy-2">Always Allow on This Website</button> | |
| <button type="button" id="policy-3">Always Allow on Every Website...</button> | |
| </div> | |
| </div> | |
| </div> | |
| </body> | |
| </html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // OpenSearch description document can be specified via the <link> tag with rel="search". | |
| // See http://blog.whatwg.org/the-road-to-html-5-link-relations#rel-search. | |
| // It should have the type "application/opensearchdescription+xml". | |
| // See https://github.com/dewitt/opensearch/blob/master/opensearch-1-1-draft-6.md#mime-type-applicationopensearchdescriptionxml. | |
| (function() { | |
| if (!document.head) | |
| return null; | |
| var linkTags = document.head.getElementsByTagName("link"); | |
| var numberOfLinkTags = linkTags.length; | |
| for (var i = 0; i < numberOfLinkTags; ++i) { | |
| var linkTag = linkTags[i]; | |
| if (linkTag.getAttribute("rel") === "search" && linkTag.getAttribute("type") === "application/opensearchdescription+xml") | |
| return linkTag.href; | |
| } | |
| return null; | |
| })(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <meta name="disabled-adaptations" content="watch"> | |
| <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> | |
| <meta name="viewport" content="initial-scale=1"> | |
| <base> | |
| <title>Reader</title> | |
| <style id="article-content"> | |
| h1, h2, h3, h4, h5, h6 { | |
| font-weight: bold; | |
| } | |
| h1 { | |
| font-size: 1.5em; | |
| line-height: 1.4em; | |
| } | |
| h2 { | |
| font-size: 1.43em; | |
| } | |
| h3 { | |
| font-size: 1.25em; | |
| } | |
| h4, h5, h6 { | |
| font-size: 1em; | |
| margin: 1em 0; | |
| } | |
| body.watch h1 { | |
| font-size: 1.1875rem; | |
| } | |
| body.watch h2 { | |
| font-size: 1.125rem; | |
| } | |
| body.watch h3 { | |
| font-size: 1.0625rem; | |
| } | |
| body.watch :matches(h4, h5, h6) { | |
| font-size: 1rem; | |
| } | |
| h1.title { | |
| font-weight: bold; | |
| font-size: 1.95552em; | |
| line-height: 1.2141em; | |
| margin-top: 0; | |
| margin-bottom: 0.5em; | |
| } | |
| .subhead { | |
| font-weight: normal; | |
| } | |
| .title, .subhead, .metadata { | |
| text-align: start; | |
| hyphens: manual; | |
| display: none; | |
| } | |
| :nth-child(1 of .page) :matches(.title, .subhead, .metadata) { | |
| display: block; | |
| } | |
| .subhead { | |
| color: rgba(27, 27, 27, 0.65); | |
| font-size: 1.46664em; | |
| margin-top: -0.35em; | |
| line-height: 1.27275em; | |
| } | |
| .metadata { | |
| margin-top: -0.75em; | |
| margin-bottom: 1.45em; | |
| } | |
| body.watch .metadata { | |
| line-height: 1.3em; | |
| } | |
| .metadata * { | |
| font-size: 1em !important; | |
| font-weight: normal !important; | |
| font-style: normal !important; | |
| display: inline !important; | |
| margin: 0; | |
| } | |
| .metadata :matches(.byline, .date) { | |
| display: inline !important; | |
| } | |
| .metadata :matches(ul, ol, li) { | |
| list-style-type: none; | |
| -webkit-padding-start: 0; | |
| } | |
| .title + .metadata { | |
| margin-top: -0.75em; | |
| } | |
| .subhead + .metadata { | |
| margin-top: -0.7em; | |
| } | |
| .page { | |
| text-align: start; | |
| word-wrap: break-word; | |
| } | |
| body.watch .page { | |
| hyphens: auto; | |
| } | |
| .page.rtl { | |
| direction: rtl; | |
| } | |
| a { | |
| text-decoration: none; | |
| } | |
| a[href] { | |
| color: rgb(65, 110, 210); | |
| } | |
| #article { | |
| text-rendering: optimizeLegibility; | |
| } | |
| #article * { | |
| /* Scale down anything larger than our view. Max-width maintains aspect ratios on images. */ | |
| max-width: 100%; | |
| } | |
| #article img { | |
| /* By default, images are centered on their own line. */ | |
| margin: 0.5em auto; | |
| display: block; | |
| height: auto; | |
| } | |
| #article img.reader-image-tiny { | |
| display: inline; | |
| margin: 0; | |
| } | |
| #article .leading-image, figure, .auxiliary { | |
| margin-bottom: 1.15em; | |
| } | |
| #article .leading-image img { | |
| margin: auto; | |
| display: block; | |
| clear: both; | |
| } | |
| #article .leading-image .credit { | |
| margin: 0; | |
| } | |
| #article .leading-image, | |
| #article figure { | |
| font-size: 0.75em; | |
| line-height: 1.5em; | |
| } | |
| body.watch #article .leading-image, | |
| body.watch #article figure { | |
| font-size: 0.8125rem; | |
| } | |
| #article .leading-image :matches(.caption, .credit), | |
| #article figcaption { | |
| margin-top: 0.8em; | |
| width: 100%; | |
| } | |
| body.watch #article .leading-image :matches(.caption, .credit), | |
| body.watch #article figcaption { | |
| margin-top: 4px; | |
| } | |
| body.watch #article figure img { | |
| margin-bottom: 0; | |
| } | |
| #article figcaption > * { | |
| margin-top: 0.25em; | |
| margin-bottom: 0.25em; | |
| } | |
| #article :matches(.leading-image, figure) p { | |
| margin-top: 0.4em; | |
| margin-bottom: 0.4em; | |
| } | |
| #article .leading-image .credit + .caption { | |
| margin-top: 0.1em; | |
| } | |
| #article .auxiliary { | |
| display: block; | |
| clear: both; | |
| font-size: 0.75em; | |
| line-height: 1.4em; | |
| text-align: start; | |
| } | |
| body.watch #article .auxiliary { | |
| font-size: 0.9em; | |
| } | |
| #article .pullquote { | |
| font-size: 1.42em; | |
| line-height: 1.38em; | |
| font-weight: 300; | |
| font-style: italic; | |
| } | |
| #article .pullquote:not(.float) { | |
| margin-top: 1em; | |
| margin-bottom: 1em; | |
| -webkit-margin-start: 1em; | |
| max-width: calc(100% - 1em); | |
| } | |
| #article .auxiliary > *:not(img) { | |
| -webkit-margin-start: 0; | |
| } | |
| #article .auxiliary.float img, #article .auxiliary > *:first-child:not(img) { | |
| margin: 0; | |
| } | |
| /* If the element immediately after an image is inline, it might bump up against the image. */ | |
| #article .auxiliary img + * { | |
| display: block; | |
| } | |
| #article .auxiliary figcaption { | |
| font-size: 100%; | |
| } | |
| #article .auxiliary * { | |
| margin-top: 0.5em; | |
| margin-bottom: 0.5em; | |
| } | |
| body:not(.watch) #article .float.left { | |
| float: left; | |
| margin-right: 20px; | |
| } | |
| body:not(.watch) #article .float.right { | |
| float: right; | |
| margin-left: 20px; | |
| } | |
| body.watch #article .float { | |
| width: auto !important; | |
| } | |
| #article .clear { | |
| clear: both; | |
| } | |
| #article ul.list-style-type-none, | |
| #article ol.list-style-type-none, | |
| #article .list-style-type-none > li { | |
| list-style-type: none; | |
| -webkit-padding-start: 0; | |
| } | |
| #article .page .list-style-type-none.code-block code { | |
| white-space: pre-wrap; | |
| } | |
| #article .page div.scrollable { | |
| overflow-x: scroll; | |
| word-wrap: normal; | |
| } | |
| #article .page div.scrollable table { | |
| max-width: none; | |
| } | |
| #article .leading-image, #article figure, #article .auxiliary:not(.pullquote) { | |
| font-family: -apple-system-font; | |
| } | |
| #article .leading-image, #article figure, #article .auxiliary, #article .pullquote { | |
| color: rgba(0, 0, 0, 0.65); | |
| } | |
| figure { | |
| margin: 0; | |
| } | |
| body:not(.watch) figure:not(.float) { | |
| margin-top: 1.4em; | |
| margin-bottom: 1.4em; | |
| } | |
| hr { | |
| background: rgba(0, 0, 0, 0.2); | |
| height: 1px; | |
| border: 0; | |
| } | |
| pre { | |
| font-family: -apple-system-ui-monospaced, Menlo; | |
| font-size: 0.87em; | |
| line-height: 1.45em; | |
| } | |
| blockquote, q { | |
| color: rgba(0, 0, 0, 0.65); | |
| } | |
| blockquote:not(.pullquote) { | |
| margin-left: 2px; | |
| margin-right: 6px; | |
| padding-left: 16px; | |
| } | |
| blockquote:not(.simple):not(.pullquote) { | |
| border-left: 3px solid rgba(0, 0, 0, 0.1); | |
| } | |
| q.pullquote { | |
| display: block; | |
| } | |
| .pullquote q::before, .pullquote q::after, q.pullquote::before, q.pullquote::after { | |
| content: ""; | |
| } | |
| /* Collapse excess whitespace. */ | |
| .page p > p:empty, | |
| .page div > p:empty, | |
| .page p > div:empty, | |
| .page div > div:empty, | |
| .page p + br, | |
| .page img + br | |
| { | |
| display: none; | |
| } | |
| .page table { | |
| font-size: 0.9em; | |
| text-align: start; | |
| word-wrap: break-word; | |
| border-collapse: collapse; | |
| } | |
| .page table td, .page table th { | |
| padding: 0.25em 0.5em; | |
| border: 1px solid rgb(216, 216, 216); | |
| } | |
| body.watch .page > * { | |
| margin-left: 0; | |
| margin-right: 0; | |
| } | |
| body.watch .page ol { | |
| padding: 0 0 0 35px; | |
| } | |
| body.watch .page ul { | |
| padding: 0 0 0 20px; | |
| } | |
| body.watch .page li { | |
| margin: 0.8em 0; | |
| } | |
| body.watch .page blockquote { | |
| padding: 0 0 0 8px; | |
| } | |
| .delimiter { | |
| margin-left: 0.45em; | |
| margin-right: 0.45em; | |
| margin-top: 0.07em; | |
| padding: 0; | |
| } | |
| .metadata.singleline .delimiter::after { | |
| content: "•"; | |
| } | |
| .metadata:not(.singleline) .delimiter { | |
| content: ""; | |
| display: block !important; | |
| } | |
| .page table th { | |
| background-color: rgba(0, 0, 0, 0.025); | |
| } | |
| .page sup, .page sub { | |
| line-height: 1; | |
| font-size: 0.75em; | |
| } | |
| .hidden { | |
| display: none; | |
| } | |
| /* Special Font Customizations */ | |
| .system { font-family: -apple-system-font; } | |
| .watch.system { font: -apple-system-body; } | |
| .yuantisc { | |
| letter-spacing: 1px; | |
| } | |
| .yuantitc { | |
| letter-spacing: 1px; | |
| } | |
| /* Printing and mailing. */ | |
| #article.exported { | |
| font-size: 1.2em; | |
| } | |
| .exported { | |
| line-height: 1.5em; | |
| } | |
| .exported a[href] { | |
| text-decoration: underline; | |
| } | |
| #article.exported { | |
| margin: 0; | |
| padding: 0; | |
| } | |
| .exported .float { | |
| float: none; | |
| margin-top: 1.4em; | |
| margin-bottom: 1.4em; | |
| } | |
| #article.exported .leading-image, | |
| #article.exported figcaption { | |
| font-size: 0.75rem; | |
| color: rgba(0, 0, 0, 0.8); | |
| } | |
| .exported .delimiter::after { | |
| content: ""; | |
| } | |
| </style> | |
| <style id="print"> | |
| @media print { | |
| body { | |
| margin: 2mm 9mm; | |
| } | |
| .original-url { | |
| display: none; | |
| } | |
| #article .float.left { | |
| float: left !important; | |
| } | |
| #article .float.right { | |
| float: right !important; | |
| } | |
| #article .float { | |
| margin-top: 0 !important; | |
| margin-bottom: 0 !important; | |
| } | |
| } | |
| </style> | |
| <style id="reader-ui"> | |
| @media screen { | |
| body { | |
| margin: 0; | |
| padding: 0; | |
| -webkit-user-select: none; | |
| overflow-x: hidden; | |
| -webkit-text-size-adjust: none; | |
| } | |
| body.mac { | |
| background-color: transparent; | |
| } | |
| #article { | |
| pointer-events: auto; | |
| -webkit-user-select: auto; | |
| overflow: visible; | |
| margin-bottom: 42vh !important; | |
| } | |
| #article:focus { | |
| outline: none; | |
| } | |
| .page-number { | |
| display: block; | |
| } | |
| #article :nth-child(1 of .page):nth-last-child(1 of .page) .page-number { | |
| display: none; | |
| } | |
| body.watch #article :nth-child(1 of .page):nth-last-child(1 of .page) { | |
| padding-top: 0.15em; | |
| } | |
| .page-number, #incoming-page-corner { | |
| font-weight: bold; | |
| position: absolute; | |
| -webkit-user-select: none; | |
| font: 12px "Helvetica Neue"; | |
| color: rgb(168, 168, 168); | |
| cursor: default; | |
| } | |
| body.watch :matches(.page-number, #incoming-page-corner) { | |
| top: 8px; | |
| right: 16px; | |
| } | |
| .page { | |
| margin-left: auto; | |
| margin-right: auto; | |
| padding-top: 35px; | |
| padding-bottom: 35px; | |
| position: relative; | |
| border-top: 1px solid rgba(0, 0, 0, 0.2); | |
| } | |
| body.watch .page { | |
| padding: 0 4px; | |
| } | |
| #article :nth-child(1 of .page) { | |
| margin-top: 0; | |
| border-top: none; | |
| padding-top: 32px; | |
| } | |
| .page:last-of-type { | |
| padding-bottom: 45px; | |
| } | |
| .page video { | |
| height: auto; | |
| position: relative; | |
| } | |
| #incoming-page-placeholder { | |
| height: 30px; | |
| margin-bottom: 0; | |
| } | |
| #incoming-page-corner { | |
| position: absolute; | |
| right: 10px; | |
| top: 8px; | |
| } | |
| #incoming-page-text { | |
| float: right; | |
| -webkit-user-select: none; | |
| } | |
| #next-page-container { | |
| position:absolute; | |
| /* Workaround for <rdar://problem/8662842> iOS Reader: loading multiple pages stops at the 2nd page. */ | |
| left: -1000px; | |
| /* The iframe needs to be wider than the width threshold value for Reader detection, see <rdar://problem/9599297>. */ | |
| width: 320px; | |
| height: 0px; | |
| } | |
| .page div.scrollable { | |
| -webkit-overflow-scrolling: touch; | |
| } | |
| } | |
| @media screen and (-webkit-min-device-pixel-ratio:2) { | |
| .page { | |
| border-top-width: 0.5px; | |
| } | |
| hr { | |
| height: 0.5px; | |
| } | |
| } | |
| #article .extendsBeyondTextColumn { | |
| max-width: none; | |
| } | |
| .iframe-wrapper { | |
| background-color: black; | |
| max-width: none; | |
| text-align: center; | |
| } | |
| iframe { | |
| border: 0; | |
| } | |
| @media screen and (min-width: 0px) { | |
| /* Includes iPhone 5 in portrait */ | |
| .page { padding-left: 16px; padding-right: 16px; } | |
| .page-number, #incoming-page-corner { | |
| top: 8px; | |
| right: 16px; | |
| } | |
| #article :nth-child(1 of .page):nth-last-child(1 of .page) { | |
| padding-top: 14px; | |
| } | |
| } | |
| @media screen and (min-width: 161px) { | |
| /* Apple Watch 40mm */ | |
| body.watch .page { | |
| padding: 0 8.5px; | |
| } | |
| } | |
| @media screen and (min-width: 183px) { | |
| /* Apple Watch 44mm */ | |
| body.watch .page { | |
| padding: 0 9.5px; | |
| } | |
| } | |
| @media screen and (min-width: 375px) { | |
| /* iPhone 6 in portrait */ | |
| .page { padding-left: 18px; padding-right: 18px; } | |
| .page-number, #incoming-page-corner { | |
| top: 6px; | |
| right: 18px; | |
| } | |
| #article :nth-child(1 of .page):nth-last-child(1 of .page) { | |
| padding-top: 16px; | |
| } | |
| } | |
| @media screen and (min-width: 414px) { | |
| /* iPhone 6 Plus in portrait */ | |
| .page { padding-left: 20px; padding-right: 20px; } | |
| .page-number, #incoming-page-corner { | |
| top: 6px; | |
| right: 20px; | |
| } | |
| #article :nth-child(1 of .page):nth-last-child(1 of .page) { | |
| padding-top: 18px; | |
| } | |
| } | |
| /* iPhone 5 in landscape (568px) */ | |
| @media screen and (min-width: 667px) { | |
| /* iPhone 6 in landscape */ | |
| .page { padding-left: 40px; padding-right: 40px; } | |
| .page-number, #incoming-page-corner { | |
| /* Stop lining this text up with .page's right margin. */ | |
| top: 10px; | |
| right: 10px; | |
| } | |
| #article :nth-child(1 of .page):nth-last-child(1 of .page) { | |
| padding-top: 26px; | |
| } | |
| } | |
| @media screen and (max-width: 569px) { | |
| /* iPhone 5 in landscape (568px) and smaller, including all iPhones in portrait */ | |
| h1.title { | |
| font-size: 1.5558em; | |
| } | |
| h1 { | |
| font-size: 1.4em; | |
| } | |
| h2 { | |
| font-size: 1.2777em; | |
| } | |
| h3 { | |
| font-size: 1.15em; | |
| } | |
| .subhead { | |
| font-size: 1.2222em; | |
| } | |
| .metadata { | |
| font-size: 0.9em; | |
| line-height: 1.6em; | |
| } | |
| .title + .metadata { | |
| margin-top: -0.65em; | |
| } | |
| } | |
| @media screen and (min-width: 704px) { | |
| /* iPad in landscape with the sidebar open */ | |
| .page { padding-left: 42px; padding-right: 42px; } | |
| } | |
| @media screen and (min-width: 736px) { | |
| /* iPhone 6 Plus in landscape */ | |
| .page { padding-left: 60px; padding-right: 60px; } | |
| #article :nth-child(1 of .page):nth-last-child(1 of .page) { | |
| padding-top: 46px; | |
| } | |
| } | |
| @media only screen and (min-width: 780px) { | |
| #article { | |
| max-width: 800px; | |
| margin: 0 auto; | |
| } | |
| /* Readable margins. */ | |
| body.system #article { max-width: 83.2ex; } | |
| body.athelas #article { max-width: 104ex; } | |
| body.charter #article { max-width: 86ex; } | |
| body.georgia #article { max-width: 94ex; } | |
| body.iowanoldstyle #article { max-width: 90ex; } | |
| body.palatino #article { max-width: 97ex; } | |
| body.seravek #article { max-width: 87ex; } | |
| body.timesnewroman #article { max-width: 97ex; } | |
| body.uiserif #article { max-width: 93ex; } | |
| :matches(body.pingfangsc, body.pingfangtc) #article { max-width: 87.6ex; } | |
| :matches(body.heitisc, body.heititc) #article { max-width: 74.8ex; } | |
| :matches(body.songtisc, body.songtitc) #article { max-width: 102ex; } | |
| :matches(body.kaitisc, body.kaititc) #article { max-width: 102ex; } | |
| :matches(body.yuantisc, body.yuantitc) #article { max-width: 86.2ex; } | |
| :matches(body.libiansc, body.libiantc) #article { max-width: 95ex; } | |
| :matches(body.weibeisc, body.weibeitc) #article { max-width: 99ex; } | |
| :matches(body.yuppysc, body.yuppytc) #article { max-width: 87.6ex; } | |
| body.hiraginosansw3 #article { max-width: 75.7ex; } | |
| body.hiraginokakugothicpron #article { max-width: 76.4ex; } | |
| body.hiraginominchopron #article { max-width: 77.5ex; } | |
| body.hiraginomarugothicpron #article { max-width: 75.1ex; } | |
| body.applesdgothicneo #article { max-width: 82ex; } | |
| body.nanumgothic #article { max-width: 88.6ex; } | |
| body.nanummyeongjo #article { max-width: 94.1ex; } | |
| .page { | |
| /* We don't want the lines seperating pages to extend beyond the primary text column. */ | |
| padding-left: 0px; | |
| padding-right: 0px; | |
| margin-left: 70px; | |
| margin-right: 70px; | |
| } | |
| } | |
| #article { | |
| -webkit-font-smoothing: subpixel-antialiased; | |
| } | |
| /* Reader's paper appearance. */ | |
| html.paper { | |
| height: 100%; | |
| } | |
| html.paper body { | |
| height: calc(100% - 44px); | |
| } | |
| html.paper body:after { | |
| content: ""; | |
| height: 22px; | |
| display: block; | |
| } | |
| /* Clearfix */ | |
| html.paper .page::after { | |
| content: ""; | |
| display: table; | |
| clear: both; | |
| } | |
| html.paper #article { | |
| min-height: 100%; | |
| margin: 22px auto 0 auto; | |
| } | |
| html.paper #article :nth-child(1 of .page), html.paper #article :nth-child(1 of .page):nth-last-child(1 of .page) { | |
| padding-top: 53px; | |
| } | |
| html.paper #article .page-number, html.paper #article #incoming-page-corner { | |
| /* Stop lining this text up with .page's right margin. */ | |
| top: 14px; | |
| right: 0px; | |
| } | |
| /* End Reader's paper appearance. */ | |
| /* Use slightly smaller page padding when vertically constrained. */ | |
| @media screen and (max-height: 700px) { | |
| .page { | |
| padding-top: 32px; | |
| padding-bottom: 32px; | |
| } | |
| } | |
| </style> | |
| <style id="theming"> | |
| body.white { | |
| --body-font-color: rgb(27, 27, 27); | |
| --horizontal-line-color: rgb(220, 220, 220); | |
| --paper-shadow-color: rgba(0, 0, 0, 0.2); | |
| } | |
| body.sepia { | |
| --body-font-color: rgb(79, 50, 28); | |
| --horizontal-line-color: rgb(230, 218, 201); | |
| --paper-shadow-color: rgba(0, 0, 0, 0.2); | |
| } | |
| body.gray { | |
| --body-font-color: rgba(255, 255, 255, 0.78); | |
| --horizontal-line-color: rgb(111, 111, 111); | |
| } | |
| body.night { | |
| --body-font-color: rgb(176, 176, 176); | |
| --horizontal-line-color: rgb(62, 62, 62); | |
| } | |
| body.night.oled { | |
| --body-font-color: rgb(210, 210, 210); | |
| --horizontal-line-color: rgba(210, 210, 210, 0.35); | |
| } | |
| body.watch.night.oled { | |
| --body-font-color: rgb(174, 180, 191); | |
| } | |
| html:not(.paper) body.white, body.white #article { | |
| background-color: white; | |
| } | |
| html:not(.paper) body.sepia, body.sepia #article { | |
| background-color: rgb(248, 241, 227); | |
| } | |
| html:not(.paper) body.gray, body.gray #article { | |
| background-color: rgb(74, 74, 77); | |
| } | |
| html:not(.paper) body.night, body.night #article { | |
| background-color: rgb(18, 18, 18); | |
| } | |
| html:not(.paper) body.night.oled, body.night.oled #article { | |
| background-color: black; | |
| } | |
| /* OS X Reader draws backdrop background colors outside of web content, so the follow set only applies to iOS. */ | |
| html.paper body.ios.white { | |
| background-color: rgb(230, 230, 230); | |
| } | |
| html.paper body.ios.sepia { | |
| background-color: rgb(224, 216, 200); | |
| } | |
| html.paper body.ios.gray { | |
| background-color: rgb(50, 50, 51); | |
| } | |
| html.paper body.ios.night { | |
| background-color: black; | |
| } | |
| body.watch.night .metadata * { | |
| color: rgb(214, 217, 223) !important; | |
| } | |
| html.paper body.white #article, html.paper body.sepia #article { | |
| box-shadow: 0px 6px 12px 3px var(--paper-shadow-color); | |
| } | |
| html.paper body.gray #article { | |
| box-shadow: 0px 6px 12px 3px rgba(0, 0, 0, 0.24); | |
| } | |
| html.paper body.night #article { | |
| outline: 1px solid #272727; | |
| } | |
| body.watch.night.oled :matches(h1, h2, h3, h4, h5, h6) { | |
| color: white; | |
| } | |
| body.sepia #article :matches(.leading-image, figure, .auxiliary, .pullquote) { | |
| color: rgba(79, 50, 28, 0.9); | |
| } | |
| body.gray #article :matches(.leading-image, figure, .auxiliary, .pullquote) { | |
| color: rgba(255, 255, 255, 0.7); | |
| } | |
| body.night #article :matches(.leading-image, figure, .auxiliary, .pullquote) { | |
| color: rgba(255, 255, 255, 0.67); | |
| } | |
| body.night.oled #article :matches(.leading-image, figure, .auxiliary, .pullquote) { | |
| color: rgba(210, 210, 210, 0.9); | |
| } | |
| body.sepia #article a[href] { | |
| color: rgb(209, 150, 0); | |
| } | |
| body.gray #article a[href], body.night #article a[href] { | |
| color: rgb(90, 200, 250); | |
| } | |
| body.watch.night.oled #article a[href] { | |
| color: rgb(32, 148, 250); | |
| } | |
| body #article :matches(.page, .metadata a[href]) { | |
| color: var(--body-font-color); | |
| } | |
| body #article .page { | |
| border-top-color: var(--horizontal-line-color); | |
| } | |
| body #article hr { | |
| background: var(--horizontal-line-color); | |
| } | |
| body.sepia .subhead { | |
| color: rgba(79, 50, 28, 0.72); | |
| } | |
| body.gray .subhead { | |
| color: rgba(255, 255, 255, 0.65); | |
| } | |
| body.night .subhead { | |
| color: rgba(185, 185, 185, 0.9); | |
| } | |
| body.night.oled .subhead { | |
| color: rgba(210, 210, 210, 0.85); | |
| } | |
| body.sepia :matches(#article .page-number, #incoming-page-corner) { | |
| color: rgba(63, 41, 23, 0.5); | |
| } | |
| body.gray :matches(#article .page-number, #incoming-page-corner) { | |
| color: rgba(255, 255, 255, 0.45); | |
| } | |
| body.night :matches(#article .page-number, #incoming-page-corner) { | |
| color: rgba(255, 255, 255, 0.55); | |
| } | |
| body.night.oled :matches(#article .page-number, #incoming-page-corner) { | |
| color: rgba(210, 210, 210, 0.8); | |
| } | |
| body.sepia #article blockquote, body.sepia #article q { | |
| color: rgb(140, 112, 79); | |
| } | |
| body.sepia #article blockquote:not(.simple):not(.pullquote) { | |
| border-left-color: rgba(154, 128, 92, 0.1); | |
| } | |
| body.gray #article blockquote, body.gray #article q { | |
| color: rgba(255, 255, 255, 0.6); | |
| } | |
| body.gray #article blockquote:not(.simple):not(.pullquote) { | |
| border-left-color: rgba(255, 255, 255, 0.15); | |
| } | |
| body.night #article blockquote, body.night #article q { | |
| color: rgba(255, 255, 255, 0.6); | |
| } | |
| body.night #article blockquote:not(.simple):not(.pullquote) { | |
| border-left-color: rgba(255, 255, 255, 0.15); | |
| } | |
| body.night.oled #article blockquote, body.night.oled #article q { | |
| color: rgba(210, 210, 210, 0.85); | |
| } | |
| body.night.oled #article blockquote:not(.simple):not(.pullquote) { | |
| border-left-color: rgba(210, 210, 210, 0.2); | |
| } | |
| body.watch.night #article blockquote, body.watch.night #article q { | |
| color: var(--body-font-color); | |
| } | |
| body.watch.night #article blockquote:not(.simple):not(.pullquote) { | |
| border-left-color: rgb(51, 51, 51); | |
| } | |
| body.sepia table :matches(td, th) { | |
| border-color: rgb(230, 218, 202); | |
| } | |
| body.sepia table th { | |
| background-color: rgba(154, 128, 92, 0.06); | |
| } | |
| body.gray table :matches(td, th) { | |
| border-color: rgb(106, 106, 106); | |
| } | |
| body.gray table th { | |
| background-color: rgba(255, 255, 255, 0.035); | |
| } | |
| body.night table :matches(td, th) { | |
| border-color: rgb(50, 50, 50); | |
| } | |
| body.night table th { | |
| background-color: rgba(255, 255, 255, 0.045); | |
| } | |
| body.night.oled table th { | |
| background-color: rgba(255, 255, 255, 0.075); | |
| } | |
| @media (inverted-colors) { | |
| /* If the user has turned on the "smart invert" accessibility preference, they generally prefer | |
| their images, such as photos, to not be inverted. Provide this by applying a filter that | |
| inverts the colors again (effectively un-inverting). */ | |
| body:not(.gray):not(.night) #article :matches(img, video) { | |
| filter: invert(); | |
| } | |
| body:not(.gray):not(.night) #article picture { | |
| filter: none !important; | |
| } | |
| body.gray, body.night { | |
| filter: invert(); | |
| } | |
| body:matches(.gray, .night) #article :matches(img:not(picture > img), picture, video) { | |
| filter: none !important; | |
| } | |
| body:matches(.gray, .night) #article iframe { | |
| filter: invert(); | |
| } | |
| html.paper body.white #article, html.paper body.sepia #article { | |
| --paper-shadow-color: rgba(255, 255, 255, 0.2); | |
| } | |
| /* The background color of <body> is not inverted by the filter. Achieve this by manually | |
| setting the inverse color. */ | |
| html:not(.paper) body.gray { | |
| background-color: rgb(165, 165, 163) !important; | |
| } | |
| html.paper body.gray { | |
| background-color: rgb(205, 205, 204) !important; | |
| } | |
| html:not(.paper) body.night { | |
| background-color: rgb(237, 237, 237) !important; | |
| } | |
| html:not(.paper) body.night.oled { | |
| background-color: white !important; | |
| } | |
| html.paper body.night { | |
| background-color: white !important; | |
| } | |
| } | |
| </style> | |
| <style id="locale-specific-adjustments"> | |
| .locale-ja .page { | |
| text-align: justify; | |
| } | |
| .locale-zh-Hans .page { | |
| text-align: justify; | |
| } | |
| .locale-zh-Hant .page { | |
| text-align: justify; | |
| word-break: break-all; | |
| } | |
| .locale-hi .title { | |
| line-height: 1.65em; | |
| } | |
| /* See 32728279 and 54061051. */ | |
| .locale-ur.notonastaliqurdu :matches(h1, h2, h3, h4, h5, h6) { | |
| font-weight: normal; | |
| line-height: 2.55em; | |
| } | |
| </style> | |
| <style id="dynamic-article-content"></style> | |
| <!-- For Twitter’s script to find and script world to be created (see 34937240). --> | |
| <script> | |
| window.isReaderPage = true; | |
| </script> | |
| </head> | |
| <body> | |
| <iframe aria-hidden="true" id="next-page-container"></iframe> | |
| <div id="article" role="article"> | |
| <!-- This node will contain a number of div.page. --> | |
| </div> | |
| </body> | |
| </html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // # sourceURL=__InjectedScript_ReaderArticleFinder.js | |
| /* Copyright (c) 2024 Apple Inc. All rights reserved. */ | |
| /* | |
| * Copyright (c) 2010 Apple Inc. All rights reserved. | |
| * | |
| * Portions Copyright (c) 2009 Arc90 Inc | |
| * Readability. An Arc90 Lab Experiment. | |
| * Website: http://lab.arc90.com/experiments/readability | |
| * Source: http://code.google.com/p/arc90labs-readability | |
| * Readability is licensed under the Apache License, Version 2.0. | |
| */ | |
| function hostnameMatchesHostKnownToContainEmbeddableMedia(e) | |
| { | |
| return /^(.+\.)?(youtube(-nocookie)?\.com|vimeo\.com|dailymotion\.com|soundcloud\.com|mixcloud\.com|embedly\.com|embed\.ly)\.?$/.test(e) | |
| } | |
| function lazyLoadingImageURLForElement(e, t) | |
| { | |
| function n(e) | |
| { | |
| const t = /\.(jpe?g|png|gif|bmp)$/i; | |
| if (t.test(e)) | |
| return !0; | |
| let n = urlFromString(e); | |
| return !!n && t.test(n.pathname) | |
| } | |
| function r(e) | |
| { | |
| let t = attributesForElement(e); | |
| for (let r of t) { | |
| let t = r.name; | |
| if (a.has(t.toLowerCase())) | |
| return e.getAttribute(t); | |
| let i = n(r.value); | |
| if (o.has(t.toLowerCase()) && i) | |
| return e.getAttribute(t); | |
| if (s && /^data.*(src|source)$/i.test(t) && i) | |
| return e.getAttribute(t); | |
| if (e instanceof HTMLImageElement && /^data-/.test(t) && i && 1 === e.naturalWidth && 1 === e.naturalHeight) | |
| return e.getAttribute(t) | |
| } | |
| } | |
| const i = /(data:image\/)?gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==/, | |
| a = new Set([ "data-lazy-src", "data-original", "datasrc", "data-src", "original-src", "rel:bf_image_src", "deferred-src", "data-mediaviewer-src", "data-hi-res-src", "data-native-src" ]), | |
| o = new Set([ "original" ]); | |
| let l = e.getAttribute("src"), | |
| s = /transparent|empty/i.test(l) || i.test(l); | |
| const c = 2; | |
| for (let t = e, n = 0; t && n < c; t = t.parentElement, ++n) { | |
| let e = r(t); | |
| if (e) | |
| return e | |
| } | |
| let u = e.closest("*[itemscope]"); | |
| if (u && /^https?:\/\/schema\.org\/ImageObject\/?$/.test(u.getAttribute("itemtype"))) { | |
| let e = u.getAttribute("itemid"); | |
| if (n(e) && !u.querySelector("img")) | |
| return e | |
| } | |
| if (LazyLoadRegex.test(t) && "function" == typeof URL) { | |
| var m; | |
| try { | |
| m = new URL(e.src) | |
| } catch (e) { | |
| } | |
| if (m && m.search) { | |
| var d, h; | |
| const t = [ "w", "width" ]; | |
| for (var g = t.length, f = 0; f < g; ++f) { | |
| var p = t[f], | |
| E = m.searchParams.get(p); | |
| if (E && !isNaN(parseInt(E))) { | |
| d = p; | |
| break | |
| } | |
| } | |
| const n = [ "h", "height" ]; | |
| var v = n.length; | |
| for (f = 0; f < v; ++f) { | |
| var N = n[f], | |
| C = m.searchParams.get(N); | |
| if (C && !isNaN(parseInt(C))) { | |
| h = N; | |
| break | |
| } | |
| } | |
| if (d && h) { | |
| var A = e.getAttribute("width"), | |
| S = e.getAttribute("height"); | |
| if (!isNaN(parseInt(A)) && !isNaN(parseInt(S))) | |
| return m.searchParams.set(d, A), m.searchParams.set(h, S), m.href | |
| } | |
| } | |
| } | |
| return null | |
| } | |
| function sanitizeElementByRemovingAttributes(e) | |
| { | |
| elementLooksLikeEmbeddedIframeTweetWithSrc(e) && (e.setAttribute("height", e.style.height), e.setAttribute("width", e.style.width)); | |
| const t = /^on|^id$|^class$|^style$|^autofocus$/; | |
| for (var n = attributesForElement(e), r = 0; r < n.length; ++r) { | |
| var i = n[r].nodeName; | |
| t.test(i) && (e.removeAttribute(i), r--) | |
| } | |
| } | |
| function characterAppearsToBeCJK(e) | |
| { | |
| if (!e || 0 === e.length) | |
| return !1; | |
| var t = e.charCodeAt(0); | |
| return t > 11904 && t < 12031 || (t > 12352 && t < 12543 || (t > 12736 && t < 19903 || (t > 19968 && t < 40959 || (t > 44032 && t < 55215 || (t > 63744 && t < 64255 || (t > 65072 && t < 65103 || (t > 131072 && t < 173791 || t > 194560 && t < 195103))))))) | |
| } | |
| function domDistance(e, t, n) | |
| { | |
| for (var r = [], i = e; i;) | |
| r.unshift(i), i = i.parentNode; | |
| var a = []; | |
| for (i = t; i;) | |
| a.unshift(i), i = i.parentNode; | |
| for (var o = Math.min(r.length, a.length), l = Math.abs(r.length - a.length), s = o; s >= 0 && r[s] !== a[s]; --s) | |
| if (l += 2, n && l >= n) | |
| return n; | |
| return l | |
| } | |
| function fontSizeFromComputedStyle(e, t) | |
| { | |
| var n = parseInt(e.fontSize); | |
| return isNaN(n) && (n = t || BaseFontSize), n | |
| } | |
| function contentTextStyleForNode(e, t) | |
| { | |
| function n(e) | |
| { | |
| if (isNodeWhitespace(e)) | |
| return null; | |
| var t = getComputedStyle(e.parentNode); | |
| return "none" !== t.float ? null : t | |
| } | |
| for (var r = "descendant::text()[not(parent::h1) and not(parent::h2) and not(parent::h3) and not(parent::h4) and not(parent::h5) and not(parent::h6)]", i = e.evaluate(r, t, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null), a = i.snapshotLength, o = 0; o < a; ++o) { | |
| for (var l = i.snapshotItem(o), s = !1, c = l.parentElement; c !== t; c = c.parentElement) | |
| if (NegativeRegEx.test(c.className)) { | |
| s = !0; | |
| break | |
| } | |
| if (!s) { | |
| var u = n(l); | |
| if (u) | |
| return u | |
| } | |
| } | |
| return null | |
| } | |
| function isNodeWhitespace(e) | |
| { | |
| return !(!e || e.nodeType !== Node.TEXT_NODE) && !/\S/.test(e.data) | |
| } | |
| function removeWhitespace(e) | |
| { | |
| return e.replace(/\s+/g, "") | |
| } | |
| function isElementNode(e) | |
| { | |
| return !(!e || e.nodeType !== Node.ELEMENT_NODE) | |
| } | |
| function computedStyleIndicatesElementIsInvisibleDueToClipping(e) | |
| { | |
| if ("absolute" !== e.position) | |
| return !1; | |
| var t = e.clip.match(/^rect\((\d+px|auto), (\d+px|auto), (\d+px|auto), (\d+px|auto)\)$/); | |
| if (!t || 5 !== t.length) | |
| return !1; | |
| var n = t.map((function(e) { | |
| return parseInt(e) | |
| })), | |
| r = n[1]; | |
| isNaN(r) && (r = 0); | |
| var i = n[2], | |
| a = n[3], | |
| o = n[4]; | |
| return isNaN(o) && (o = 0), r >= a || i >= o | |
| } | |
| function isElementVisible(e) | |
| { | |
| var t = getComputedStyle(e); | |
| if ("visible" !== t.visibility || "none" === t.display) | |
| return !1; | |
| if (cachedElementBoundingRect(e).height) | |
| return !0; | |
| var n = document.createRange(); | |
| return n.selectNode(e), !!n.getBoundingClientRect().height | |
| } | |
| function isElementPositionedOffScreen(e) | |
| { | |
| var t = cachedElementBoundingRect(e); | |
| return !(!t.height || !t.width) && (t.bottom <= 0 || t.right <= 0) | |
| } | |
| function elementDepth(e) | |
| { | |
| for (var t = 0; e; e = e.parentElement) | |
| t++; | |
| return t | |
| } | |
| function depthOfElementWithinElement(e, t) | |
| { | |
| for (var n = 0; e !== t; e = e.parentElement) { | |
| if (!e) | |
| return NaN; | |
| n++ | |
| } | |
| return n | |
| } | |
| function nearestAncestorElementWithTagName(e, t, n) | |
| { | |
| var r = {}; | |
| if (n) | |
| for (var i = 0; i < n.length; ++i) | |
| r[n[i]] = !0; | |
| if (r[normalizedElementTagName(e)]) | |
| return null; | |
| for (; e = e.parentElement;) { | |
| var a = normalizedElementTagName(e); | |
| if (r[a]) | |
| break; | |
| if (a === t) | |
| return e | |
| } | |
| return null | |
| } | |
| function elementDescendsFromElementMatchingSelector(e, t) | |
| { | |
| do { | |
| if (e.matches(t)) | |
| return !0 | |
| } while (e = e.parentElement); | |
| return !1 | |
| } | |
| function elementDescendsFromElementInSet(e, t) | |
| { | |
| do { | |
| if (t.has(e)) | |
| return !0 | |
| } while (e = e.parentElement); | |
| return !1 | |
| } | |
| function elementIsHidingContentDueToContentVisibilityAuto(e) | |
| { | |
| return !!window.ContentVisibilityAutoStateChangeEvent && ("auto" === getComputedStyle(e).contentVisibility && (!!e.children.length && !e.children[0].checkVisibility({ | |
| contentVisibilityAuto : !0 | |
| }))) | |
| } | |
| function cachedElementBoundingRect(e) | |
| { | |
| if (e._cachedElementBoundingRect) | |
| return e._cachedElementBoundingRect; | |
| if (ReaderArticleFinderJS.shouldSuppressBoundingRectCalculationForSkippedElements() && elementIsHidingContentDueToContentVisibilityAuto(e)) { | |
| let n = e.previousElementSibling; | |
| return n && !elementIsHidingContentDueToContentVisibilityAuto(n) ? ((t = cachedElementBoundingRect(n)).top += t.height, t.bottom += t.height, t) : { | |
| top : 0, | |
| right : 0, | |
| bottom : 0, | |
| left : 0, | |
| width : 0, | |
| height : 0 | |
| } | |
| } | |
| var t = e.getBoundingClientRect(); | |
| return ReaderArticleFinderJS._elementsWithCachedBoundingRects.push(e), ReaderArticleFinderJS._cachedScrollX || ReaderArticleFinderJS._cachedScrollY ? (e._cachedElementBoundingRect = { | |
| top : t.top + ReaderArticleFinderJS._cachedScrollY, | |
| right : t.right + ReaderArticleFinderJS._cachedScrollX, | |
| bottom : t.bottom + ReaderArticleFinderJS._cachedScrollY, | |
| left : t.left + ReaderArticleFinderJS._cachedScrollX, | |
| width : t.width, | |
| height : t.height | |
| }, | |
| e._cachedElementBoundingRect) | |
| : (e._cachedElementBoundingRect = t, e._cachedElementBoundingRect) | |
| } | |
| function clearCachedElementBoundingRects() | |
| { | |
| for (var e = ReaderArticleFinderJS._elementsWithCachedBoundingRects, t = e.length, n = 0; n < t; ++n) | |
| e[n]._cachedElementBoundingRect = null; | |
| ReaderArticleFinderJS._elementsWithCachedBoundingRects = [] | |
| } | |
| function trimmedInnerTextIgnoringTextTransform(e) | |
| { | |
| var t = e.innerText; | |
| if (!/\S/.test(t)) | |
| return e.textContent.trim(); | |
| var n = getComputedStyle(e).textTransform; | |
| return "uppercase" === n || "lowercase" === n ? e.textContent.trim() : t ? t.trim() | |
| : "" | |
| } | |
| function levenshteinDistance(e, t) | |
| { | |
| for (var n = e.length, r = t.length, i = new Array(n + 1), a = 0; a < n + 1; ++a) | |
| i[a] = new Array(r + 1), i[a][0] = a; | |
| for (var o = 0; o < r + 1; ++o) | |
| i[0][o] = o; | |
| for (o = 1; o < r + 1; ++o) | |
| for (a = 1; a < n + 1; ++a) | |
| if (e[a - 1] === t[o - 1]) | |
| i[a][o] = i[a - 1][o - 1]; | |
| else { | |
| var l = i[a - 1][o] + 1, | |
| s = i[a][o - 1] + 1, | |
| c = i[a - 1][o - 1] + 1; | |
| i[a][o] = Math.min(l, s, c) | |
| } | |
| return i[n][r] | |
| } | |
| function stringSimilarity(e, t) | |
| { | |
| var n = Math.max(e.length, t.length); | |
| return n ? (n - levenshteinDistance(e, t)) / n : 0 | |
| } | |
| function stringsAreNearlyIdentical(e, t) | |
| { | |
| return e === t || stringSimilarity(e, t) > StringSimilarityToDeclareStringsNearlyIdentical | |
| } | |
| function elementIsCommentBlock(e) | |
| { | |
| if (/(^|\s)comment/.test(e.className)) | |
| return !0; | |
| var t = e.getAttribute("id"); | |
| return !(!t || 0 !== t.indexOf("comment") && 0 !== t.indexOf("Comment")) | |
| } | |
| function elementLooksLikeEmbeddedTweet(e) | |
| { | |
| var t = null; | |
| if ("iframe" === normalizedElementTagName(e)) { | |
| if (!e.contentDocument) | |
| return elementLooksLikeEmbeddedIframeTweetWithSrc(e); | |
| t = e.contentDocument.documentElement | |
| } else | |
| "twitter-widget" === normalizedElementTagName(e) && (t = e.shadowRoot); | |
| if (!t) | |
| return !1; | |
| if (e.closest(".twitter-video") && t.querySelector("[data-tweet-id]")) | |
| return !0; | |
| let n = 0, | |
| r = t.querySelector("blockquote"); | |
| r && TweetURLRegex.test(r.getAttribute("cite")) && ++n; | |
| let i = t.querySelector("[data-iframe-title]"); | |
| return i && TweetIframeTitleRegex.test(i.getAttribute("data-iframe-title")) && ++n, e.classList.contains("twitter-tweet") && ++n, t.querySelector("[data-tweet-id]") && ++n, n > 2 | |
| } | |
| function elementLooksLikeEmbeddedIframeTweetWithSrc(e) | |
| { | |
| return EmbeddedTwitterIframeSrcRegEx.test(e.getAttribute("src")) && "Twitter Tweet" === e.getAttribute("title") | |
| } | |
| function elementLooksLikeACarousel(e) | |
| { | |
| const t = /carousel-|carousel_|-carousel|_carousel|swiper-/; | |
| return t.test(e.className) || t.test(e.getAttribute("data-analytics")) | |
| } | |
| function elementLooksLikePartOfACarousel(e) | |
| { | |
| const t = 3; | |
| for (var n = e, r = 0; r < t; ++r) { | |
| if (!n) | |
| return !1; | |
| if (elementLooksLikeACarousel(n)) | |
| return !0; | |
| n = n.parentElement | |
| } | |
| return !1 | |
| } | |
| function urlIsHTTPFamilyProtocol(e) | |
| { | |
| let t = e.protocol; | |
| return "http:" === t || "https:" === t | |
| } | |
| function shouldPruneIframe(e) | |
| { | |
| if (e.srcdoc) | |
| return !0; | |
| let t = urlFromString(e.src); | |
| if (t) { | |
| if (!urlIsHTTPFamilyProtocol(t)) | |
| return !0; | |
| if (hostnameMatchesHostKnownToContainEmbeddableMedia(t.hostname)) | |
| return !1 | |
| } | |
| return !elementLooksLikeEmbeddedTweet(e.originalElement) | |
| } | |
| function textContentAppearsToBeCJK(e, t) | |
| { | |
| if (!e || !e.length) | |
| return !1; | |
| let n = e.length; | |
| t && !isNaN(t) && (n = Math.min(n, t)); | |
| let r = 0; | |
| for (let t = 0; t < n; t++) | |
| characterAppearsToBeCJK(e[t]) && r++; | |
| return r >= n * MinimumRatioOfCharactersForLanguageMultiplier | |
| } | |
| function languageScoreMultiplierForTextNodes(e) | |
| { | |
| if (!e || !e.length) | |
| return 1; | |
| for (var t = Math.min(e.length, DefaultNumberOfTextNodesToCheckForLanguageMultiplier), n = 0, r = 0, i = 0; i < t; i++) { | |
| for (var a = e[i].nodeValue.trim(), o = Math.min(a.length, NumberOfCharactersPerTextNodeToEvaluateForLanguageMultiplier), l = 0; l < o; l++) | |
| characterAppearsToBeCJK(a[l]) && n++; | |
| r += o | |
| } | |
| return n >= r * MinimumRatioOfCharactersForLanguageMultiplier ? ScoreMultiplierForChineseJapaneseKorean : 1 | |
| } | |
| function scoreMultiplierForElementTagNameAndAttributes(e) | |
| { | |
| for (var t = 1, n = e; n; n = n.parentElement) { | |
| var r = n.getAttribute("id"); | |
| r && (ArticleRegEx.test(r) && (t += ArticleMatchBonus), CommentRegEx.test(r) && (t -= CommentMatchPenalty), CarouselRegEx.test(r) && (t -= CarouselMatchPenalty)); | |
| var i = n.className; | |
| i && (ArticleRegEx.test(i) && (t += ArticleMatchBonus), CommentRegEx.test(i) && (t -= CommentMatchPenalty), CarouselRegEx.test(i) && (t -= CarouselMatchPenalty)), "article" === normalizedElementTagName(n) && (t += ArticleMatchBonus) | |
| } | |
| return t < 0 ? 0 : t | |
| } | |
| function elementAtPoint(e, t, n) | |
| { | |
| if ("undefined" != typeof ReaderArticleFinderJSController && ReaderArticleFinderJSController.nodeAtPoint) { | |
| var r = ReaderArticleFinderJSController.nodeAtPoint(e, t); | |
| return r && r.nodeType !== Node.ELEMENT_NODE && (r = r.parentElement), r | |
| } | |
| return n.elementFromPoint(e, t) | |
| } | |
| function userVisibleURLString(e) | |
| { | |
| return "undefined" != typeof ReaderArticleFinderJSController && ReaderArticleFinderJSController.userVisibleURLString ? ReaderArticleFinderJSController.userVisibleURLString(e) : e | |
| } | |
| function urlFromString(e, t) | |
| { | |
| try { | |
| return null != t ? new URL(e, t) : new URL(e) | |
| } catch (e) { | |
| return null | |
| } | |
| } | |
| function urlStringShouldHaveItsAnchorMadeNonFunctional(e, t) | |
| { | |
| if (!e) | |
| return !0; | |
| var n = urlFromString(e); | |
| if (n || (n = urlFromString(e, t)), !n || !n.href || !n.href.length) | |
| return !0; | |
| let r = n.href; | |
| return "javascript:" === r.trim().substring(0, 11).toLowerCase() || "data:" === r.trim().substring(0, 5).toLowerCase() | |
| } | |
| function anchorLinksToAttachment(e) | |
| { | |
| return /\battachment\b/i.test(e.getAttribute("rel")) | |
| } | |
| function anchorLinksToTagOrCategoryPage(e) | |
| { | |
| return /\bcategory|tag\b/i.test(e.getAttribute("rel")) | |
| } | |
| function anchorLooksLikeDownloadFlashLink(e) | |
| { | |
| return /^https?:\/\/(www\.|get\.)(adobe|macromedia)\.com\/(((products|[a-zA-Z]{1,2}|)\/flashplayer|flashplayer|go\/getflash(player)?)|(shockwave\/download\/(index|download)\.cgi\?P1_Prod_Version=ShockwaveFlash)\/?$)/i.test(e.href) | |
| } | |
| function elementsHaveSameTagAndClassNames(e, t) | |
| { | |
| return normalizedElementTagName(e) === normalizedElementTagName(t) && e.className === t.className | |
| } | |
| function selectorForElement(e) | |
| { | |
| let t = normalizedElementTagName(e); | |
| for (var n = e.classList, r = n.length, i = 0; i < r; i++) | |
| t += "." + n[i]; | |
| return t | |
| } | |
| function elementFingerprintForDepth(e, t) | |
| { | |
| function n(e, t) | |
| { | |
| if (!e) | |
| return ""; | |
| var o = []; | |
| o.push(selectorForElement(e)); | |
| var l = e.children, | |
| s = l.length; | |
| if (s && t > 0) { | |
| o.push(r); | |
| for (var c = 0; c < s; ++c) | |
| o.push(n(l[c], t - 1)), c !== s - 1 && o.push(a); | |
| o.push(i) | |
| } | |
| return o.join("") | |
| } | |
| const r = " / ", | |
| i = " \\", | |
| a = " | "; | |
| return n(e, t) | |
| } | |
| function childrenOfParentElement(e) | |
| { | |
| var t = e.parentElement; | |
| return t ? t.children : [] | |
| } | |
| function arrayOfKeysAndValuesOfObjectSortedByValueDescending(e) | |
| { | |
| var t = []; | |
| for (var n in e) | |
| e.hasOwnProperty(n) && t.push({ | |
| key : n, | |
| value : e[n] | |
| }); | |
| return t.sort((function(e, t) { | |
| return t.value - e.value | |
| })), | |
| t | |
| } | |
| function walkElementSubtree(e, t, n) | |
| { | |
| if (!(t < 0)) { | |
| for (var r = e.children, i = r.length, a = t - 1, o = 0; o < i; ++o) | |
| walkElementSubtree(r[o], a, n); | |
| n(e, t) | |
| } | |
| } | |
| function elementIndicatesItIsASchemaDotOrgArticleContainer(e) | |
| { | |
| var t = e.getAttribute("itemtype"); | |
| return /^https?:\/\/schema\.org\/((News)?Article|APIReference)$/.test(t) | |
| } | |
| function elementIndicatesItIsASchemaDotOrgImageObject(e) | |
| { | |
| var t = e.getAttribute("itemtype"); | |
| return "https://schema.org/ImageObject" === t || "http://schema.org/ImageObject" === t | |
| } | |
| function elementWouldAppearBetterAsFigureOrAuxiliary(e, t) | |
| { | |
| const n = /caption/i; | |
| if (!e) | |
| return !1; | |
| if (t.closest("figure, .auxiliary")) | |
| return !1; | |
| if (elementIndicatesItIsASchemaDotOrgImageObject(e) && !t.querySelector("figure, .auxiliary")) | |
| return !0; | |
| var r = t.ownerDocument.createTreeWalker(t, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, { | |
| acceptNode : function() { | |
| return NodeFilter.FILTER_ACCEPT | |
| } | |
| }); | |
| r.currentNode = t; | |
| for (var i = !1, a = !1; r.nextNode();) { | |
| var o = r.currentNode; | |
| if (o.nodeType === Node.TEXT_NODE) { | |
| if (!i && /\S/.test(o.nodeValue)) | |
| return !1; | |
| continue | |
| } | |
| if (o.nodeType !== Node.ELEMENT_NODE) | |
| return !1; | |
| let e = normalizedElementTagName(o); | |
| if ("figure" === e || "table" === e) | |
| return !1; | |
| if (o.classList.contains("auxiliary")) | |
| return !1; | |
| if ("img" === e) { | |
| if (i) | |
| return !1; | |
| i = !0 | |
| } | |
| var l = o.originalElement; | |
| a || l && !hasClassMatchingRegexp(o.originalElement, n) || !/\S/.test(o.innerText) || (a = !0) | |
| } | |
| return i && a | |
| } | |
| function cleanStyleAndClassList(e) | |
| { | |
| e.classList.length || e.removeAttribute("class"), e.getAttribute("style") || e.removeAttribute("style") | |
| } | |
| function getVisibleNonWhitespaceTextNodes(e, t, n, r, i) | |
| { | |
| function a(e) | |
| { | |
| var t = e.children[0]; | |
| if (t) | |
| for (var n = t.children, r = n.length, i = 0; i < r; ++i) | |
| if ("none" !== getComputedStyle(n[i]).float) | |
| return !1; | |
| return !0 | |
| } | |
| function o(e, r) | |
| { | |
| if (e.nodeType === Node.TEXT_NODE) | |
| return void (/\S/.test(e.nodeValue) && s.push(e)); | |
| if (e.nodeType !== Node.ELEMENT_NODE) | |
| return; | |
| if (!isElementVisible(e)) | |
| return; | |
| if (n && ++l > n) | |
| return; | |
| if (i && i.has(e)) | |
| return; | |
| let u = normalizedElementTagName(e); | |
| if ("iframe" !== u && "form" !== u) { | |
| if (c.has(u)) | |
| r--; | |
| else if ("ul" !== u && "ol" !== u || !a(e)) { | |
| var m = e.parentElement; | |
| if (m) | |
| "section" !== normalizedElementTagName(m) || e.previousElementSibling || e.nextElementSibling || r-- | |
| } else | |
| r--; | |
| var d = r + 1; | |
| if (d < t) | |
| for (var h = e.childNodes, g = h.length, f = 0; f < g; ++f) | |
| o(h[f], d) | |
| } | |
| } | |
| var l = 0, | |
| s = []; | |
| let c = new Set([ "p", "strong", "b", "em", "i", "span", "section" ]); | |
| return r && (c.add("center"), c.add("font")), o(e, 0), s | |
| } | |
| function mapOfVisibleTextNodeComputedStyleReductionToNumberOfMatchingCharacters(e, t) | |
| { | |
| for (var n = {}, r = getVisibleNonWhitespaceTextNodes(e, 100), i = r.length, a = 0; a < i; ++a) { | |
| var o = r[a], | |
| l = o.length, | |
| s = o.parentElement, | |
| c = t(getComputedStyle(s)); | |
| n[c] ? n[c] += l : n[c] = l | |
| } | |
| return n | |
| } | |
| function keyOfMaximumValueInDictionary(e) | |
| { | |
| var t, n; | |
| for (var r in e) { | |
| var i = e[r]; | |
| (!n || i > n) && (t = r, n = i) | |
| } | |
| return t | |
| } | |
| function elementIsProtected(e) | |
| { | |
| return e.classList.contains("protected") || e.querySelector(".protected") | |
| } | |
| function dominantFontFamilyAndSizeForElement(e) | |
| { | |
| return keyOfMaximumValueInDictionary(mapOfVisibleTextNodeComputedStyleReductionToNumberOfMatchingCharacters(e, (function(e) { | |
| return e.fontFamily + "|" + e.fontSize | |
| }))) | |
| } | |
| function dominantFontSizeInPointsFromFontFamilyAndSizeString(e) | |
| { | |
| return e ? parseInt(e.split("|")[1]) : null | |
| } | |
| function canvasElementHasNoUserVisibleContent(e) | |
| { | |
| if (!e.width || !e.height) | |
| return !0; | |
| for (var t = e.getContext("2d").getImageData(0, 0, e.width, e.height).data, n = 0, r = t.length; n < r; n += 4) { | |
| if (t[n + 3]) | |
| return !1 | |
| } | |
| return !0 | |
| } | |
| function findArticleNodeSelectorsInQuirksListForHostname(e, t) | |
| { | |
| const n = [ | |
| [ AppleDotComAndSubdomainsRegex, "*[itemprop='articleBody']" ], | |
| [ /^(.+\.)?buzzfeed\.com\.?$/, "article #buzz_sub_buzz" ], | |
| [ /^(.+\.)?mashable\.com\.?$/, ".parsec-body .parsec-container" ], | |
| [ /^(.+\.)?cnet\.com\.?$/, "#rbContent.container" ], | |
| [ /^(.+\.)?engadget\.com\.?$/, "main article #page_body" ], | |
| [ /^(.*\.)?m\.wikipedia\.org\.?$/, "#content #bodyContent" ], | |
| [ /^(.*\.)?theintercept\.com\.?$/, ".PostContent" ], | |
| [ /^(.*\.)?tools\.ietf\.org\.?$/, "div.content" ], | |
| [ /^(.+\.)?meteoinfo\.ru\.?$/, "#jm-content-bottom" ], | |
| [ /^(.*\.)?tmd\.go\.th\.?$/, "#sidebar" ] | |
| ]; | |
| for (var r = n.length, i = 0; i < r; ++i) { | |
| var a = n[i]; | |
| if (a[0].test(e.toLowerCase())) | |
| if (t(a[1])) | |
| return | |
| } | |
| } | |
| function functionToPreventPruningDueToInvisibilityInQuirksListForHostname(e) | |
| { | |
| const t = [ | |
| [ /^mobile\.nytimes\.com\.?$/, function(e, t) { | |
| var n = e; | |
| if (!t) | |
| return !1; | |
| for (; n && n !== t;) { | |
| if (n.classList.contains("hidden")) | |
| return !0; | |
| n = n.parentElement | |
| } | |
| return !1 | |
| } ] | |
| ]; | |
| for (var n = t.length, r = 0; r < n; ++r) { | |
| var i = t[r]; | |
| if (i[0].test(e.toLowerCase())) | |
| return i[1] | |
| } | |
| return null | |
| } | |
| function elementIsAHeader(e) | |
| { | |
| return !!{ | |
| h1 : 1, | |
| h2 : 1, | |
| h3 : 1, | |
| h4 : 1, | |
| h5 : 1, | |
| h6 : 1 | |
| }[normalizedElementTagName(e)] | |
| } | |
| function leafElementForElementAndDirection(e, t) | |
| { | |
| var n = e.ownerDocument, | |
| r = n.createTreeWalker(n.body, NodeFilter.SHOW_ELEMENT, { | |
| acceptNode : function(e) { | |
| return 0 === e.children.length ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP | |
| } | |
| }); | |
| return r.currentNode = e, r[t]() | |
| } | |
| function previousLeafElementForElement(e) | |
| { | |
| return leafElementForElementAndDirection(e, "previousNode") | |
| } | |
| function nextLeafElementForElement(e) | |
| { | |
| return leafElementForElementAndDirection(e, "nextNode") | |
| } | |
| function nextNonFloatingVisibleElementSibling(e) | |
| { | |
| for (var t = e; t = t.nextElementSibling;) | |
| if (isElementVisible(t) && "none" === getComputedStyle(t).float) | |
| return t; | |
| return null | |
| } | |
| function elementWithLargestAreaFromElements(e) | |
| { | |
| var t, n = e.length; | |
| if (!n) | |
| return null; | |
| for (var r = 0, i = 0; i < n; ++i) { | |
| var a = e[i], | |
| o = cachedElementBoundingRect(a), | |
| l = o.width * o.height; | |
| l > r && (t = a, r = l) | |
| } | |
| return t | |
| } | |
| function unwrappedArticleContentElement(e) | |
| { | |
| for (var t = e;;) { | |
| for (var n = t.childNodes, r = n.length, i = null, a = 0; a < r; ++a) { | |
| var o = n[a], | |
| l = o.nodeType; | |
| if (l === Node.ELEMENT_NODE || l === Node.TEXT_NODE && !isNodeWhitespace(o)) { | |
| if (i) | |
| return t; | |
| var s = normalizedElementTagName(o); | |
| if ("div" !== s && "article" !== s && "section" !== s) | |
| return t; | |
| i = o | |
| } | |
| } | |
| if (!i) | |
| break; | |
| t = i | |
| } | |
| return t | |
| } | |
| function elementsMatchingClassesInClassList(e, t) | |
| { | |
| return elementsOfSameClassIgnoringClassNamesMatchingRegexp(e, t) | |
| } | |
| function elementsMatchingClassesInClassListIgnoringCommonLayoutClassNames(e, t) | |
| { | |
| return elementsOfSameClassIgnoringClassNamesMatchingRegexp(e, t, /clearfix/i) | |
| } | |
| function elementsMatchingClassesInClassListIgnoringClassesWithNumericSuffix(e, t) | |
| { | |
| return elementsOfSameClassIgnoringClassNamesMatchingRegexp(e, t, /\d+$/) | |
| } | |
| function elementsOfSameClassIgnoringClassNamesMatchingRegexp(e, t, n) | |
| { | |
| for (var r = "", i = e.length, a = 0; a < i; ++a) { | |
| var o = e[a]; | |
| n && n.test(o) || (r += "." + o) | |
| } | |
| try { | |
| return t.querySelectorAll(r) | |
| } catch (e) { | |
| return [] | |
| } | |
| } | |
| function imageIsContainedByContainerWithImageAsBackgroundImage(e) | |
| { | |
| var t = e.parentElement; | |
| if (!t || !t.style || !t.style.backgroundImage) | |
| return !1; | |
| var n = /url\((.*)\)/.exec(t.style.backgroundImage); | |
| return !(!n || 2 !== n.length) && n[1] === e.src | |
| } | |
| function pseudoElementContent(e, t) | |
| { | |
| var n = getComputedStyle(e, t).content, | |
| r = /^\"(.*)\"$/.exec(n); | |
| return r && 2 == r.length ? r[1] : null | |
| } | |
| function hasClassMatchingRegexp(e, t) | |
| { | |
| for (var n = e.classList, r = n.length, i = 0; i < r; ++i) | |
| if (t.test(n[i])) | |
| return !0; | |
| return !1 | |
| } | |
| function elementLooksLikeDropCap(e) | |
| { | |
| return hasClassMatchingRegexp(e, DropCapRegex) && 1 === e.innerText.length | |
| } | |
| function changeElementType(e, t) | |
| { | |
| for (var n = e.ownerDocument.createElement(t), r = attributesForElement(e), i = r.length, a = 0; a < i; ++a) { | |
| var o = r.item(a); | |
| n.setAttribute(o.nodeName, o.nodeValue) | |
| } | |
| for (; e.firstChild;) | |
| n.appendChild(e.firstChild); | |
| return e.replaceWith(n), n | |
| } | |
| function pathComponentsForAnchor(e) | |
| { | |
| var t = e.pathname.substring(1).split("/"); | |
| return t[t.length - 1] || t.pop(), t | |
| } | |
| function lastPathComponentFromAnchor(e) | |
| { | |
| var t = pathComponentsForAnchor(e); | |
| return t.length ? t[t.length - 1] : null | |
| } | |
| function clamp(e, t, n) | |
| { | |
| return Math.min(Math.max(e, t), n) | |
| } | |
| function normalizedElementTagName(e) | |
| { | |
| return e.localName | |
| } | |
| function childrenWithParallelStructure(e) | |
| { | |
| var t = e.children; | |
| if (!t) | |
| return []; | |
| var n = t.length; | |
| if (!n) | |
| return []; | |
| for (var r = {}, i = 0; i < n; ++i) { | |
| var a = t[i]; | |
| if (!SetOfCandidateTagNamesToIgnore.has(normalizedElementTagName(a)) && a.className) | |
| for (var o = a.classList, l = o.length, s = 0; s < l; ++s) { | |
| (m = r[u = o[s]]) ? m.push(a) : r[u] = [ a ] | |
| } | |
| } | |
| var c = Math.floor(n / 2); | |
| for (var u in r) { | |
| var m; | |
| if ((m = r[u]).length > c) | |
| return m | |
| } | |
| return [] | |
| } | |
| function elementAppearsToBeCollapsed(e) | |
| { | |
| return !(!ReaderArticleFinderJS.isMediaWikiPage() || !/collaps/.test(e.className)) || "false" === e.getAttribute("aria-expanded") && !isElementVisible(e) | |
| } | |
| const ReaderMinimumScore = 1600, | |
| ReaderMinimumAdvantage = 15, | |
| ArticleMinimumScoreDensity = 4.25, | |
| CandidateMinimumWidthPortionForIndicatorElements = .5, | |
| CandidateMinumumListItemLineCount = 4, | |
| SetOfCandidateTagNamesToIgnore = new Set([ "a", "embed", "form", "html", "iframe", "object", "ol", "option", "script", "style", "svg", "ul" ]), | |
| PrependedArticleCandidateMinimumHeight = 50, | |
| AppendedArticleCandidateMinimumHeight = 200, | |
| AppendedArticleCandidateMaximumVerticalDistanceFromArticle = 150, | |
| StylisticClassNames = { | |
| justfy : 1, | |
| justify : 1, | |
| left : 1, | |
| right : 1, | |
| small : 1 | |
| }, | |
| CommentRegEx = /[Cc]omment|meta|footer|footnote|talkback/, | |
| CommentMatchPenalty = .75, | |
| ArticleRegEx = /(?:(?:^|\s)(?:(post|hentry|entry)[-_]{0,2}(?:content|text|body)?|article[-_]{0,2}(?:content|text|body|page|copy)?)(?:\s|$))/i, | |
| ArticleMatchBonus = .5, | |
| CarouselRegEx = /carousel/i, | |
| CarouselMatchPenalty = .75, | |
| SectionRegex = /section|content.*component/i, | |
| DropCapRegex = /first.*letter|drop.*cap/i, | |
| ProgressiveLoadingRegex = /progressive/i, | |
| DensityExcludedElementSelector = "#disqus_thread, #comments, .userComments", | |
| PositiveRegEx = /article|body|content|entry|hentry|page|pagination|post|related-asset|text/i, | |
| NegativeRegEx = /advertisement|breadcrumb|combx|comment|contact|disqus|footer|link|meta|mod-conversations|promo|related|scroll|share|shoutbox|sidebar|social|sponsor|spotim|subscribe|talkback|tags|toolbox|widget|[-_]ad$|zoom-(in|out)/i, | |
| VeryPositiveClassNameRegEx = /instapaper_body/, | |
| VeryNegativeClassNameRegEx = /instapaper_ignore/, | |
| SharingRegex = /email|print|rss|digg|slashdot|delicious|reddit|share|twitter|facebook|pinterest|whatsapp/i, | |
| VeryLiberalCommentRegex = /comment/i, | |
| AdvertisementHostRegex = /^adserver\.|doubleclick.net$/i, | |
| SidebarRegex = /sidebar/i, | |
| MinimumAverageDistanceBetweenHRElements = 400, | |
| MinimumAverageDistanceBetweenHeaderElements = 400, | |
| PortionOfCandidateHeightToIgnoreForHeaderCheck = .1, | |
| DefaultNumberOfTextNodesToCheckForLanguageMultiplier = 3, | |
| NumberOfCharactersPerTextNodeToEvaluateForLanguageMultiplier = 12, | |
| MinimumRatioOfCharactersForLanguageMultiplier = .5, | |
| ScoreMultiplierForChineseJapaneseKorean = 3, | |
| MinimumContentMediaHeight = 150, | |
| MinimumContentMediaWidthToArticleWidthRatio = .25, | |
| MaximumContentMediaAreaToArticleAreaRatio = .2, | |
| LinkContinueMatchRegEx = /continue/gi, | |
| LinkNextMatchRegEx = /next/gi, | |
| LinkPageMatchRegEx = /page/gi, | |
| LinkListItemBonus = 5, | |
| LinkPageMatchBonus = 10, | |
| LinkNextMatchBonus = 15, | |
| LinkContinueMatchBonus = 15, | |
| LinkNextOrdinalValueBase = 3, | |
| LinkMismatchValueBase = 2, | |
| LinkMatchWeight = 200, | |
| LinkMaxVerticalDistanceFromArticle = 200, | |
| LinkVerticalDistanceFromArticleWeight = 150, | |
| LinkCandidateXPathQuery = "descendant-or-self::*[(not(@id) or (@id!='disqus_thread' and @id!='comments')) and (not(@class) or @class!='userComments')]/a", | |
| LinkDateRegex = /\D(?:\d\d(?:\d\d)?[\-\/](?:10|11|12|0?[1-9])[\-\/](?:30|31|[12][0-9]|0?[1-9])|\d\d(?:\d\d)?\/(?:10|11|12|0[1-9])|(?:10|11|12|0?[1-9])\-(?:30|31|[12][0-9]|0?[1-9])\-\d\d(?:\d\d)?|(?:30|31|[12][0-9]|0?[1-9])\-(?:10|11|12|0?[1-9])\-\d\d(?:\d\d)?)\D/, | |
| LinkURLSearchParameterKeyMatchRegex = /(page|^p$|^pg$)/i, | |
| LinkURLPageSlashNumberMatchRegex = /\/.*page.*\/\d+/i, | |
| LinkURLSlashDigitEndMatchRegex = /\/\d+\/?$/, | |
| LinkURLArchiveSlashDigitEndMatchRegex = /archives?\/\d+\/?$/, | |
| LinkURLBadSearchParameterKeyMatchRegex = /author|comment|feed|id|nonce|related/i, | |
| LinkURLSemanticMatchBonus = 100, | |
| LinkMinimumURLSimilarityRatio = .75, | |
| SubheadRegex = /sub(head|title)|description|dec?k|abstract/i, | |
| HeaderMinimumDistanceFromArticleTop = 200, | |
| HeaderLevenshteinDistanceToLengthRatio = .75, | |
| MinimumRatioOfListItemsBeingRelatedToSharingToPruneEntireList = .5, | |
| FloatMinimumHeight = 130, | |
| ImageSizeTiny = 32, | |
| ToleranceForLeadingMediaWidthToArticleWidthForFullWidthPresentation = 80, | |
| MaximumFloatWidth = 325, | |
| AnchorImageMinimumWidth = 100, | |
| AnchorImageMinimumHeight = 100, | |
| MinimumHeightForImagesAboveTheArticleTitle = 50, | |
| MainImageMinimumWidthAndHeight = 83, | |
| BaseFontSize = 16, | |
| BaseLineHeightRatio = 1.125, | |
| MaximumExactIntegralValue = 9007199254740992, | |
| TitleCandidateDepthScoreMultiplier = .1, | |
| TextNodeLengthPower = 1.25, | |
| LazyLoadRegex = /lazy/i, | |
| HeaderElementsSelector = "h1, h2, h3, h4, h5, h6", | |
| PageType = { | |
| homepage : "homepage", | |
| searchResults : "search-results", | |
| article : "article" | |
| }, | |
| StringSimilarityToDeclareStringsNearlyIdentical = .97, | |
| FindArticleMode = { | |
| Element : !1, | |
| ExistenceOfElement : !0 | |
| }, | |
| AppleDotComAndSubdomainsRegex = /.*\.apple\.com\.?$/, | |
| SchemaDotOrgArticleContainerSelector = "*[itemtype='https://schema.org/Article'], *[itemtype='https://schema.org/NewsArticle'], *[itemtype='https://schema.org/APIReference'], *[itemtype='http://schema.org/Article'], *[itemtype='http://schema.org/NewsArticle'], *[itemtype='http://schema.org/APIReference']", | |
| CleaningType = { | |
| MainArticleContent : 0, | |
| MetadataContent : 1, | |
| LeadingMedia : 2 | |
| }, | |
| MaximumWidthOrHeightOfImageInMetadataSection = 20; | |
| var attributesForElement = function() { | |
| var e = Element.prototype.__lookupGetter__("attributes"); | |
| return function(t) { | |
| return e.call(t) | |
| } | |
| }(); | |
| const TweetURLRegex = /^https?:\/\/(.+\.)?twitter\.com\/.*\/status\/(.*\/)*[0-9]+\/?$/i, | |
| TweetIframeTitleRegex = /tweet/i, | |
| EmbeddedTwitterIframeSrcRegEx = /^https?:\/\/platform\.twitter\.com\/embed\/Tweet\.html/i; | |
| CandidateElement = function(e, t) { | |
| this.element = e, this.contentDocument = t, this.textNodes = this.usableTextNodesInElement(this.element), this.rawScore = this.calculateRawScore(), this.tagNameAndAttributesScoreMultiplier = this.calculateElementTagNameAndAttributesScoreMultiplier(), this.languageScoreMultiplier = 0, this.depthInDocument = 0 | |
| }, CandidateElement.extraArticleCandidateIfElementIsViable = function(e, t, n, r) { | |
| const i = "a, b, strong, i, em, u, span"; | |
| var a = cachedElementBoundingRect(e), | |
| o = cachedElementBoundingRect(t.element); | |
| if ((r && a.height < PrependedArticleCandidateMinimumHeight || !r && a.height < AppendedArticleCandidateMinimumHeight) && e.childElementCount && e.querySelectorAll("*").length !== e.querySelectorAll(i).length) | |
| return null; | |
| if (r) { | |
| if (a.bottom > o.top) | |
| return null | |
| } else if (a.top < o.bottom) | |
| return null; | |
| if (!r && a.top - o.bottom > AppendedArticleCandidateMaximumVerticalDistanceFromArticle) | |
| return null; | |
| if (a.left > o.right || a.right < o.left) | |
| return null; | |
| if (elementLooksLikePartOfACarousel(e)) | |
| return null; | |
| var l = new CandidateElement(e, n); | |
| return l.isPrepended = r, l | |
| }, CandidateElement.candidateIfElementIsViable = function(e, t, n) { | |
| var r = cachedElementBoundingRect(e), | |
| i = ReaderArticleFinderJS.candidateElementFilter; | |
| return r.width < i.minimumWidth || r.height < i.minimumHeight || r.width * r.height < i.minimumArea || !n && r.top > i.maximumTop || CandidateElement.candidateElementAdjustedHeight(e) < i.minimumHeight ? null : new CandidateElement(e, t) | |
| }, CandidateElement.candidateElementAdjustedHeight = function(e) { | |
| for (var t = cachedElementBoundingRect(e), n = t.height, r = e.getElementsByTagName("form"), i = r.length, a = 0; a < i; ++a) { | |
| var o = cachedElementBoundingRect(r[a]); | |
| o.width > t.width * CandidateMinimumWidthPortionForIndicatorElements && (n -= o.height) | |
| } | |
| var l = e.querySelectorAll("ol, ul"), | |
| s = l.length, | |
| c = null; | |
| for (a = 0; a < s; ++a) { | |
| var u = l[a]; | |
| if (!(c && c.compareDocumentPosition(u) & Node.DOCUMENT_POSITION_CONTAINED_BY)) { | |
| var m = u.getElementsByTagName("li"), | |
| d = m.length, | |
| h = cachedElementBoundingRect(u); | |
| if (d) { | |
| var g = h.height / d, | |
| f = getComputedStyle(m[0]), | |
| p = parseInt(f.lineHeight); | |
| if (isNaN(p)) | |
| p = fontSizeFromComputedStyle(f) * BaseLineHeightRatio; | |
| h.width > t.width * CandidateMinimumWidthPortionForIndicatorElements && g / p < CandidateMinumumListItemLineCount && (n -= h.height, c = u) | |
| } else | |
| n -= h.height | |
| } | |
| } | |
| return n | |
| }, CandidateElement.prototype = { | |
| calculateRawScore : function() { | |
| for (var e = 0, t = this.textNodes, n = t.length, r = 0; r < n; ++r) | |
| e += this.rawScoreForTextNode(t[r]); | |
| return e | |
| }, | |
| calculateElementTagNameAndAttributesScoreMultiplier : function() { | |
| return scoreMultiplierForElementTagNameAndAttributes(this.element) | |
| }, | |
| calculateLanguageScoreMultiplier : function() { | |
| 0 === this.languageScoreMultiplier && (this.languageScoreMultiplier = languageScoreMultiplierForTextNodes(this.textNodes)) | |
| }, | |
| depth : function() { | |
| return this.depthInDocument || (this.depthInDocument = elementDepth(this.element)), this.depthInDocument | |
| }, | |
| finalScore : function() { | |
| return this.calculateLanguageScoreMultiplier(), this.basicScore() * this.languageScoreMultiplier | |
| }, | |
| basicScore : function() { | |
| return this.rawScore * this.tagNameAndAttributesScoreMultiplier | |
| }, | |
| scoreDensity : function() { | |
| var e = 0, | |
| t = this.element.querySelector(DensityExcludedElementSelector); | |
| t && (e = t.clientWidth * t.clientHeight); | |
| for (var n = this.element.children || [], r = n.length, i = 0; i < r; ++i) { | |
| var a = n[i]; | |
| elementIsCommentBlock(a) && (e += a.clientWidth * a.clientHeight) | |
| } | |
| var o = cachedElementBoundingRect(this.element).width * cachedElementBoundingRect(this.element).height, | |
| l = o * MaximumContentMediaAreaToArticleAreaRatio, | |
| s = cachedElementBoundingRect(this.element).width * MinimumContentMediaWidthToArticleWidthRatio, | |
| c = this.element.querySelectorAll("img, video"), | |
| u = c.length; | |
| for (i = 0; i < u; ++i) { | |
| var m = cachedElementBoundingRect(c[i]); | |
| if (m.width >= s && m.height > MinimumContentMediaHeight) { | |
| var d = m.width * m.height; | |
| d < l && (e += d) | |
| } | |
| } | |
| var h = this.basicScore(), | |
| g = o - e, | |
| f = this.textNodes.length, | |
| p = 0, | |
| E = 0; | |
| for (i = 0; i < f; ++i) { | |
| var v = this.textNodes[i].parentNode; | |
| v && (E += fontSizeFromComputedStyle(getComputedStyle(v)), p++) | |
| } | |
| var N = BaseFontSize; | |
| return p && (N = E /= p), this.calculateLanguageScoreMultiplier(), h / g * 1e3 * (N / BaseFontSize) * this.languageScoreMultiplier | |
| }, | |
| usableTextNodesInElement : function(e) { | |
| var t = []; | |
| if (!e) | |
| return t; | |
| const n = new Set([ "a", "dd", "dt", "noscript", "ol", "option", "pre", "script", "style", "td", "ul", "iframe" ]); | |
| var r = this.contentDocument, | |
| i = function(e) { | |
| const i = "text()|*/text()|*/a/text()|*/li/text()|*/li/p/text()|*/span/text()|*/em/text()|*/i/text()|*/strong/text()|*/b/text()|*/font/text()|blockquote/*/text()|div[count(./p)=count(./*)]/p/text()|div[count(*)=1]/div/p/text()|div[count(*)=1]/div/p/*/text()|div/div/text()"; | |
| for (var a = r.evaluate(i, e, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null), o = a.snapshotLength, l = 0; l < o; ++l) { | |
| var s = a.snapshotItem(l); | |
| n.has(normalizedElementTagName(s.parentNode)) || s._countedTextNode || isNodeWhitespace(s) || (s._countedTextNode = !0, t.push(s)) | |
| } | |
| }; | |
| i(e); | |
| for (var a = childrenWithParallelStructure(e), o = a.length, l = 0; l < o; ++l) { | |
| i(a[l]) | |
| } | |
| var s = t.length; | |
| for (l = 0; l < s; ++l) | |
| delete t[l]._countedTextNode; | |
| return t | |
| }, | |
| addTextNodesFromCandidateElement : function(e) { | |
| for (var t = this.textNodes.length, n = 0; n < t; ++n) | |
| this.textNodes[n].alreadyCounted = !0; | |
| var r = e.textNodes, | |
| i = r.length; | |
| for (n = 0; n < i; ++n) | |
| r[n].alreadyCounted || this.textNodes.push(r[n]); | |
| for (t = this.textNodes.length, n = 0; n < t; ++n) | |
| this.textNodes[n].alreadyCounted = null; | |
| this.rawScore = this.calculateRawScore() | |
| }, | |
| rawScoreForTextNode : function(e) { | |
| const t = 20; | |
| if (!e) | |
| return 0; | |
| var n = e.length; | |
| if (n < t) | |
| return 0; | |
| var r = e.parentNode; | |
| if (!isElementVisible(r)) | |
| return 0; | |
| for (var i = 1; r && r !== this.element;) | |
| i -= .1, r = r.parentNode; | |
| return Math.pow(n * i, TextNodeLengthPower) | |
| }, | |
| shouldDisqualifyDueToScoreDensity : function() { | |
| return this.scoreDensity() < ArticleMinimumScoreDensity | |
| }, | |
| shouldDisqualifyDueToHorizontalRuleDensity : function() { | |
| for (var e = this.element.getElementsByTagName("hr"), t = e.length, n = 0, r = cachedElementBoundingRect(this.element), i = .7 * r.width, a = 0; a < t; ++a) | |
| e[a].clientWidth > i && n++; | |
| if (n && r.height / n < MinimumAverageDistanceBetweenHRElements) | |
| return !0; | |
| return !1 | |
| }, | |
| shouldDisqualifyDueToHeaderDensity : function() { | |
| var e = "(h1|h2|h3|h4|h5|h6|*/h1|*/h2|*/h3|*/h4|*/h5|*/h6)[a[@href]]", | |
| t = this.contentDocument.evaluate(e, this.element, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null), | |
| n = t.snapshotLength; | |
| if (n > 2) { | |
| for (var r = 0, i = cachedElementBoundingRect(this.element), a = i.height * PortionOfCandidateHeightToIgnoreForHeaderCheck, o = 0; o < n; ++o) { | |
| var l = t.snapshotItem(o); | |
| if ("#" !== l.querySelector("a[href]").getAttribute("href").substring(0, 1)) { | |
| var s = cachedElementBoundingRect(l); | |
| s.top - i.top > a && i.bottom - s.bottom > a && r++ | |
| } | |
| } | |
| if (i.height / r < MinimumAverageDistanceBetweenHeaderElements) | |
| return !0 | |
| } | |
| return !1 | |
| }, | |
| shouldDisqualifyDueToSimilarElements : function(e) { | |
| function t(e, t) | |
| { | |
| if (!e || !t) | |
| return !1; | |
| var n = 1; | |
| return e.className ? e.className === t.className : elementFingerprintForDepth(e, n) === elementFingerprintForDepth(t, n) | |
| } | |
| var n = function(e) { | |
| const t = /related-posts/i; | |
| for (var n = e.parentElement; n && n !== this.contentDocument.body; n = n.parentElement) | |
| if (t.test(n.className)) | |
| return !0; | |
| return !1 | |
| }.bind(this), r = this.element; | |
| if ("article" === normalizedElementTagName(r.parentElement)) | |
| return !1; | |
| let i = normalizedElementTagName(r); | |
| if ("li" === i || "dd" === i) | |
| for (var a = r.parentNode, o = a.children.length, l = 0; l < o; ++l) { | |
| if (normalizedElementTagName(f = a.children[l]) === i && f.className === r.className && f !== r) | |
| return !0 | |
| } | |
| var s = r.classList; | |
| if (s.length || (r = r.parentElement) && ((s = r.classList).length || (r = r.parentElement) && (s = r.classList)), s.length) { | |
| e || (e = []); | |
| var c = e.length; | |
| for (l = 0; l < c; ++l) | |
| e[l].element.candidateElement = e[l]; | |
| var u = elementsMatchingClassesInClassListIgnoringCommonLayoutClassNames(s, this.contentDocument), | |
| m = !1, | |
| d = elementDepth(r), | |
| h = n(r), | |
| g = u.length; | |
| for (l = 0; l < g; ++l) { | |
| var f; | |
| if ((f = u[l]) !== r && (f.parentElement !== r && r.parentElement !== f && isElementVisible(f))) { | |
| var p = f.candidateElement; | |
| if ((p || (p = new CandidateElement(f, this.contentDocument))) && p.basicScore() * ReaderMinimumAdvantage > this.basicScore()) { | |
| if (f.closest("section") && r.closest("section")) | |
| return !1; | |
| if (SectionRegex.test(f.className) && SectionRegex.test(r.className)) | |
| return !1; | |
| if (n(f) && !h) | |
| return !1; | |
| if (!m && cachedElementBoundingRect(f).bottom < cachedElementBoundingRect(this.element).top) { | |
| m = !0; | |
| continue | |
| } | |
| if (t(r.previousElementSibling, f.previousElementSibling) || t(r.nextElementSibling, f.nextElementSibling)) { | |
| var E = r.querySelector(HeaderElementsSelector), | |
| v = f.querySelector(HeaderElementsSelector); | |
| if (E && v && elementsHaveSameTagAndClassNames(E, v)) | |
| return !0; | |
| if (E = r.previousElementSibling, v = f.previousElementSibling, E && v && elementIsAHeader(E) && elementIsAHeader(v) && elementsHaveSameTagAndClassNames(E, v)) | |
| return !0 | |
| } | |
| if (elementDepth(f) === d) | |
| for (; f.parentElement && r.parentElement && f.parentElement !== r.parentElement;) | |
| f = f.parentElement, r = r.parentElement; | |
| for (; r.childElementCount <= 1;) { | |
| if (!r.childElementCount || !f.childElementCount) | |
| return !1; | |
| if (f.childElementCount > 1) | |
| return !1; | |
| if (normalizedElementTagName(r.firstElementChild) !== normalizedElementTagName(f.firstElementChild)) | |
| return !1; | |
| r = r.firstElementChild, f = f.firstElementChild | |
| } | |
| if (f.childElementCount <= 1) | |
| return !1; | |
| v = f.firstElementChild; | |
| var N = f.lastElementChild, | |
| C = (E = r.firstElementChild, r.lastElementChild); | |
| if (normalizedElementTagName(v) !== normalizedElementTagName(E)) | |
| return !1; | |
| if (normalizedElementTagName(N) !== normalizedElementTagName(C)) | |
| return !1; | |
| var A = v.className, | |
| S = N.className, | |
| b = E.className, | |
| y = N.className, | |
| T = y === b ? 2 : 1; | |
| if (A.length || b.length) { | |
| if (!A.length || !b.length) | |
| return !1; | |
| if (A === b && elementsMatchingClassesInClassList(E.classList, r).length <= T) | |
| return !0 | |
| } | |
| if (S.length || y.length) { | |
| if (!S.length || !y.length) | |
| return !1; | |
| if (S === y && elementsMatchingClassesInClassList(N.classList, r).length <= T) | |
| return !0 | |
| } | |
| var x = E.clientHeight, | |
| R = C.clientHeight; | |
| return !(!x || !v.clientHeight) && (!(!R || !N.clientHeight) && (x === v.clientHeight || R === N.clientHeight)) | |
| } | |
| } | |
| } | |
| for (l = 0; l < c; ++l) | |
| e[l].element.candidateElement = null | |
| } | |
| return !1 | |
| }, | |
| shouldDisqualifyForDeepLinking : function() { | |
| const e = 5; | |
| for (var t = this.element, n = this.contentDocument.location, r = pathComponentsForAnchor(n).length, i = [], a = t.getElementsByTagName("a"), o = a.length, l = 0; l < o; l++) { | |
| var s = a[l]; | |
| if (n.host === s.host && !(pathComponentsForAnchor(s).length <= r || 0 !== (s.host + s.pathname).indexOf(n.host + n.pathname) || anchorLinksToAttachment(s) || (i.push(s), i.length < e))) { | |
| var c = t.offsetTop + t.offsetHeight / e; | |
| return i[0].offsetTop < c | |
| } | |
| } | |
| return !1 | |
| } | |
| }, | |
| String.prototype.lastInteger = function() { | |
| const e = /[0-9]+/g; | |
| var t = this.match(e); | |
| return t ? parseInt(t[t.length - 1]) : NaN | |
| }; | |
| ReaderArticleFinder = function(e) { | |
| this.contentDocument = e, this.didSearchForArticleNode = !1, this.didChangeContentDocumentToFrameOnPage = !1, this.article = null, this.didSearchForExtraArticleNode = !1, this.extraArticle = null, this._leadingMediaElement = null, this._isMediaWikiPage = void 0, this._cachedScrollY = 0, this._cachedScrollX = 0, this._elementsWithCachedBoundingRects = [], this._cachedContentTextStyle = null, this.pageNumber = 1, this.prefixWithDateForNextPageURL = null, this.previouslyDiscoveredPageURLStrings = [], this.candidateElementFilter = { | |
| minimumWidth : 280, | |
| minimumHeight : 295, | |
| minimumArea : 17e4, | |
| maxTop : 1300 | |
| }; | |
| let t = 0; | |
| this._nextUniqueID = function() { | |
| return t++ + "" | |
| }, this._mapOfUniqueIDToOriginalElement = new Map, this._weakMapOfOriginalElementToUniqueID = new WeakMap | |
| }, ReaderArticleFinder.prototype = { | |
| setCandidateElementFilter : function(e) { | |
| let [t, n] = this._validityAndValidCandidateElementFilterFromFilter(e); | |
| t && (this.candidateElementFilter = n) | |
| }, | |
| _validityAndValidCandidateElementFilterFromFilter : function(e) { | |
| let t = {}, | |
| n = !1; | |
| for (let i of ["minimumWidth", "minimumHeight", "minimumArea", "maxTop"]) { | |
| let r = (e || {})[i]; | |
| if (void 0 === r || "number" != typeof r || r < 0) { | |
| t = {}, n = !1; | |
| break | |
| } | |
| t[i] = r, n = !0 | |
| } | |
| return [ n, t ] | |
| }, | |
| pointsForDominantIframeHitTest : function() { | |
| const e = 60; | |
| return [ | |
| [ e, e ], | |
| [ window.innerWidth - e, e ], | |
| [ e, window.innerHeight - e ], | |
| [ window.innerWidth - e, window.innerHeight - e ] | |
| ] | |
| }, | |
| dominantContentIframe : function() { | |
| let e, t = this.pointsForDominantIframeHitTest(), | |
| n = t.length; | |
| for (let i = 0; i < n; i++) { | |
| if (cornerElement = document.elementFromPoint(t[i][0], t[i][1]), !cornerElement || "IFRAME" !== cornerElement.tagName) | |
| return null; | |
| if (e) { | |
| if (e !== cornerElement) | |
| return null | |
| } else | |
| e = cornerElement | |
| } | |
| return e | |
| }, | |
| checkForIframeCoveringMostOfWebpage : function() { | |
| let e = this.dominantContentIframe(); | |
| e && !this.didChangeContentDocumentToFrameOnPage && (this.contentDocument = e.contentDocument, this.resetArticleInformation(), this.didChangeContentDocumentToFrameOnPage = !0) | |
| }, | |
| isReaderModeAvailable : function() { | |
| return this.setSuppressBoundingRectCalculationForSkippedElements(!0), this.checkForIframeCoveringMostOfWebpage(), !!this.findArticleBySearchingQuirksList() || (this.cacheWindowScrollPosition(), !!this.findArticleFromMetadata(FindArticleMode.ExistenceOfElement) || (this.article = this.findArticleByVisualExamination(), this.article && this.articleIsLTR(), !!this.article)) | |
| }, | |
| resetArticleInformation : function() { | |
| this.didSearchForArticleNode = !1, this.didSearchForExtraArticleNode = !1, delete this.article, delete this.extraArticle, delete this._articleTitleInformation, delete this._articleTitleElement, delete this._leadingMediaElement, delete this._cachedContentTextStyle, delete this._adoptableArticle, delete this._articleIsLTR, delete this._nextPageURL, delete this._cachedScrollY, delete this._cachedScrollX, clearCachedElementBoundingRects() | |
| }, | |
| reset : function() { | |
| this.resetArticleInformation(), this.prepareToTransitionToReader() | |
| }, | |
| prepareToTransitionToReader : function() { | |
| this.adoptableArticle(!0), this.nextPageURL(), this.articleIsLTR() | |
| }, | |
| nextPageURL : function() { | |
| if (!this._nextPageURL) { | |
| var e = this.nextPageURLString(); | |
| "undefined" != typeof ReaderArticleFinderJSController && e && (e = ReaderArticleFinderJSController.substituteURLForNextPageURL(e)), this._nextPageURL = e | |
| } | |
| return this._nextPageURL | |
| }, | |
| containerElementsForMultiPageContent : function() { | |
| const e = /(.*page[^0-9]*|.*article.*item[^0-9]*)(\d{1,2})(.*)/i, | |
| t = 3; | |
| for (var n, i = [], r = this.articleNode(), a = 0; !(n = e.exec(r.getAttribute("id")));) | |
| if (!(r = r.parentElement) || a++ === t) | |
| return []; | |
| for (var l = childrenOfParentElement(r), o = l.length, s = 0; s < o; ++s) { | |
| var c = l[s]; | |
| if (c !== r) { | |
| var m = e.exec(c.getAttribute("id")); | |
| m && m[1] === n[1] && m[3] === n[3] && (isElementVisible(c) && !isElementPositionedOffScreen(c) || i.push(c)) | |
| } | |
| } | |
| return i | |
| }, | |
| adoptableMultiPageContentElements : function() { | |
| return this.containerElementsForMultiPageContent().map((function(e) { | |
| return this.cleanArticleNode(e, e.cloneNode(!0), CleaningType.MainArticleContent, !1) | |
| }), | |
| this) | |
| }, | |
| classNameIsSignificantInRouteComputation : function(e) { | |
| return !!e && !(e.toLowerCase() in StylisticClassNames) | |
| }, | |
| shouldIgnoreInRouteComputation : function(e) { | |
| let t = normalizedElementTagName(e); | |
| return "script" === t || "link" === t || "style" === t || "tr" === t && !e.offsetHeight | |
| }, | |
| routeToArticleNode : function() { | |
| for (var e = [], t = this.articleNode(); t;) { | |
| var n = {}; | |
| n.tagName = normalizedElementTagName(t); | |
| var i = t.getAttribute("id"); | |
| i && (n.id = i), this.classNameIsSignificantInRouteComputation(t.className) && (n.className = t.className), n.index = 1; | |
| for (var r = t.previousElementSibling; r; r = r.previousElementSibling) | |
| this.shouldIgnoreInRouteComputation(r) || n.index++; | |
| e.unshift(n), t = t.parentElement | |
| } | |
| return e | |
| }, | |
| adjustArticleNodeUpwardIfNecessary : function() { | |
| if (!this.article) | |
| return; | |
| var e = this.article.element; | |
| if (!e.parentElement) | |
| return; | |
| for (var t = e; t; t = t.parentElement) | |
| if (VeryPositiveClassNameRegEx.test(t.className)) | |
| return void (this.article.element = t); | |
| if ("header" === normalizedElementTagName(e) && "article" === normalizedElementTagName(e.parentElement)) | |
| return void (this.article.element = e.parentElement); | |
| var n = e.previousElementSibling; | |
| if (n && "figure" === normalizedElementTagName(n) && "article" === normalizedElementTagName(e.parentElement)) | |
| return void (this.article.element = e.parentElement); | |
| var i = "section" === normalizedElementTagName(e) ? e : nearestAncestorElementWithTagName(e, "section", [ "article" ]); | |
| if (i) { | |
| var r = i.parentElement, | |
| a = function() { | |
| for (var e = r.children, t = e.length, n = 0; n < t; ++n) { | |
| var a = e[n], | |
| l = normalizedElementTagName(a); | |
| if (a !== i && ("section" === l || "header" === l)) | |
| return !0 | |
| } | |
| return !1 | |
| }(); | |
| if (a && (/\barticleBody\b/.test(r.getAttribute("itemprop")) || "main" === normalizedElementTagName(r) || "main" === r.getAttribute("role") || "article" === normalizedElementTagName(r) || r === this.contentDocument.body || r.classList.contains("entry-content"))) | |
| return void (this.article.element = r) | |
| } | |
| const l = /intro/i, | |
| o = /body|content/i; | |
| if (e = this.article.element, l.test(e.className) && e.nextElementSibling && o.test(e.nextElementSibling.className) || o.test(e.className) && e.previousElementSibling && l.test(e.previousElementSibling.className)) | |
| return void (this.article.element = e.parentElement); | |
| if ("article" !== normalizedElementTagName(e)) { | |
| var s = e.parentElement.closest("*[itemprop='articleBody']"); | |
| if (s && s.parentElement.closest(SchemaDotOrgArticleContainerSelector)) | |
| return void (this.article.element = s) | |
| } | |
| var c = e.closest("article"); | |
| if (c) { | |
| e = unwrappedArticleContentElement(e); | |
| var m, d = elementDepth(e); | |
| "p" !== normalizedElementTagName(e) || e.className || (e = e.parentElement, d--), e.classList.length ? 1 === (m = elementsMatchingClassesInClassListIgnoringCommonLayoutClassNames(e.classList, this.contentDocument)).length && (m = elementsMatchingClassesInClassListIgnoringClassesWithNumericSuffix(e.classList, this.contentDocument)) : m = e.parentElement.children; | |
| for (var h = m.length, u = 0; u < h; ++u) { | |
| var g = m[u]; | |
| if (e !== g && d === elementDepth(g) && (isElementVisible(g) && !g.querySelector("article") && Object.keys(e.dataset).join() === Object.keys(g.dataset).join() && dominantFontFamilyAndSizeForElement(e) === dominantFontFamilyAndSizeForElement(g))) | |
| return void (this.article.element = c) | |
| } | |
| } | |
| let f = this.findExtraArticle(), | |
| p = f ? f.element : null; | |
| if (p && p.parentElement && e.parentElement === p.parentElement && ArticleRegEx.test(e.parentElement.className)) { | |
| if (dominantFontFamilyAndSizeForElement(e) === dominantFontFamilyAndSizeForElement(p)) | |
| return void (this.article.element = e.parentElement) | |
| } | |
| let E = e.parentElement; | |
| if (elementIsCommentBlock(e) && !elementIsCommentBlock(E) && ArticleRegEx.test(E.className)) { | |
| let e = CandidateElement.candidateIfElementIsViable(E, this.contentDocument, !0); | |
| if (e && e.finalScore() >= ReaderMinimumScore) | |
| return void (this.article.element = E) | |
| } | |
| if (!(e = this.article.element).getAttribute("id") && e.className) { | |
| var v = normalizedElementTagName(e), | |
| T = e.className, | |
| y = e.parentElement; | |
| if (y) | |
| for (var S = y.children, A = (u = 0, S.length); u < A; ++u) { | |
| var N = S[u]; | |
| if (N !== e && (normalizedElementTagName(N) === v && N.className === T)) { | |
| var b = CandidateElement.candidateIfElementIsViable(N, this.contentDocument, !0); | |
| if (b && !(b.finalScore() < ReaderMinimumScore)) | |
| return void (this.article.element = y) | |
| } | |
| } | |
| } | |
| }, | |
| findArticleBySearchingQuirksList : function() { | |
| var e, t = this.contentDocument; | |
| return findArticleNodeSelectorsInQuirksListForHostname(t.location.hostname, (function(n) { | |
| var i = t.querySelectorAll(n); | |
| if (1 === i.length) | |
| return e = new CandidateElement(i[0], t), !0 | |
| })), | |
| e | |
| }, | |
| articleNode : function(e) { | |
| return this.checkForIframeCoveringMostOfWebpage(), this.didSearchForArticleNode || (this.article = this.findArticleBySearchingQuirksList(), this.article || (this.article = this.findArticleBySearchingAllElements()), this.article || (this.article = this.findArticleByVisualExamination()), this.article || (this.article = this.findArticleFromMetadata()), !this.article && e && (this.article = this.findArticleBySearchingAllElements(!0)), this.didSearchForArticleNode = !0, this.adjustArticleNodeUpwardIfNecessary(), this.article && (this.article.element = unwrappedArticleContentElement(this.article.element)), this.article && this.articleIsLTR()), this.article ? this.article.element : null | |
| }, | |
| extraArticleNode : function() { | |
| return this.didSearchForArticleNode || this.articleNode(), this.didSearchForExtraArticleNode || (this.extraArticle = this.findExtraArticle(), this.didSearchForExtraArticleNode = !0), this.extraArticle ? this.extraArticle.element : null | |
| }, | |
| cacheWindowScrollPosition : function() { | |
| this._cachedScrollY = window.scrollY, this._cachedScrollX = window.scrollX | |
| }, | |
| contentTextStyle : function() { | |
| return this._cachedContentTextStyle || (this._cachedContentTextStyle = contentTextStyleForNode(this.contentDocument, this.articleNode()), this._cachedContentTextStyle || (this._cachedContentTextStyle = getComputedStyle(this.articleNode()))), this._cachedContentTextStyle | |
| }, | |
| commaCountIsLessThan : function(e, t) { | |
| for (var n = 0, i = e.textContent, r = -1; n < t && (r = i.indexOf(",", r + 1)) >= 0;) | |
| n++; | |
| return n < t | |
| }, | |
| calculateLinkDensityForPruningElement : function(e, t) { | |
| var n = removeWhitespace(e.textContent).length; | |
| if (!n) | |
| return 0; | |
| for (var i = this.article.element, r = function() { | |
| for (var t = e.originalElement; t && t !== i; t = t.parentElement) | |
| if ("none" !== getComputedStyle(t).float) | |
| return t; | |
| return null | |
| }(), a = e.getElementsByTagName("a"), l = 0, o = a.length, s = 0; s < o; ++s) { | |
| var c = a[s]; | |
| !r && c.href && t && t === dominantFontFamilyAndSizeForElement(c.originalElement) || (l += removeWhitespace(c.textContent).length) | |
| } | |
| return l / n | |
| }, | |
| shouldPruneElement : function(e, t, n) { | |
| const i = .33, | |
| r = .5, | |
| a = .2, | |
| l = 25, | |
| o = 4e4; | |
| let s = normalizedElementTagName(e); | |
| if (!e.parentElement) | |
| return !1; | |
| if (t.classList.contains("footnotes")) | |
| return !1; | |
| if (e.querySelector(".tweet-wrapper")) | |
| return !1; | |
| if ("figure" === normalizedElementTagName(e.parentElement) && e.querySelector("img")) | |
| return !1; | |
| if ("iframe" === s) | |
| return shouldPruneIframe(e); | |
| if ("canvas" !== s) { | |
| for (var c = !1, m = e.childNodes.length, d = 0; d < m; ++d) { | |
| var h = e.childNodes[d], | |
| u = h.nodeType; | |
| if (u === Node.ELEMENT_NODE || u === Node.TEXT_NODE && !isNodeWhitespace(h)) { | |
| c = !0; | |
| break | |
| } | |
| } | |
| if (!c) { | |
| if ("p" === s) { | |
| var g = e.previousSibling, | |
| f = e.nextSibling; | |
| if (g && g.nodeType === Node.TEXT_NODE && !isNodeWhitespace(g) && f && f.nodeType === Node.TEXT_NODE && !isNodeWhitespace(f)) | |
| return !1 | |
| } | |
| return !0 | |
| } | |
| if ("p" === s) | |
| return !1 | |
| } | |
| if ("canvas" === s) | |
| return window.innerWidth === t.width && window.innerHeight === t.height || (!(!ProgressiveLoadingRegex.test(t.className) || "img" !== normalizedElementTagName(t.nextElementSibling)) || (!!canvasElementHasNoUserVisibleContent(t) || "cufon" === normalizedElementTagName(e.parentNode))); | |
| if (e.closest("figure") && e.querySelector("picture")) | |
| return !1; | |
| var p = 0; | |
| if (t) { | |
| if (VeryNegativeClassNameRegEx.test(t.className)) | |
| return !0; | |
| var E = t.className, | |
| v = t.getAttribute("id"); | |
| PositiveRegEx.test(E) && p++, PositiveRegEx.test(v) && p++, NegativeRegEx.test(E) && p--, NegativeRegEx.test(v) && p-- | |
| } | |
| let T = this.isMediaWikiPage(); | |
| if (p < 0 && !T) | |
| return !0; | |
| if (elementIsProtected(e)) | |
| return !1; | |
| if ("ul" === s || "ol" === s) { | |
| if (t.querySelector("iframe") && t.querySelector("script")) | |
| return !0; | |
| var y = t.children, | |
| S = y.length; | |
| if (!S && !/\S/.test(e.innerText)) | |
| return !0; | |
| var A = 0, | |
| N = 0; | |
| for (d = 0; d < S; ++d) { | |
| var b = y[d]; | |
| if (SharingRegex.test(b.className)) | |
| A++; | |
| else { | |
| var x = b.children; | |
| 1 === x.length && SharingRegex.test(x[0].className) && A++ | |
| } | |
| NegativeRegEx.test(y[d].className) && N++ | |
| } | |
| return A / S >= MinimumRatioOfListItemsBeingRelatedToSharingToPruneEntireList || N / S >= MinimumRatioOfListItemsBeingRelatedToSharingToPruneEntireList | |
| } | |
| if (1 === e.childElementCount) { | |
| var C = e.firstElementChild; | |
| if ("a" === normalizedElementTagName(C)) | |
| return !1; | |
| if ("span" === normalizedElementTagName(C) && "converted-anchor" === C.className && nearestAncestorElementWithTagName(C, "table")) | |
| return !1 | |
| } | |
| var D = e.getElementsByTagName("img"), | |
| I = D.length; | |
| if (I) { | |
| var M = 0; | |
| for (d = 0; d < I; ++d) { | |
| var L = D[d].originalElement; | |
| if (isElementVisible(L)) { | |
| var R = cachedElementBoundingRect(L); | |
| M += R.width / I * (R.height / I) | |
| } | |
| } | |
| if (M > o) | |
| return !1 | |
| } | |
| if (!this.commaCountIsLessThan(e, 10)) | |
| return !1; | |
| var w = e.getElementsByTagName("p").length, | |
| F = e.getElementsByTagName("br").length, | |
| _ = w + Math.floor(F / 2); | |
| if (I > _ && "table" !== s) | |
| return !0; | |
| if (!e.closest("table") && !e._originalElementDepthInCollapsedArea && !T) { | |
| if (e.getElementsByTagName("li").length > _ && dominantFontFamilyAndSizeForElement(t.querySelector("li")) !== n) | |
| return !0; | |
| if (e.textContent.length < l && 1 !== I) | |
| return !0; | |
| let i = this.calculateLinkDensityForPruningElement(e, n); | |
| if (p >= 1 && i > r) | |
| return !0; | |
| if (p < 1 && i > a) | |
| return !0 | |
| } | |
| if (e.getElementsByTagName("input").length / _ > i) | |
| return !0; | |
| if ("table" === s) { | |
| if (removeWhitespace(e.innerText).length <= .5 * removeWhitespace(t.innerText).length) | |
| return !0; | |
| if (T && t.classList.contains("toc")) | |
| return !0 | |
| } | |
| return !1 | |
| }, | |
| wordCountIsLessThan : function(e, t) { | |
| for (var n = 0, i = e.textContent, r = -1; | |
| (r = i.indexOf(" ", r + 1)) >= 0 && n < t;) | |
| n++; | |
| return n < t | |
| }, | |
| leadingMediaIsAppropriateWidth : function(e) { | |
| return !(!this.article || !e) && e.getBoundingClientRect().width >= this.article.element.getBoundingClientRect().width - ToleranceForLeadingMediaWidthToArticleWidthForFullWidthPresentation | |
| }, | |
| newDivFromNode : function(e) { | |
| var t = this.contentDocument.createElement("div"); | |
| return e && (t.innerHTML = e.innerHTML), t | |
| }, | |
| headerElement : function() { | |
| if (!this.article) | |
| return null; | |
| var e = this.article.element.previousElementSibling; | |
| if (e && "header" === normalizedElementTagName(e)) | |
| return e; | |
| var t = this._articleTitleElement; | |
| if (!t) | |
| return null; | |
| var n = t.parentElement; | |
| if (n && "header" === normalizedElementTagName(n) && !this.article.element.contains(n)) | |
| for (var i = n.querySelectorAll("img"), r = i.length, a = 0; a < r; ++a) { | |
| var l = i[a], | |
| o = cachedElementBoundingRect(l); | |
| if (o.width >= MainImageMinimumWidthAndHeight && o.height >= MainImageMinimumWidthAndHeight) | |
| return n | |
| } | |
| return null | |
| }, | |
| adoptableLeadingMedia : function() { | |
| if (!this.article || !this._leadingMediaElement || !this.leadingMediaIsAppropriateWidth(this._leadingMediaElement)) | |
| return null; | |
| var e = this._leadingMediaElement.closest("figure"); | |
| if (e) | |
| return this.cleanArticleNode(e, e.cloneNode(!0), CleaningType.LeadingMedia, !0); | |
| if ("img" !== normalizedElementTagName(this._leadingMediaElement)) | |
| return this.cleanArticleNode(this._leadingMediaElement, this._leadingMediaElement.cloneNode(!0), CleaningType.LeadingMedia, !0); | |
| const t = 5, | |
| n = /credit/, | |
| i = /caption/, | |
| r = /src|alt/; | |
| var a = this._leadingMediaElement.parentNode, | |
| l = null, | |
| o = null, | |
| s = a.children.length; | |
| if ("div" === normalizedElementTagName(a) && s > 1 && s < t) | |
| for (var c = a.cloneNode(!0).querySelectorAll("p, div"), m = c.length, d = 0; d < m; ++d) { | |
| var h = c[d]; | |
| n.test(h.className) ? l = h.cloneNode(!0) : i.test(h.className) && (o = h.cloneNode(!0)) | |
| } | |
| var u = this._leadingMediaElement.cloneNode(!1), | |
| g = lazyLoadingImageURLForElement(u, u.className); | |
| g && u.setAttribute("src", g), !g && u.hasAttribute("src") || !u.hasAttribute("data-srcset") || u.setAttribute("srcset", u.getAttribute("data-srcset")); | |
| var f = attributesForElement(u); | |
| for (d = 0; d < f.length; ++d) { | |
| var p = f[d].nodeName; | |
| r.test(p) || (u.removeAttribute(p), d--) | |
| } | |
| var E = this.contentDocument.createElement("div"); | |
| if (E.className = "leading-image", E.appendChild(u), l) { | |
| var v = this.newDivFromNode(l); | |
| v.className = "credit", E.appendChild(v) | |
| } | |
| if (o) { | |
| var T = this.newDivFromNode(o); | |
| T.className = "caption", E.appendChild(T) | |
| } | |
| return E | |
| }, | |
| articleBoundingRect : function() { | |
| return this._articleBoundingRect || (this._articleBoundingRect = cachedElementBoundingRect(this.article.element)), this._articleBoundingRect | |
| }, | |
| adoptableArticle : function(e) { | |
| if (this._adoptableArticle) | |
| return this._adoptableArticle.cloneNode(!0); | |
| this.setSuppressBoundingRectCalculationForSkippedElements(!1), clearCachedElementBoundingRects(), this.cacheWindowScrollPosition(); | |
| var t = this.articleNode(e); | |
| if (this._adoptableArticle = t ? t.cloneNode(!0) : null, !this._adoptableArticle) | |
| return this._adoptableArticle; | |
| if (this._adoptableArticle = this.cleanArticleNode(t, this._adoptableArticle, CleaningType.MainArticleContent, !1), "p" === normalizedElementTagName(this._adoptableArticle)) { | |
| var n = document.createElement("div"); | |
| n.appendChild(this._adoptableArticle), this._adoptableArticle = n | |
| } | |
| var i = this.extraArticleNode(); | |
| if (i) { | |
| var r = this.cleanArticleNode(i, i.cloneNode(!0), CleaningType.MainArticleContent, !0); | |
| r ? this.extraArticle.isPrepended ? this._adoptableArticle.insertBefore(r, this._adoptableArticle.firstChild) : this._adoptableArticle.appendChild(r) : i = null; | |
| var a = cachedElementBoundingRect(this.article.element), | |
| l = cachedElementBoundingRect(this.extraArticle.element), | |
| o = { | |
| top : Math.min(a.top, l.top), | |
| right : Math.max(a.right, l.right), | |
| bottom : Math.max(a.bottom, l.bottom), | |
| left : Math.min(a.left, l.left) | |
| }; | |
| o.width = o.right - o.left, o.height = o.bottom - o.top, this._articleBoundingRect = o | |
| } | |
| this._articleTextContent = this._adoptableArticle.innerText; | |
| var s = this.headerElement(); | |
| if (this._leadingMediaElement && (!s || !s.contains(this._leadingMediaElement))) { | |
| var c = this.adoptableLeadingMedia(); | |
| c && this._adoptableArticle.insertBefore(c, this._adoptableArticle.firstChild) | |
| } | |
| var m = !!s; | |
| if (m && i && (i === s && (m = !1), m)) { | |
| var d = i.compareDocumentPosition(s); | |
| (d & Node.DOCUMENT_POSITION_CONTAINS || d & Node.DOCUMENT_POSITION_CONTAINED_BY) && (m = !1) | |
| } | |
| if (m) { | |
| var h = this.cleanArticleNode(s, s.cloneNode(!0), CleaningType.MainArticleContent, !0); | |
| h && this._adoptableArticle.insertBefore(h, this._adoptableArticle.firstChild) | |
| } | |
| return this._adoptableArticle | |
| }, | |
| dominantContentSelectorAndDepth : function(e) { | |
| var t, n = {}, | |
| i = {}; | |
| walkElementSubtree(e, 2, (function(e, t) { | |
| if (isElementVisible(e)) { | |
| var r = selectorForElement(e) + " | " + t; | |
| i[r] ? i[r] += 1 : (i[r] = 1, n[r] = e) | |
| } | |
| })); | |
| var r = arrayOfKeysAndValuesOfObjectSortedByValueDescending(i); | |
| switch (r.length) { | |
| case 0: | |
| break; | |
| case 1: | |
| t = r[0].key; | |
| break; | |
| default: | |
| var a = r[0]; | |
| a.value > r[1].value && (t = a.key) | |
| } | |
| if (!t) | |
| return null; | |
| var l = n[t]; | |
| return | |
| { | |
| selector: selectorForElement(l), | |
| depth: depthOfElementWithinElement(l, e) | |
| } | |
| }, | |
| functionToPreventPruningElementDueToInvisibility : function() { | |
| return functionToPreventPruningDueToInvisibilityInQuirksListForHostname(this.contentDocument.location.hostname) || function() { | |
| return !1 | |
| } | |
| }, | |
| cleanArticleNode : function(e, t, n, i) { | |
| function r(e) | |
| { | |
| v += e, T && (T += e), y && (y += e), S && (S += e), A && (A += e), N && (N += e) | |
| } | |
| function a() | |
| { | |
| 1 === T && (T = 0), 1 === y && (y = 0), 1 === S && (S = 0), 1 === A && (A = 0), 1 === N && (N = 0) | |
| } | |
| function l() | |
| { | |
| const t = .8; | |
| var n = cachedElementBoundingRect(e); | |
| if (0 === n.width || 0 === n.height) | |
| return !0; | |
| var i, r = childrenWithParallelStructure(e), | |
| a = r.length; | |
| if (a) { | |
| i = []; | |
| for (var l = 0; l < a; ++l) { | |
| var o = r[l]; | |
| if ("none" === getComputedStyle(o).float) | |
| for (var s = o.children, c = s.length, m = 0; m < c; ++m) | |
| i.push(s[m]); | |
| else | |
| i.push(o) | |
| } | |
| } else | |
| i = e.children; | |
| var d = i.length, | |
| h = 0; | |
| for (l = 0; l < d; ++l) { | |
| var u = i[l]; | |
| "none" !== getComputedStyle(u).float && (h += u.innerText.length) | |
| } | |
| return h / e.innerText.length > t | |
| } | |
| function o(t) | |
| { | |
| const n = 50; | |
| if (cachedElementBoundingRect(t).height > n) | |
| return !1; | |
| return !!new Set([ "ul", "li", "nav" ]).has(normalizedElementTagName(t)) || t.parentElement === e && !t.nextElementSibling | |
| } | |
| function s(e, t) | |
| { | |
| const n = .9; | |
| return !(cachedElementBoundingRect(e).height > n * cachedElementBoundingRect(t).height) | |
| } | |
| function c(e, t) | |
| { | |
| const n = 1.1, | |
| i = 1.4; | |
| t && H && (e.matches(HeaderElementsSelector) || (t > i * H || V.test(b.className) && t > n * H) && !e.closest(".pullquote") && (e.classList.add("pullquote"), e.classList.contains("float") || (e.style.width = null, cleanStyleAndClassList(e)))) | |
| } | |
| function m(e, t) | |
| { | |
| for (var n = e[t]; n; n = n[t]) | |
| if (!isNodeWhitespace(n) && n.nodeType !== Node.COMMENT_NODE) | |
| return !1; | |
| return !0 | |
| } | |
| const d = new Set([ "form", "script", "style", "link", "button", "object", "embed", "applet" ]), | |
| h = new Set([ "div", "table", "ul", "canvas", "p", "iframe", "aside", "section", "footer", "nav", "ol", "menu", "svg" ]), | |
| u = new Set([ "i", "em" ]), | |
| g = new Set([ "b", "strong", "h1", "h2", "h3", "h4", "h5", "h6" ]), | |
| f = new Set([ "i-amphtml-sizer" ]), | |
| p = /lightbox/i; | |
| var E = [], | |
| v = 0, | |
| T = 0, | |
| y = 0, | |
| S = 0, | |
| A = 0, | |
| N = 0, | |
| b = e, | |
| x = b.ownerDocument.defaultView, | |
| C = t, | |
| D = this.articleTitle(), | |
| I = this._articleTitleElement, | |
| M = (this.articleSubhead(), this._articleSubheadElement), | |
| L = I && cachedElementBoundingRect(I).top > cachedElementBoundingRect(e).bottom, | |
| R = isElementVisible(e), | |
| w = new Set([ I, M ]), | |
| F = new Set; | |
| if (n === CleaningType.MainArticleContent) { | |
| this.updateArticleBylineAndDateElementsIfNecessary(); | |
| var _ = this.articleBylineElement(); | |
| _ && F.add(_); | |
| var O = this.articleDateElement(); | |
| O && F.add(O) | |
| } | |
| var B = this.dominantContentSelectorAndDepth(e), | |
| P = l(), | |
| k = new Set; | |
| this.previouslyDiscoveredPageURLStrings.forEach((function(e) { | |
| k.add(e) | |
| })); | |
| var q = this.nextPageURL(); | |
| q && k.add(q); | |
| var z = null; | |
| this._articleTitleElement && (z = cachedElementBoundingRect(this._articleTitleElement)); | |
| var W = this.functionToPreventPruningElementDueToInvisibility(), | |
| U = dominantFontFamilyAndSizeForElement(e), | |
| H = dominantFontSizeInPointsFromFontFamilyAndSizeString(U); | |
| const V = /pull(ed)?quote/i; | |
| for (var j = [], G = [], X = [], Y = [], K = []; b;) { | |
| try { | |
| var Q, J = null, | |
| $ = normalizedElementTagName(C), | |
| Z = !1, | |
| ee = elementLooksLikeDropCap(b); | |
| if (C.originalElement = b, !N && elementAppearsToBeCollapsed(b) && (N = 1), (d.has($) || this.isAMPPage() && f.has($)) && (J = C), !J && b !== e && w.has(b) ? J = C : !J && b !== e && F.has(b) ? (C.parentElementBeforePruning = C.parentElement, J = C, j.push(C)) | |
| : elementIsAHeader(C) && previousLeafElementForElement(b) === I && C.classList.add("protected"), | |
| "twitter-widget" === $ && C.classList.add("protected"), !J && ("h1" === $ || "h2" === $)) | |
| if (b.offsetTop - e.offsetTop < HeaderMinimumDistanceFromArticleTop) { | |
| var te = trimmedInnerTextIgnoringTextTransform(b), | |
| ne = te.length * HeaderLevenshteinDistanceToLengthRatio; | |
| levenshteinDistance(D, te) <= ne && (J = C) | |
| } | |
| if (J || this.isMediaWikiPage() && /editsection|icon-edit|edit-page|mw-empty-elt/.test(b.className) && (J = C), "video" === $) | |
| if (C.getAttribute("src")) { | |
| C.classList.add("protected"); | |
| var ie = cachedElementBoundingRect(b); | |
| C.setAttribute("width", ie.width), C.setAttribute("height", ie.height), C.removeAttribute("style"); | |
| b.hasAttribute("autoplay") && b.hasAttribute("muted") && b.hasAttribute("loop") ? C.setAttribute("data-reader-silent-looped-animation", "") : (C.setAttribute("controls", !0), C.removeAttribute("autoplay"), C.removeAttribute("preload")) | |
| } else | |
| J = C; | |
| J || (Q = getComputedStyle(b)); | |
| let t = function() { | |
| if ("div" !== $ && "span" !== $) | |
| return !1; | |
| if (LazyLoadRegex.test(b.className)) | |
| return !0; | |
| for (let e of attributesForElement(b)) | |
| if (/^data-/.test(e.name) && LazyLoadRegex.test(e.value) && cachedElementBoundingRect(b).height) | |
| return !0; | |
| return !1 | |
| }(); | |
| if (!J && t && (!b.innerText || b.previousElementSibling && "noscript" === normalizedElementTagName(b.previousElementSibling))) | |
| if (Ie = lazyLoadingImageURLForElement(C, b.className)) { | |
| var re = this.contentDocument.createElement("img"); | |
| re.setAttribute("src", Ie), C.parentNode.replaceChild(re, C), (C = re).originalElement = b, $ = normalizedElementTagName(C), J = C, C.classList.add("protected") | |
| } | |
| if (!J && "img" !== $ && /img/.test($)) { | |
| lazyLoadingImageURLForElement(C, b.className) && ((C = changeElementType(C, "img")).originalElement = b, $ = "img") | |
| } | |
| if (!J && "div" === $ && C.parentNode) { | |
| var ae = b.querySelectorAll("a, blockquote, dl, div, img, ol, p, pre, table, ul"), | |
| le = T || "none" !== Q.float, | |
| oe = null; | |
| if (le || ae.length ? elementIndicatesItIsASchemaDotOrgImageObject(b) && !C.querySelector("figure, .auxiliary") ? oe = "figure" : ee && (oe = "span") : oe = "p", oe) { | |
| for (var se = C.parentNode, ce = this.contentDocument.createElement(oe); C.firstChild;) { | |
| var me = C.firstChild; | |
| ce.appendChild(me) | |
| } | |
| se.replaceChild(ce, C), (C = ce).originalElement = b, $ = normalizedElementTagName(C) | |
| } | |
| } | |
| if (b.dataset && b.dataset.mathml && b.querySelector("math") && X.push(C), !J && C.parentNode && h.has($) && (C._originalElementDepthInCollapsedArea = N, E.push(C)), J || (isElementPositionedOffScreen(b) ? J = C : b === e || T || "none" === Q.float || P || !(cachedElementBoundingRect(b).height >= FloatMinimumHeight || b.childElementCount > 1) || (T = 1)), !J) { | |
| if (sanitizeElementByRemovingAttributes(C), n === CleaningType.MetadataContent) | |
| if ("|" === C.innerText) | |
| C.innerText = "", C.classList.add("delimiter"); | |
| else if ("time" === normalizedElementTagName(C)) { | |
| var de = C.previousElementSibling; | |
| if (de && "span" === normalizedElementTagName(de) && !de.classList.contains("delimiter")) { | |
| var he = this.contentDocument.createElement("span"); | |
| he.classList.add("delimiter"), C.before(he) | |
| } | |
| } else | |
| "figure" === $ && (J = C); | |
| if ("both" === Q.clear && C.classList.add("clear"), "ul" === $ || "ol" === $ || "menu" === $) { | |
| if (z && !N && cachedElementBoundingRect(b).top < z.top) | |
| J = C; | |
| else if ("none" === Q["list-style-type"] && "none" === Q["background-image"]) { | |
| for (var ue = b.children, ge = ue.length, fe = !0, pe = 0; pe < ge; ++pe) { | |
| var Ee = ue[pe], | |
| ve = getComputedStyle(Ee); | |
| if ("none" !== ve["list-style-type"] || 0 !== parseInt(ve["-webkit-padding-start"])) { | |
| fe = !1; | |
| break | |
| } | |
| var Te = getComputedStyle(Ee, ":before").content; | |
| if (/\u2022|\u25e6|\u2023|\u2219|counter/.test(Te)) { | |
| fe = !1; | |
| break | |
| } | |
| } | |
| fe && C.classList.add("list-style-type-none") | |
| } | |
| if (b.querySelector("code")) { | |
| const e = /monospace|menlo|courier/i; | |
| var ye = dominantFontFamilyAndSizeForElement(b); | |
| e.test(ye) && (C.classList.add("code-block"), C.classList.add("protected")) | |
| } | |
| } | |
| if (S || "normal" === Q.fontStyle || (u.has($) || C.style && (C.style.fontStyle = Q.fontStyle), S = 1), !A && "normal" !== Q.fontWeight) { | |
| if (!g.has($)) { | |
| var Se = parseInt(Q.fontWeight), | |
| Ae = null; | |
| isNaN(Se) ? Ae = Q.fontWeight : Se <= 400 || Se >= 500 && (Ae = "bold"), Ae && C.style && (C.style.fontWeight = Ae) | |
| } | |
| A = 1 | |
| } | |
| if (T && "section" !== $ && s(b, e) || "aside" === $) { | |
| ye = dominantFontFamilyAndSizeForElement(b); | |
| var Ne = dominantFontSizeInPointsFromFontFamilyAndSizeString(ye), | |
| be = ye && ye === U; | |
| if (1 !== T || ee || (cachedElementBoundingRect(b).width <= MaximumFloatWidth ? C.setAttribute("class", "auxiliary float " + Q.float) : be || C.classList.add("auxiliary")), C.closest(".auxiliary") && b.style) { | |
| var xe = b.style.getPropertyValue("width"); | |
| if ("table" === Q.display && /%/.test(xe) && parseInt(xe) < 2) | |
| C.style.width = Q.width; | |
| else if (xe) | |
| C.style.width = xe; | |
| else { | |
| var Ce = x.getMatchedCSSRules(b, "", !0); | |
| if (Ce) | |
| for (pe = Ce.length - 1; pe >= 0; --pe) { | |
| xe = Ce[pe].style.getPropertyValue("width"); | |
| var De = parseInt(xe); | |
| if (xe && (isNaN(De) || De > 0)) { | |
| C.style.width = xe; | |
| break | |
| } | |
| } | |
| } | |
| 1 !== T || xe || (C.style.width = cachedElementBoundingRect(b).width + "px") | |
| } | |
| ee || c(C, Ne) | |
| } | |
| if ("table" === $) | |
| y || (y = 1); | |
| else if ("img" === $) { | |
| var Ie; | |
| if (Ie = lazyLoadingImageURLForElement(C, b.className)) { | |
| C.setAttribute("src", Ie); | |
| var Me = !!C.closest("figure"); | |
| if (!Me) { | |
| var Le = attributesForElement(b), | |
| Re = Le.length; | |
| for (pe = 0; pe < Re; ++pe) | |
| if (p.test(Le[pe].nodeName)) { | |
| Me = !0; | |
| break | |
| } | |
| } | |
| Me && C.classList.add("protected"), Z = !0 | |
| } | |
| !Ie && C.hasAttribute("src") || !b.hasAttribute("data-srcset") || C.setAttribute("srcset", b.getAttribute("data-srcset")), C.removeAttribute("border"), C.removeAttribute("hspace"), C.removeAttribute("vspace"); | |
| var we = C.getAttribute("align"); | |
| if (C.removeAttribute("align"), "left" !== we && "right" !== we || (C.classList.add("float"), C.classList.add(we)), !T && !Z) { | |
| var Fe, _e = (Fe = cachedElementBoundingRect(b)).width, | |
| Oe = Fe.height; | |
| hasClassMatchingRegexp(b, ProgressiveLoadingRegex) && b.nextElementSibling && "img" === normalizedElementTagName(b.nextElementSibling) ? J = C : imageIsContainedByContainerWithImageAsBackgroundImage(b) ? C.classList.add("protected") | |
| : 1 === _e&& 1 === Oe || z&& Oe < MinimumHeightForImagesAboveTheArticleTitle&& Fe.bottom < z.top ? J = C | |
| : _e < ImageSizeTiny && Oe < ImageSizeTiny && C.setAttribute("class", "reader-image-tiny") | |
| } | |
| if (n === CleaningType.MetadataContent) | |
| ((Fe = cachedElementBoundingRect(b)).width > MaximumWidthOrHeightOfImageInMetadataSection || Fe.height > MaximumWidthOrHeightOfImageInMetadataSection) && (J = C); | |
| if (b.classList.contains("emoji")) { | |
| let e = urlFromString(C.src); | |
| if (e && "s.w.org" === e.hostname && e.pathname.startsWith("/images/core/emoji/")) { | |
| let e = this.replaceImageWithAltText(C); | |
| e && ((C = e).originalElement = b, $ = normalizedElementTagName(C), J = C, C.classList.add("protected")) | |
| } | |
| } | |
| } else if ("font" === $) | |
| C.removeAttribute("size"), C.removeAttribute("face"), C.removeAttribute("color"); | |
| else if ("a" === $ && C.parentNode) { | |
| let e, t; | |
| C instanceof HTMLAnchorElement ? (e = C.getAttribute("href"), t = HTMLAnchorElement) : C instanceof SVGAElement && (e = C.getAttribute("xlink:href"), t = SVGAElement); | |
| let i = C.originalElement.ownerDocument.location, | |
| r = urlStringShouldHaveItsAnchorMadeNonFunctional(e, i); | |
| if (t === HTMLAnchorElement && "author" === b.getAttribute("itemprop")) | |
| C.classList.add("protected"); | |
| else if (e && e.length && ("#" === e[0] || r)) { | |
| const e = new Set([ "li", "sup" ]); | |
| if (!y && !C.childElementCount && 1 === C.parentElement.childElementCount && !e.has(normalizedElementTagName(C.parentElement))) | |
| this.contentDocument.evaluate("text()", C.parentElement, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotLength || (J = C); | |
| if (!J) { | |
| ce = this.contentDocument.createElement("span"); | |
| if (1 === C.childElementCount && "img" === normalizedElementTagName(C.firstElementChild)) { | |
| var Be = C.firstElementChild; | |
| Be.width > AnchorImageMinimumWidth && Be.height > AnchorImageMinimumHeight && ce.setAttribute("class", "converted-image-anchor") | |
| } | |
| for (ce.className || ce.setAttribute("class", "converted-anchor"); C.firstChild;) | |
| ce.appendChild(C.firstChild); | |
| C.parentNode.replaceChild(ce, C), (C = ce).originalElement = b | |
| } | |
| } else if (AdvertisementHostRegex.test(C.host) && !C.innerText) | |
| J = C; | |
| else if (n !== CleaningType.MetadataContent && I && !L && I.compareDocumentPosition(b) & document.DOCUMENT_POSITION_PRECEDING && cachedElementBoundingRect(b).top < cachedElementBoundingRect(I).top) | |
| G.push(C); | |
| else { | |
| var Pe = b.children; | |
| 1 === Pe.length && "img" === normalizedElementTagName(Pe[0]) && !b.innerText && anchorLooksLikeDownloadFlashLink(b) && (J = C) | |
| } | |
| r && (C.removeAttribute("xlink:href"), C.removeAttribute("href")) | |
| } else if ("aside" === $ || "blockquote" === $ || "q" === $ || "div" === $ && V.test(b.className)) { | |
| ye = dominantFontFamilyAndSizeForElement(b), Ne = dominantFontSizeInPointsFromFontFamilyAndSizeString(ye); | |
| ee || c(C, Ne) | |
| } else if ("cite" === $) { | |
| var ke = pseudoElementContent(b, ":after") ?? "", | |
| qe = document.createElement("span"); | |
| qe.innerText = ke, C.after(qe) | |
| } else | |
| "pre" === $ ? C.style.whiteSpace = Q.whiteSpace : "source" === $ && b.hasAttribute("data-srcset") ? (C.setAttribute("srcset", b.getAttribute("data-srcset")), C.classList.add("protected")) | |
| : C instanceof SVGAnimateElement && "xlink:href" === C.attributes.attributeName.value && (J = C) | |
| } | |
| if (Q && R && !Z) { | |
| var ze = "none" === Q.display || "visible" !== Q.visibility || computedStyleIndicatesElementIsInvisibleDueToClipping(Q); | |
| if (ze || "img" === $ || (ze = "0" === Q.opacity && "absolute" === Q.position && !C.closest("figure")), ze && !N) | |
| !!B && (v === B.depth && selectorForElement(b) === B.selector) || W(b, e) || (J = C) | |
| } | |
| if (!J && elementIsCommentBlock(b) && (J = C), !J && z && cachedElementBoundingRect(b).top < z.top && VeryLiberalCommentRegex.test(b.className) && C.parentElement && (J = C), !J && "a" === $ && k.has(b.href)) { | |
| for (var We, Ue, He = b, Ve = C; | |
| (He = He.parentElement) && (Ve = Ve.parentElement);) { | |
| const t = 10; | |
| if (cachedElementBoundingRect(He).top - cachedElementBoundingRect(b).top > t) | |
| break; | |
| if (He === e) | |
| break; | |
| o(He) && (We = He, Ue = Ve) | |
| } | |
| We && (J = Ue, b = We, (C = Ue).originalElement = b, $ = normalizedElementTagName(C)), He = null, Ve = null, We = null, Ue = null | |
| } | |
| } catch (e) { | |
| J = C | |
| } | |
| if (!J || J.parentElement || i || (J = null), "div" === $ ? Y.push(C) : "aside" === $ && K.push(C), !J) { | |
| let e = this._weakMapOfOriginalElementToUniqueID.get(C.originalElement); | |
| e || (e = this._nextUniqueID()), this._mapOfUniqueIDToOriginalElement.set(e, C.originalElement), C.setAttribute(this.elementReaderUniqueIDAttributeKey(), e), this._weakMapOfOriginalElementToUniqueID.set(C.originalElement, e) | |
| } | |
| var je = J ? null : b.firstElementChild; | |
| if (je) | |
| b = je, C = C.firstElementChild, r(1); | |
| else { | |
| for (var Ge; b !== e && !(Ge = b.nextElementSibling);) | |
| b = b.parentElement, C = C.parentElement, r(-1); | |
| if (b === e) { | |
| if (J && !elementIsProtected(J)) | |
| if (J.parentElement) | |
| J.remove(); | |
| else if (i) | |
| return null; | |
| break | |
| } | |
| b = Ge, C = C.nextElementSibling, a() | |
| } | |
| if (J && !elementIsProtected(J)) | |
| if (J.parentElement) | |
| J.remove(); | |
| else if (i) | |
| return null | |
| } | |
| for (let e of t.querySelectorAll("iframe")) { | |
| if (elementLooksLikeEmbeddedTweet(e.originalElement)) | |
| (Xe = this.adoptableSimpleTweetFromTwitterElement(e)) && e.parentElement.replaceChild(Xe, e); | |
| e.classList.add("protected"), e.setAttribute("sandbox", "allow-scripts allow-same-origin") | |
| } | |
| for (let e of t.querySelectorAll("twitter-widget")) { | |
| var Xe; | |
| if (elementLooksLikeEmbeddedTweet(e.originalElement)) | |
| (Xe = this.adoptableSimpleTweetFromTwitterElement(e)) && e.parentElement.replaceChild(Xe, e); | |
| e.classList.add("protected") | |
| } | |
| const Ye = t.querySelectorAll("blockquote"), | |
| Ke = Ye.length; | |
| for (pe = 0; pe < Ke; ++pe) { | |
| const e = Ye[pe], | |
| t = e.originalElement; | |
| t && this.convertBlockquoteTweetToSimpleTweetIfAppropriate(e, t) | |
| } | |
| for (pe = E.length - 1; pe >= 0; --pe) { | |
| (vt = E[pe]).parentNode && this.shouldPruneElement(vt, vt.originalElement, U) && vt.remove(), delete vt._originalElementDepthInCollapsedArea | |
| } | |
| var Qe = G.length; | |
| for (pe = 0; pe < Qe; ++pe) | |
| G[pe].remove(); | |
| var Je = t.querySelectorAll(".float"); | |
| for (pe = 0; pe < Je.length; ++pe) { | |
| var $e = !1, | |
| Ze = Je[pe]; | |
| if (!$e) { | |
| var et = Ze.querySelectorAll("a, span.converted-image-anchor"), | |
| tt = Ze.querySelectorAll("span.converted-anchor"); | |
| $e = Ze.parentNode && tt.length > et.length | |
| } | |
| if (!$e) { | |
| var nt = Ze.querySelectorAll("embed, object").length, | |
| it = Ze.originalElement.querySelectorAll("embed, object").length; | |
| !nt && it && ($e = !0) | |
| } | |
| if (!$e) { | |
| for (var rt = Ze.originalElement.getElementsByTagName("img"), at = rt.length, lt = 0, ot = 0; ot < at && (R && isElementVisible(rt[ot]) && lt++, !(lt > 1)); ++ot) | |
| ; | |
| if (1 === lt) | |
| Ze.getElementsByTagName("img").length || ($e = !0) | |
| } | |
| if (!$e) { | |
| const e = "img, video, embed, iframe, object, svg"; | |
| /\S/.test(Ze.innerText) || Ze.matches(e) || Ze.querySelector(e) || ($e = !0) | |
| } | |
| $e && !elementIsProtected(Ze) && Ze.remove() | |
| } | |
| var st = t.querySelectorAll("br"); | |
| for (pe = st.length - 1; pe >= 0; --pe) { | |
| var ct = st[pe]; | |
| ct.originalElement && "block" === getComputedStyle(ct.originalElement.parentElement).display && (m(ct, "nextSibling") || m(ct, "previousSibling")) && ct.remove() | |
| } | |
| if (i && !removeWhitespace(t.innerText).length && (n !== CleaningType.LeadingMedia || !t.querySelector("video, iframe, img"))) | |
| return null; | |
| var mt = {}, | |
| dt = (et = t.querySelectorAll("a")).length; | |
| for (pe = 0; pe < dt; ++pe) { | |
| mt[ht = (ft = et[pe]).style.fontWeight] || (mt[ht] = []), mt[ht].push(ft) | |
| } | |
| for (var ht in mt) { | |
| var ut = mt[ht], | |
| gt = ut.length; | |
| if (gt > .7 * dt) | |
| for (pe = 0; pe < gt; ++pe) { | |
| var ft; | |
| (ft = ut[pe]).style.fontWeight = null, ft.getAttribute("style") || ft.removeAttribute("style") | |
| } | |
| } | |
| var pt = t.querySelectorAll(".protected"), | |
| Et = pt.length; | |
| for (pe = 0; pe < Et; ++pe) { | |
| var vt; | |
| (vt = pt[pe]).classList.remove("protected"), vt.classList.length || vt.removeAttribute("class") | |
| } | |
| var Tt = t.querySelectorAll("p.auxiliary"), | |
| yt = Tt.length; | |
| for (pe = 0; pe < yt; ++pe) { | |
| for (var St = Tt[pe], At = [ St ], Nt = St.nextElementSibling; Nt && "p" === normalizedElementTagName(Nt) && Nt.classList.contains("auxiliary");) | |
| At.push(Nt), Nt = Nt.nextElementSibling; | |
| var bt = At.length; | |
| if (bt > 1) { | |
| for (ot = 0; ot < bt; ++ot) { | |
| var xt = At[ot]; | |
| xt.classList.remove("auxiliary"), xt.style && (xt.style.width = null), cleanStyleAndClassList(xt) | |
| } | |
| pe += bt - 1 | |
| } | |
| } | |
| for (pe = Y.length - 1; pe >= 0; --pe) { | |
| var Ct = Y[pe]; | |
| Ct !== t && elementWouldAppearBetterAsFigureOrAuxiliary(Ct.originalElement, Ct) && changeElementType(Ct, "figure") | |
| } | |
| for (pe = K.length - 1; pe >= 0; --pe) { | |
| var Dt = K[pe]; | |
| Dt !== t && elementWouldAppearBetterAsFigureOrAuxiliary(Dt.originalElement, Dt) && Dt.classList.add("auxiliary") | |
| } | |
| var It = j.length; | |
| for (pe = 0; pe < It; ++pe) { | |
| var Mt = j[pe], | |
| Lt = Mt.parentElementBeforePruning, | |
| Rt = null, | |
| wt = null; | |
| if (Lt) | |
| Rt = depthOfElementWithinElement(Lt, t), wt = selectorForElement(Lt); | |
| var Ft = Lt ? Lt.closest("ul") : null; | |
| if (Ft) | |
| Ft.remove(); | |
| else { | |
| const e = 40; | |
| Lt && cachedElementBoundingRect(Lt.originalElement).height < e && (!B || B.selector !== wt || B.depth !== Rt) ? Lt.remove() : Mt.remove() | |
| } | |
| } | |
| var _t = X.length; | |
| for (pe = 0; pe < _t; ++pe) { | |
| var Ot = X[pe], | |
| Bt = this.contentDocument.createElement("div"); | |
| Bt.innerHTML = Ot.dataset ? Ot.dataset.mathml : "", Ot.parentNode.replaceChild(Bt, Ot) | |
| } | |
| return t | |
| }, | |
| convertBlockquoteTweetToSimpleTweetIfAppropriate : function(e, t) { | |
| const n = t.classList; | |
| if (!n.contains("twitter-tweet") && !n.contains("twitter-video")) | |
| return; | |
| const i = t.getElementsByTagName("a"), | |
| r = i.length; | |
| if (r < 1) | |
| return; | |
| const a = i[r - 1]; | |
| if ("twitter.com" !== a.host) | |
| return; | |
| const l = lastPathComponentFromAnchor(a); | |
| if (isNaN(parseInt(l))) | |
| return; | |
| const o = this.contentDocument.createElement("div"); | |
| o.setAttribute("data-reader-tweet-id", l), o.classList.add("tweet-wrapper"), e.parentElement.replaceChild(o, e), e.classList.add("simple-tweet"), o.appendChild(e) | |
| }, | |
| adoptableSimpleTweetFromTwitterElement : function(e) { | |
| var t = function(e) { | |
| var t = this.contentDocument.createElement("div"), | |
| n = this.contentDocument.createTextNode(e); | |
| return t.appendChild(n), t.innerHTML | |
| }.bind(this); | |
| let n = null, | |
| i = e.originalElement; | |
| if ("iframe" === normalizedElementTagName(e) ? n = i.contentDocument ? i.contentDocument.documentElement : null : "twitter-widget" === normalizedElementTagName(e) && (n = i.shadowRoot), !n) | |
| return null; | |
| var r = n.querySelector("[data-tweet-id].expanded") || n.querySelector("[data-tweet-id]"); | |
| if (!r) | |
| return null; | |
| var a = this.contentDocument.createElement("div"); | |
| a.classList.add("tweet-wrapper"); | |
| var l = this.contentDocument.createElement("blockquote"); | |
| l.classList.add("simple-tweet"), a.appendChild(l); | |
| var o = r.getAttribute("data-tweet-id"); | |
| a.setAttribute("data-reader-tweet-id", o); | |
| var s = r.querySelector(".dateline"), | |
| c = r.querySelector('[data-scribe="element:screen_name"]'), | |
| m = r.querySelector('[data-scribe="element:name"]'), | |
| d = r.querySelector(".e-entry-title"); | |
| if (!(s && c && m && d)) | |
| return a; | |
| var h = "— " + t(m.innerText) + " (" + t(c.innerText) + ")", | |
| u = this.contentDocument.createElement("p"); | |
| u.innerHTML = d.innerHTML, l.appendChild(u), l.insertAdjacentHTML("beforeend", h); | |
| var g = this.contentDocument.createElement("span"); | |
| g.innerHTML = s.innerHTML, l.appendChild(g); | |
| for (let e of l.querySelectorAll("img.twitter-emoji")) | |
| this.replaceImageWithAltText(e); | |
| for (var f = l.getElementsByTagName("*"), p = f.length, E = 0; E < p; ++E) { | |
| e = f[E]; | |
| "script" === normalizedElementTagName(e) ? e.remove() : sanitizeElementByRemovingAttributes(e) | |
| } | |
| return a | |
| }, | |
| replaceImageWithAltText : function(e) { | |
| var t = e.getAttribute("alt"); | |
| if (!t || t.length < 1) | |
| return null; | |
| let n = this.contentDocument.createElement("span"); | |
| return n.innerText = t, e.parentNode.replaceChild(n, e), n | |
| }, | |
| leadingVideoNode : function() { | |
| var e = this.leadingContentNodeWithSelector("video, iframe"); | |
| return e && e.parentElement && !e.previousElementSibling && !e.nextElementSibling ? e.parentElement : null | |
| }, | |
| leadingImageNode : function() { | |
| return this.leadingContentNodeWithSelector("figure img, img") | |
| }, | |
| ancestorsOfElement : function(e) { | |
| let t = [], | |
| n = e.parentNode; | |
| for (; n;) | |
| t.push(n), n = n.parentNode; | |
| return t | |
| }, | |
| leadingContentNodeWithSelector : function(e) { | |
| const t = 250, | |
| n = .5, | |
| i = .9, | |
| r = 3; | |
| if (!this.article || !this.article.element) | |
| return null; | |
| let a = 0; | |
| if (this._articleTitleElement) { | |
| let e, t = this.ancestorsOfElement(this.article.element); | |
| for (let n of t) | |
| if (n.contains(this._articleTitleElement)) { | |
| e = n; | |
| break | |
| } | |
| a = t.length - this.ancestorsOfElement(e).length + 2 | |
| } | |
| let l = Math.max(r, a); | |
| for (var o = this.article.element, s = 0; s < l && o.parentNode; ++s) { | |
| var c = (o = o.parentNode).querySelectorAll(e); | |
| for (var m of c) | |
| if (m && isElementVisible(m)) { | |
| var d = cachedElementBoundingRect(m); | |
| if (!(d.width >= window.innerWidth * i) && d.height < t) | |
| continue; | |
| if (d.width < this._articleWidth * n) | |
| continue; | |
| var h = this.article.element.compareDocumentPosition(m); | |
| if (!(h & Node.DOCUMENT_POSITION_PRECEDING) || h & Node.DOCUMENT_POSITION_CONTAINED_BY) | |
| continue; | |
| var u = this.extraArticle ? this.extraArticle.element : null; | |
| if (u && this.article.element.compareDocumentPosition(u) & Node.DOCUMENT_POSITION_FOLLOWING && (h = u.compareDocumentPosition(m)) && (!(h & Node.DOCUMENT_POSITION_PRECEDING) || h & Node.DOCUMENT_POSITION_CONTAINED_BY)) | |
| continue; | |
| return m | |
| } | |
| } | |
| return null | |
| }, | |
| pageImageURLFromMetadata : function(e) { | |
| var t = e["property:og:image"]; | |
| if (t || (t = e["property:twitter:image"]), t || (t = e["property:twitter:image:src"]), t) { | |
| let e = urlFromString(t); | |
| if (e) { | |
| let n = e.href; | |
| n && urlIsHTTPFamilyProtocol(e) && (t = n) | |
| } | |
| } | |
| return t | |
| }, | |
| mainImageNode : function() { | |
| var e = this.leadingImageNode(); | |
| if (e) | |
| return e; | |
| if (this.article && this.article.element) | |
| for (var t = this.article.element.querySelectorAll("img"), n = t.length, i = 0; i < n; ++i) { | |
| var r = t[i], | |
| a = r._cachedElementBoundingRect; | |
| if (a || (a = r.getBoundingClientRect()), a.width >= MainImageMinimumWidthAndHeight && a.height >= MainImageMinimumWidthAndHeight) | |
| return r | |
| } | |
| return null | |
| }, | |
| schemaDotOrgMetadataObjectForArticle : function() { | |
| if (this._schemaDotOrgMetadataObjectForArticle) | |
| return this._schemaDotOrgMetadataObjectForArticle; | |
| const e = new Set([ "Article", "NewsArticle", "Report", "ScholarlyArticle", "SocialMediaPosting", "BlogPosting", "LiveBlogPosting", "DiscussionForumPosting", "TechArticle", "APIReference" ]); | |
| var t = this.contentDocument.querySelectorAll("script[type='application/ld+json']"), | |
| n = t.length; | |
| try { | |
| for (var i = 0; i < n; ++i) { | |
| var r = t[i], | |
| a = JSON.parse(r.textContent), | |
| l = a["@context"]; | |
| if ("https://schema.org" === l || "http://schema.org" === l) { | |
| var o = a["@type"]; | |
| if (e.has(o)) | |
| return this._schemaDotOrgMetadataObjectForArticle = a, a | |
| } | |
| } | |
| return null | |
| } catch (e) { | |
| return null | |
| } | |
| }, | |
| articleTitle : function() { | |
| var e = this.articleTitleInformation(); | |
| return e ? e.titleText : "" | |
| }, | |
| articleTitleInformation : function() { | |
| function e(e, t) | |
| { | |
| var n = e ? t.indexOf(e) : -1; | |
| return -1 !== n && (0 === n || n + e.length === t.length) | |
| } | |
| function t(e, t) | |
| { | |
| return e.host === t.host && e.pathname === t.pathname && e.hash === t.hash | |
| } | |
| function n(e) | |
| { | |
| let t = nearestAncestorElementWithTagName(e, "a") || e.querySelector("a"); | |
| return t ? urlStringShouldHaveItsAnchorMadeNonFunctional(t.href, t.ownerDocument.location) ? null : t : null | |
| } | |
| if (!this.articleNode()) | |
| return; | |
| if (this._articleTitleInformation) | |
| return this._articleTitleInformation; | |
| const i = /((article|post).*title|headline|instapaper_title|inside-head)/i, | |
| r = 600, | |
| a = 20, | |
| l = 8, | |
| o = 1.1, | |
| s = 1.25, | |
| c = /header|title|headline|instapaper_title/i, | |
| m = 1.5, | |
| d = 1.8, | |
| h = 1.5, | |
| u = .6, | |
| g = 3, | |
| f = 1.5, | |
| p = .8, | |
| E = .8, | |
| v = 9, | |
| T = 1.5, | |
| y = /byline|author/i; | |
| var S = function(e, t) { | |
| var n = this.contentFromUniqueMetadataSelector(e, t); | |
| if (n) { | |
| var i = this.articleTitleAndSiteNameFromTitleString(n); | |
| i && (n = i.articleTitle) | |
| } | |
| return n | |
| }.bind(this), A = function() { | |
| for (var e = this.articleNode(); e; e = e.parentElement) | |
| if (elementIndicatesItIsASchemaDotOrgArticleContainer(e)) | |
| return e; | |
| return null | |
| }.bind(this)(), N = A ? this.contentFromUniqueMetadataSelector(A, "meta[itemprop=headline]") : "", b = A ? this.contentFromUniqueMetadataSelector(A, "meta[itemprop=alternativeHeadline]") : "", x = this.contentDocument, C = x.location, D = x.title, I = S(x, "meta[property='og:title']"), M = this.contentFromUniqueMetadataSelector(x, "meta[property='og:site_name']"), L = S(x, "meta[name='twitter:title']"), R = S(x, "meta[name='sailthru.headline']"), w = this.schemaDotOrgMetadataObjectForArticle(), F = w ? w.headline : null, _ = this.articleNode(), O = cachedElementBoundingRect(_); | |
| this.extraArticleNode() && this.extraArticle.isPrepended && (O = cachedElementBoundingRect(this.extraArticleNode())); | |
| var B = O.left + O.width / 2, | |
| P = O.top, | |
| k = P; | |
| (this._articleWidth = O.width, this._leadingMediaElement = this.leadingImageNode(), this._leadingMediaElement || (this._leadingMediaElement = this.leadingVideoNode()), this._leadingMediaElement) && (k = (cachedElementBoundingRect(this._leadingMediaElement).top + P) / 2); | |
| var q = "h1, h2, h3, h4, h5, a:not(svg a), p, div, span", | |
| z = normalizedElementTagName(this.article.element); | |
| "dl" !== z && "dd" !== z || (q += ", dt"); | |
| for (var W = [], U = x.querySelectorAll(q), H = U.length, V = 0; V < H; ++V) { | |
| var j = U[V], | |
| G = normalizedElementTagName(j); | |
| if ("a" === G) | |
| j.innerText === I && t(j, C) && (j.previousElementSibling || j.nextElementSibling ? W.push(j) : W.push(j.parentElement)); | |
| else if ("div" === G || "span" === G || "p" === G) { | |
| if (hasClassMatchingRegexp(j, i) || i.test(j.getAttribute("id"))) { | |
| var X = j.parentElement; | |
| elementIsAHeader(X) || W.push(j) | |
| } | |
| } else | |
| W.push(j) | |
| } | |
| W = Array.prototype.slice.call(W, 0); | |
| const Y = 2; | |
| var K = this.article.element; | |
| for (V = 0; V < Y; ++V) | |
| K.parentElement && (K = K.parentElement); | |
| for (var Q, J = K.querySelectorAll("a:not(svg a)"), $ = (V = 0, J.length); V < $; ++V) { | |
| var Z = J[V]; | |
| if (Z.offsetTop > _.offsetTop + a) | |
| break; | |
| if (t(Z, C) && "#" !== Z.getAttribute("href")) { | |
| W.push(Z); | |
| break | |
| } | |
| } | |
| var ee = W.map(trimmedInnerTextIgnoringTextTransform), | |
| te = W.length, | |
| ne = 0, | |
| ie = [], | |
| re = [], | |
| ae = [], | |
| le = [], | |
| oe = [], | |
| se = [], | |
| ce = []; | |
| const me = {}, | |
| de = e => { | |
| const t = me[e]; | |
| if (t) | |
| return t; | |
| const n = stringSimilarity(D, e); | |
| return me[e] = n, n | |
| }; | |
| for (V = 0; V < te; ++V) { | |
| var he = W[V], | |
| ue = ee[V]; | |
| const e = {}, | |
| t = t => { | |
| const n = e[t]; | |
| if (n) | |
| return n; | |
| const i = stringSimilarity(ue, t); | |
| return e[t] = i, i | |
| }; | |
| let n = de(ue); | |
| if (I) { | |
| const e = t(I); | |
| n += e, e > StringSimilarityToDeclareStringsNearlyIdentical && re.push(he) | |
| } | |
| if (L) { | |
| const e = t(L); | |
| n += e, e > StringSimilarityToDeclareStringsNearlyIdentical && ae.push(he) | |
| } | |
| if (N) { | |
| const e = t(N); | |
| n += e, e > StringSimilarityToDeclareStringsNearlyIdentical && le.push(he) | |
| } | |
| if (b) { | |
| const e = t(b); | |
| n += e, e > StringSimilarityToDeclareStringsNearlyIdentical && oe.push(he) | |
| } | |
| if (R) { | |
| const e = t(R); | |
| n += e, e > StringSimilarityToDeclareStringsNearlyIdentical && se.push(he) | |
| } | |
| if (F) { | |
| const e = t(F); | |
| n += e, e > StringSimilarityToDeclareStringsNearlyIdentical && ce.push(he) | |
| } | |
| n === ne ? ie.push(he) : n > ne && (ne = n, ie = [ he ]) | |
| } | |
| let ge = []; | |
| for (let e of W) { | |
| let t = e.nextElementSibling; | |
| t && SubheadRegex.test(t.className) && ge.push(e) | |
| } | |
| if (1 === re.length ? (Q = re[0]).headerText = trimmedInnerTextIgnoringTextTransform(Q) : 1 === ae.length ? (Q = ae[0]).headerText = trimmedInnerTextIgnoringTextTransform(Q) | |
| : 1 === le.length ? (Q = le[0]).headerText = trimmedInnerTextIgnoringTextTransform(Q) | |
| : 1 === se.length ? (Q = se[0]).headerText = trimmedInnerTextIgnoringTextTransform(Q) | |
| : 1 === ce.length && ((Q = ce[0]).headerText = trimmedInnerTextIgnoringTextTransform(Q)), | |
| !Q) | |
| for (V = 0; V < te; ++V) { | |
| he = W[V]; | |
| if (!isElementVisible(he)) | |
| continue; | |
| var fe = cachedElementBoundingRect(he), | |
| pe = fe.left + fe.width / 2, | |
| Ee = pe - B, | |
| ve = fe.top + fe.height / 2 - k, | |
| Te = -1 !== re.indexOf(he), | |
| ye = -1 !== ae.indexOf(he), | |
| Se = he.classList.contains("instapaper_title"), | |
| Ae = /\bheadline\b/.test(he.getAttribute("itemprop")), | |
| Ne = -1 !== le.indexOf(he), | |
| be = -1 !== oe.indexOf(he), | |
| xe = -1 !== se.indexOf(he), | |
| Ce = -1 !== ce.indexOf(he); | |
| let t = ge.includes(he) && ve < 0; | |
| var De = Te || ye || Se || Ae || Ne || be || xe || Ce || t, | |
| Ie = Math.sqrt(Ee * Ee + ve * ve), | |
| Me = De ? r : Math.max(r - Ie, 0), | |
| Le = (ue = ee[V], he.getAttribute("property")); | |
| if (Le) { | |
| var Re = /dc.title/i.exec(Le); | |
| if (Re && Re[0]) | |
| if (1 === this.contentDocument.querySelectorAll('*[property~="' + Re[0] + '"]').length) { | |
| (Q = he).headerText = ue; | |
| break | |
| } | |
| } | |
| if (!y.test(he.className)) { | |
| if (!De) { | |
| if (Ie > r) | |
| continue; | |
| if (pe < O.left || pe > O.right) | |
| continue | |
| } | |
| if (D && stringsAreNearlyIdentical(ue, D)) | |
| Me *= g; | |
| else if (e(ue, D)) | |
| Me *= f; | |
| else if (ue.length < l) | |
| continue; | |
| if (ue !== M || !I) { | |
| var we = !1; | |
| if (We = n(he)) { | |
| if ("author" === We.getAttribute("rel")) | |
| continue; | |
| var Fe = We.host === C.host, | |
| _e = We.pathname === C.pathname; | |
| if (Fe && _e) | |
| Me *= h; | |
| else { | |
| if (Fe && nearestAncestorElementWithTagName(he, "li")) | |
| continue; | |
| Me *= u, we = !0 | |
| } | |
| } | |
| var Oe = fontSizeFromComputedStyle(getComputedStyle(he)); | |
| we || (Me *= Oe / BaseFontSize), Me *= 1 + TitleCandidateDepthScoreMultiplier * elementDepth(he); | |
| var Be = parseInt(this.contentTextStyle().fontSize); | |
| parseInt(Oe) > Be * o && (Me *= s), (c.test(he.className) || c.test(he.getAttribute("id"))) && (Me *= m); | |
| var Pe = he.parentElement; | |
| Pe && (c.test(Pe.className) || c.test(Pe.getAttribute("id"))) && (Me *= m), -1 !== ie.indexOf(he) && (Me *= d); | |
| _ = this.article.element; | |
| for (var ke = he; ke && ke !== _; ke = ke.parentElement) | |
| if (SidebarRegex.test(ke.className)) { | |
| Me *= p; | |
| break | |
| } | |
| he.closest("li") && (Me *= E), (!Q || Me > Q.headerScore) && ((Q = he).headerScore = Me, Q.headerText = ue) | |
| } | |
| } | |
| } | |
| var qe; | |
| if (Q && domDistance(Q, _, v + 1) > v && parseInt(getComputedStyle(Q).fontSize) < T * Be && (Q = null), Q) { | |
| this._articleTitleElement = Q; | |
| var ze = Q.headerText.trim(); | |
| qe = I && e(I, ze) ? I : D && e(D, ze) ? D | |
| : ze | |
| } | |
| this._leadingMediaElement || (this._leadingMediaElement = this.leadingImageNode()), this._leadingMediaElement || (this._leadingMediaElement = this.leadingVideoNode()), qe || (qe = I && e(I, D) ? I : D); | |
| var We, Ue = null, | |
| He = !1, | |
| Ve = !1; | |
| Q && ((We = n(Q)) && (Ue = We.href, He = "_blank" === We.getAttribute("target"), Ve = We.host !== C.host || We.pathname !== C.pathname)); | |
| let je = { | |
| titleText : qe, | |
| linkURL : Ue, | |
| linkIsTargetBlank : He, | |
| linkIsForExternalPage : Ve | |
| }; | |
| if (this._articleTitleElement) { | |
| const e = this.titleUniqueID(); | |
| this._mapOfUniqueIDToOriginalElement.set(e, Q), this._weakMapOfOriginalElementToUniqueID.set(Q, e) | |
| } | |
| return this._articleTitleInformation = je, je | |
| }, | |
| contentFromUniqueMetadataSelector : function(e, t) { | |
| var n = e.querySelectorAll(t); | |
| if (1 !== n.length) | |
| return null; | |
| var i = n[0]; | |
| return i ? this.elementAttributesContainImproperQuote(i) ? null : i.content : null | |
| }, | |
| elementAttributesContainImproperQuote : function(e) { | |
| for (var t = attributesForElement(e), n = t.length, i = 0; i < n; ++i) | |
| if (/['"]/.test(t[i].name)) | |
| return !0; | |
| return !1 | |
| }, | |
| articleSubhead : function() { | |
| function e(e) | |
| { | |
| return elementIsAHeader(e) ? parseInt(/h(\d)?/.exec(normalizedElementTagName(e))[1]) : NaN | |
| } | |
| function t(e) | |
| { | |
| if (!e) | |
| return null; | |
| var t = e.content; | |
| return t ? t.trim() : null | |
| } | |
| const n = /author|kicker/i; | |
| if (this._articleSubhead) | |
| return this._articleSubhead; | |
| var i = this.articleNode(); | |
| if (!i) | |
| return; | |
| var r = this._articleTitleElement; | |
| if (!r) | |
| return; | |
| var a = this.contentDocument, | |
| l = a.location, | |
| o = e(r), | |
| s = cachedElementBoundingRect(r), | |
| c = new Set, | |
| m = t(a.querySelector("meta[property='og:description']")); | |
| m && c.add(m); | |
| var d = t(a.querySelector("meta[name=description]")); | |
| d && c.add(d); | |
| var h, u = this.schemaDotOrgMetadataObjectForArticle(); | |
| if (u) { | |
| var g = u.description; | |
| g && "string" == typeof g && c.add(g.trim()) | |
| } | |
| var f = this.contentFromUniqueMetadataSelector(a, "head meta.swiftype[name=dek]"); | |
| f && (h = f); | |
| let p = [], | |
| E = nextNonFloatingVisibleElementSibling(r); | |
| E && p.push(E); | |
| let v = nextLeafElementForElement(r); | |
| if (v && r && r.contains(v) && v.innerText && v.innerText.trim() === r.innerText.trim() && (v = nextLeafElementForElement(v)), v && p.push(v), c.size) | |
| for (var T = a.querySelectorAll(HeaderElementsSelector + ", *[itemprop=description]"), y = T.length, S = 0; S < y; ++S) { | |
| var A = T[S]; | |
| c.has(A.innerText.trim()) && p.push(A) | |
| } | |
| var N = p.length; | |
| for (S = 0; S < N; ++S) { | |
| var b = p[S]; | |
| if (!b) | |
| continue; | |
| if (b === i) | |
| continue; | |
| var x = b.className; | |
| if (n.test(x)) | |
| continue; | |
| var C = b.closest("a"); | |
| if (C) { | |
| var D = C.host === l.host, | |
| I = C.pathname === l.pathname; | |
| if (!D || !I) | |
| continue | |
| } | |
| var M, L = !1; | |
| if (elementIsAHeader(b)) | |
| if (isNaN(o)) | |
| L = !0; | |
| else | |
| e(b) - 1 === o && (L = !0); | |
| if (!L && SubheadRegex.test(x) && (L = !0), !L) { | |
| const e = b.getAttribute("itemprop"); | |
| /\bdescription\b/.test(e) && !/\barticleBody\b/.test(e) && (L = !0) | |
| } | |
| if (!L && c.has(b.innerText) && (L = !0), !L && h && h === b.innerText && (L = !0), L || "summary" !== b.getAttribute("itemprop") || (L = !0), !L) | |
| continue; | |
| if ("meta" === normalizedElementTagName(b)) { | |
| var R = b.getAttribute("content"); | |
| M = R ? R.trim() : ""; | |
| var w = b.nextElementSibling; | |
| if (!w || trimmedInnerTextIgnoringTextTransform(w) !== M) | |
| continue; | |
| b = w | |
| } else { | |
| if (cachedElementBoundingRect(b).top < (s.bottom + s.top) / 2) | |
| continue; | |
| M = trimmedInnerTextIgnoringTextTransform(b).trim() | |
| } | |
| if (!M.length) | |
| continue; | |
| this._articleSubheadElement = b; | |
| const t = this.subheadUniqueID(); | |
| this._mapOfUniqueIDToOriginalElement.set(t, b), this._weakMapOfOriginalElementToUniqueID.set(b, t), this._articleSubhead = M; | |
| break | |
| } | |
| return this._articleSubhead | |
| }, | |
| adoptableMetadataBlock : function() { | |
| function e(e) | |
| { | |
| function t(e, i) | |
| { | |
| if (e.nodeType !== Node.TEXT_NODE) { | |
| if (e.nodeType === Node.ELEMENT_NODE) { | |
| var r = e.childNodes, | |
| a = r.length; | |
| 0 !== a && (1 !== a ? (i !== n.Right && t(r[0], n.Left), i !== n.Left && t(r[a - 1], n.Right)) : t(r[0], i)) | |
| } | |
| } else | |
| i === n.Left ? e.textContent = e.textContent.trimLeft() : i === n.Right ? e.textContent = e.textContent.trimRight() | |
| : e.textContent = e.textContent.trim() | |
| } | |
| const n = { | |
| Left : 1, | |
| Right : 2, | |
| Both : 3 | |
| }; | |
| t(e) | |
| } | |
| this.updateArticleBylineAndDateElementsIfNecessary(); | |
| var t = this.articleBylineElement(), | |
| n = this.articleDateElement(); | |
| if (!t && !n) | |
| return null; | |
| if (t && n) { | |
| var i = t.compareDocumentPosition(n); | |
| i&Node.DOCUMENT_POSITION_CONTAINS && (t = null), i&Node.DOCUMENT_POSITION_CONTAINED_BY && (n = null), t === n && (n = null) | |
| } | |
| var r, a = this.contentDocument.createElement("div"), | |
| l = !1, | |
| o = !1; | |
| t && (e(r = this.cleanArticleNode(t, t.cloneNode(!0), CleaningType.MetadataContent, !1)), r.innerText.trim() && (l = !0, r.classList.add("byline"))); | |
| if (n) { | |
| var s = this.cleanArticleNode(n, n.cloneNode(!0), CleaningType.MetadataContent, !1); | |
| e(s), s.innerText.trim() && (o = !0, s.classList.add("date")) | |
| } | |
| if (l && a.appendChild(r), l && o) { | |
| var c = document.createElement("span"); | |
| c.classList.add("delimiter"), a.appendChild(c) | |
| } | |
| return o && a.appendChild(s), a | |
| }, | |
| articleBylineElement : function() { | |
| return this._articleBylineElement | |
| }, | |
| findArticleBylineElement : function() { | |
| var e = this.findArticleBylineElementWithoutRejection(); | |
| return e && ("footer" === normalizedElementTagName(e) || e.closest("figure")) ? null : e | |
| }, | |
| findArticleBylineElementWithoutRejection : function() { | |
| function e(e) | |
| { | |
| if (!e.length) | |
| return null; | |
| e = e.filter(isElementVisible); | |
| for (var t = new Set, n = new Set, r = e.length, o = 0; o < r - 1; ++o) { | |
| var s = e[o], | |
| c = e[o + 1]; | |
| if (isElementVisible(s) && isElementVisible(c)) { | |
| var m = s.parentElement; | |
| m === c.parentElement && (m.contains(i) || (n.add(s.parentElement), t.add(s), t.add(c))) | |
| } | |
| } | |
| var d = new Set(e); | |
| n.forEach((function(e) { | |
| d.add(e) | |
| })), | |
| t.forEach((function(e) { | |
| d.delete(e) | |
| })), | |
| e = [], d.forEach((function(t) { | |
| e.push(t) | |
| })); | |
| var h, u = null; | |
| r = e.length; | |
| for (o = 0; o < r; ++o) { | |
| s = e[o]; | |
| if (isElementVisible(s)) { | |
| var g = cachedElementBoundingRect(s), | |
| f = g.left + g.width / 2, | |
| p = g.top + g.height / 2, | |
| E = a - f, | |
| v = l - p, | |
| T = Math.sqrt(E * E + v * v); | |
| (!u || T < h) && (u = s, h = T) | |
| } | |
| } | |
| return u | |
| } | |
| const t = "[itemprop~=author], a[rel='author']:not(svg a)", | |
| n = "#byline, .byline, .article-byline, .byline__author, .entry-meta, .author-name, .byline-dateline, .article-author, [itemprop~=author], a[rel='author']:not(svg a)"; | |
| var i = this._articleSubheadElement || this._articleTitleElement; | |
| if (i) | |
| var r, a = (r = i ? cachedElementBoundingRect(i) : null).left + r.width / 2, | |
| l = r.top + r.height / 2; | |
| var o = this.contentFromUniqueMetadataSelector(this.contentDocument, "head meta[name=author]"); | |
| if (o || (o = this.contentFromUniqueMetadataSelector(this.contentDocument, "head meta[property=author]")), !o) { | |
| var s = this.schemaDotOrgMetadataObjectForArticle(); | |
| if (s) { | |
| var c = s.author; | |
| c && "object" == typeof c && (o = c.name) | |
| } | |
| } | |
| var m = this.article.element, | |
| d = m.querySelectorAll(n); | |
| if (1 === d.length) | |
| return d[0]; | |
| var h = i ? i.nextElementSibling : null; | |
| if (h) { | |
| if (h.matches(n) || h.innerText === o || (h = h.querySelector(n)), h) | |
| if (h.querySelector("li")) { | |
| var u = h.querySelector(n); | |
| u && (h = u) | |
| } | |
| if (h) | |
| return h | |
| } | |
| for (var g = this.contentDocument.getElementsByTagName("a"), f = 0, p = g.length; f < p; ++f) { | |
| var E = g[f]; | |
| if (trimmedInnerTextIgnoringTextTransform(E) === o) | |
| return E | |
| } | |
| var v = m.closest("article"); | |
| if (i && v) { | |
| if (y = e(Array.from(v.querySelectorAll(t)))) | |
| return y; | |
| if (y = e(Array.from(v.querySelectorAll(n)))) | |
| return y | |
| } | |
| var T = m.previousElementSibling; | |
| if (T) { | |
| var y; | |
| if (y = e(Array.from(T.querySelectorAll(t)))) | |
| return y; | |
| if (y = e(Array.from(T.querySelectorAll(n)))) | |
| return y | |
| } | |
| return null | |
| }, | |
| articleDateElement : function() { | |
| return this._articleDateElement | |
| }, | |
| findArticleDateElement : function() { | |
| function e(e) | |
| { | |
| for (var t = e; t && t !== l; t = t.parentElement) | |
| if (elementIsCommentBlock(t) || elementLooksLikeACarousel(t)) | |
| return !0; | |
| return !1 | |
| } | |
| function t(t) | |
| { | |
| for (var n, i = null, r = t.length, a = 0; a < r; ++a) { | |
| var l = t[a]; | |
| if (isElementVisible(l) && !e(l)) { | |
| var o = cachedElementBoundingRect(l), | |
| s = o.left + o.width / 2, | |
| d = o.top + o.height / 2, | |
| h = c - s, | |
| u = m - d, | |
| g = Math.sqrt(h * h + u * u); | |
| (!i || g < n) && (i = l, n = g) | |
| } | |
| } | |
| return i | |
| } | |
| const n = /date/i, | |
| i = "time, .dateline, .entry-date"; | |
| var r, a = this._articleSubheadElement || this._articleTitleElement, | |
| l = this.article.element, | |
| o = a ? a.nextElementSibling : null; | |
| if (o && 1 === (r = o.querySelectorAll(i)).length && (o = r[0]), !o || o.matches(i) || hasClassMatchingRegexp(o, n) || o.querySelector(i) || (o = null), o && o.contains(l) && (o = null), o) | |
| return o; | |
| if (a) | |
| var s, c = (s = a ? cachedElementBoundingRect(a) : null).left + s.width / 2, | |
| m = s.top + s.height / 2; | |
| if ((r = l.querySelectorAll(i)).length) | |
| return t(r); | |
| if ((l = l.closest("article")) && (r = l.querySelectorAll(i)).length) | |
| return t(r); | |
| return null | |
| }, | |
| articleDateElementWithBylineElementHint : function(e) { | |
| function t(e) | |
| { | |
| return /date/.test(e.className) || /\bdatePublished\b/.test(e.getAttribute("itemprop")) | |
| } | |
| var n = e.nextElementSibling; | |
| if (n && t(n)) | |
| return n; | |
| var i = nextLeafElementForElement(e); | |
| return i && t(i) ? i : null | |
| }, | |
| updateArticleBylineAndDateElementsIfNecessary : function() { | |
| this.article && (this._didArticleBylineAndDateElementDetection || (this.updateArticleBylineAndDateElements(), this._didArticleBylineAndDateElementDetection = !0)) | |
| }, | |
| updateArticleBylineAndDateElements : function() { | |
| var e = this.findArticleBylineElement(), | |
| t = this.findArticleDateElement(); | |
| !t && e && (t = this.articleDateElementWithBylineElementHint(e)), this._articleDateElement = t, this._articleBylineElement = e | |
| }, | |
| articleIsLTR : function() { | |
| if (!this._articleIsLTR) { | |
| var e = getComputedStyle(this.article.element); | |
| this._articleIsLTR = !e || "ltr" === e.direction | |
| } | |
| return this._articleIsLTR | |
| }, | |
| findSuggestedCandidate : function() { | |
| var e, t, n = this.suggestedRouteToArticle; | |
| if (!n || !n.length) | |
| return null; | |
| for (t = n.length - 1; t >= 0 && (!n[t].id || !(e = this.contentDocument.getElementById(n[t].id))); --t) | |
| ; | |
| for (t++, e || (e = this.contentDocument); t < n.length;) { | |
| for (var i = n[t], r = e.nodeType === Node.DOCUMENT_NODE ? e.documentElement : e.firstElementChild, a = 1; r && a < i.index; r = r.nextElementSibling) | |
| this.shouldIgnoreInRouteComputation(r) || a++; | |
| if (!r) | |
| return null; | |
| if (normalizedElementTagName(r) !== normalizedElementTagName(i)) | |
| return null; | |
| if (i.className && r.className !== i.className) | |
| return null; | |
| e = r, t++ | |
| } | |
| return isElementVisible(e) ? new CandidateElement(e, this.contentDocument) : null | |
| }, | |
| findArticleBySearchingAllElements : function(e) { | |
| var t = this.findSuggestedCandidate(), | |
| n = this.findCandidateElements(); | |
| if (!n || !n.length) | |
| return t; | |
| if (t && t.basicScore() >= ReaderMinimumScore) | |
| return t; | |
| for (var i = this.highestScoringCandidateFromCandidates(n), r = i.element; r !== this.contentDocument; r = r.parentNode) | |
| if ("blockquote" === normalizedElementTagName(r)) { | |
| for (var a = r.parentNode, l = n.length, o = 0; o < l; ++o) { | |
| var s = n[o]; | |
| if (s.element === a) { | |
| i = s; | |
| break | |
| } | |
| } | |
| break | |
| } | |
| if (t && i.finalScore() < ReaderMinimumScore) | |
| return t; | |
| if (!e) { | |
| if (i.shouldDisqualifyDueToScoreDensity()) | |
| return null; | |
| if (i.shouldDisqualifyDueToHorizontalRuleDensity()) | |
| return null; | |
| if (i.shouldDisqualifyDueToHeaderDensity()) | |
| return null; | |
| if (i.shouldDisqualifyDueToSimilarElements(n)) | |
| return null | |
| } | |
| return i | |
| }, | |
| findExtraArticle : function() { | |
| if (!this.article) | |
| return null; | |
| for (var e = 0, t = this.article.element; e < 3 && t; ++e, t = t.parentNode) { | |
| var n = this.findExtraArticleCandidateElements(t); | |
| if (n && n.length) | |
| for (var i, r = this.sortCandidateElementsInDescendingScoreOrder(n), a = 0; a < r.length && ((i = r[a]) && i.basicScore()); a++) | |
| if (!i.shouldDisqualifyDueToScoreDensity() && !i.shouldDisqualifyDueToHorizontalRuleDensity() && !(i.shouldDisqualifyDueToHeaderDensity() || cachedElementBoundingRect(i.element).height < PrependedArticleCandidateMinimumHeight && cachedElementBoundingRect(this.article.element).width !== cachedElementBoundingRect(i.element).width)) { | |
| var l = contentTextStyleForNode(this.contentDocument, i.element); | |
| if (l && l.fontFamily === this.contentTextStyle().fontFamily && l.fontSize === this.contentTextStyle().fontSize && i) | |
| return i | |
| } | |
| } | |
| return null | |
| }, | |
| highestScoringCandidateFromCandidates : function(e) { | |
| for (var t = 0, n = null, i = e.length, r = 0; r < i; ++r) { | |
| var a = e[r], | |
| l = a.basicScore(); | |
| l >= t && (t = l, n = a) | |
| } | |
| return n | |
| }, | |
| sortCandidateElementsInDescendingScoreOrder : function(e) { | |
| function t(e, t) | |
| { | |
| return e.basicScore() !== t.basicScore() ? t.basicScore() - e.basicScore() : t.depth() - e.depth() | |
| } | |
| return e.sort(t) | |
| }, | |
| findCandidateElements : function() { | |
| const e = 1e3; | |
| for (var t = Date.now() + e, n = this.contentDocument.getElementsByTagName("*"), i = n.length, r = [], a = 0; a < i; ++a) { | |
| var l = n[a]; | |
| if (!SetOfCandidateTagNamesToIgnore.has(normalizedElementTagName(l))) { | |
| var o = CandidateElement.candidateIfElementIsViable(l, this.contentDocument); | |
| if (o && r.push(o), Date.now() > t) { | |
| r = []; | |
| break | |
| } | |
| } | |
| } | |
| var s = r.length; | |
| for (a = 0; a < s; ++a) | |
| r[a].element.candidateElement = r[a]; | |
| for (a = 0; a < s; ++a) { | |
| var c = r[a]; | |
| if ("blockquote" === normalizedElementTagName(c.element)) { | |
| var m = c.element.parentElement.candidateElement; | |
| m && m.addTextNodesFromCandidateElement(c) | |
| } | |
| } | |
| for (a = 0; a < s; ++a) | |
| r[a].element.candidateElement = null; | |
| return r | |
| }, | |
| findExtraArticleCandidateElements : function(e) { | |
| if (!this.article) | |
| return []; | |
| e || (e = this.article.element); | |
| for (var t = "preceding-sibling::*/descendant-or-self::*", n = this.contentDocument.evaluate(t, e, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null), i = n.snapshotLength, r = [], a = 0; a < i; ++a) { | |
| var l = n.snapshotItem(a); | |
| if (!SetOfCandidateTagNamesToIgnore.has(normalizedElementTagName(l))) | |
| (o = CandidateElement.extraArticleCandidateIfElementIsViable(l, this.article, this.contentDocument, !0)) && r.push(o) | |
| } | |
| t = "following-sibling::*/descendant-or-self::*", i = (n = this.contentDocument.evaluate(t, e, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)).snapshotLength; | |
| for (a = 0; a < i; ++a) { | |
| var o; | |
| l = n.snapshotItem(a); | |
| if (!SetOfCandidateTagNamesToIgnore.has(normalizedElementTagName(l))) | |
| (o = CandidateElement.extraArticleCandidateIfElementIsViable(l, this.article, this.contentDocument, !1)) && r.push(o) | |
| } | |
| return r | |
| }, | |
| isGeneratedBy : function(e) { | |
| var t = this.contentDocument.head ? this.contentDocument.head.querySelector("meta[name=generator]") : null; | |
| if (!t) | |
| return !1; | |
| var n = t.content; | |
| return !!n && e.test(n) | |
| }, | |
| isMediaWikiPage : function() { | |
| return void 0 === this._isMediaWikiPage && (this._isMediaWikiPage = this.isGeneratedBy(/^MediaWiki /)), this._isMediaWikiPage | |
| }, | |
| isWordPressSite : function() { | |
| return this.isGeneratedBy(/^WordPress/) | |
| }, | |
| isAMPPage : function() { | |
| return this.contentDocument.documentElement.hasAttribute("amp-version") | |
| }, | |
| nextPageURLString : function() { | |
| if (!this.article) | |
| return null; | |
| if (this.isMediaWikiPage()) | |
| return null; | |
| var e, t = 0, | |
| n = this.article.element; | |
| n.parentNode && "inline" === getComputedStyle(n).display && (n = n.parentNode); | |
| for (var i = n, r = cachedElementBoundingRect(n).bottom + LinkMaxVerticalDistanceFromArticle; isElementNode(i) && cachedElementBoundingRect(i).bottom <= r;) | |
| i = i.parentNode; | |
| i === n || i !== this.contentDocument && !isElementNode(i) || (n = i); | |
| var a = this.contentDocument.evaluate(LinkCandidateXPathQuery, n, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null), | |
| l = a.snapshotLength; | |
| if (this.pageNumber <= 2 && !this.prefixWithDateForNextPageURL) { | |
| var o = this.contentDocument.location.pathname, | |
| s = o.match(LinkDateRegex); | |
| s && (s = s[0], this.prefixWithDateForNextPageURL = o.substring(0, o.indexOf(s) + s.length)) | |
| } | |
| for (var c = 0; c < l; ++c) { | |
| var m = a.snapshotItem(c), | |
| d = this.scoreNextPageLinkCandidate(m); | |
| d > t && (e = m, t = d) | |
| } | |
| return e ? e.href : null | |
| }, | |
| scoreNextPageLinkCandidate : function(e) { | |
| function t(e, t, n, i) | |
| { | |
| t.substring(0, e.length) === e && (t = t.substring(e.length), e = ""); | |
| var r = t.lastInteger(); | |
| if (isNaN(r)) | |
| return !1; | |
| var a = e ? e.lastInteger() : NaN; | |
| return (isNaN(a) || a >= MaximumExactIntegralValue) && (a = i), r === a ? n.lastInteger() === a + 1 : r === a + 1 | |
| } | |
| function n(e) | |
| { | |
| for (var t = {}, n = e.substring(1).split("&"), i = n.length, r = 0; r < i; ++r) { | |
| var a = n[r], | |
| l = a.indexOf("="); | |
| -1 === l ? t[a] = null : t[a.substring(0, l)] = a.substring(l + 1) | |
| } | |
| return t | |
| } | |
| var i = this.contentDocument.location; | |
| if (e.host !== i.host) | |
| return 0; | |
| if (e.pathname === i.pathname && e.search === i.search) | |
| return 0; | |
| if (-1 !== e.toString().indexOf("#")) | |
| return 0; | |
| if (anchorLinksToAttachment(e) || anchorLinksToTagOrCategoryPage(e)) | |
| return 0; | |
| if (!isElementVisible(e)) | |
| return 0; | |
| var r = cachedElementBoundingRect(e), | |
| a = this.articleBoundingRect(), | |
| l = Math.max(0, Math.max(a.top - (r.top + r.height), r.top - (a.top + a.height))); | |
| if (r.top < a.top) | |
| return 0; | |
| if (l > LinkMaxVerticalDistanceFromArticle) | |
| return 0; | |
| if (Math.max(0, Math.max(a.left - (r.left + r.width), r.left - (a.left + a.width))) > 0) | |
| return 0; | |
| var o = i.pathname, | |
| s = e.pathname; | |
| if (this.prefixWithDateForNextPageURL) { | |
| if (-1 === e.pathname.indexOf(this.prefixWithDateForNextPageURL)) | |
| return 0; | |
| o = o.substring(this.prefixWithDateForNextPageURL.length), s = s.substring(this.prefixWithDateForNextPageURL.length) | |
| } | |
| var c = s.substring(1).split("/"); | |
| c[c.length - 1] || c.pop(); | |
| var m = c.length, | |
| d = o.substring(1).split("/"), | |
| h = !1; | |
| d[d.length - 1] || (h = !0, d.pop()); | |
| var u = d.length; | |
| if (m < u) | |
| return 0; | |
| for (var g = 0, f = 0, p = e.textContent, E = 0; E < m; ++E) { | |
| var v = c[E], | |
| T = E < u ? d[E] : ""; | |
| if (T !== v) { | |
| if (E < u - 2) | |
| return 0; | |
| if (v.length >= T.length) { | |
| for (var y = 0; v[v.length - 1 - y] === T[T.length - 1 - y];) | |
| y++; | |
| y && (v = v.substring(0, v.length - y), T = T.substring(0, T.length - y)); | |
| var S = v.indexOf(T); | |
| -1 !== S && (v = v.substring(S)) | |
| } | |
| t(T, v, p, this.pageNumber) ? f = Math.pow(LinkNextOrdinalValueBase, E - m + 1) : g++ | |
| } | |
| if (g > 1) | |
| return 0 | |
| } | |
| var A = !1; | |
| if (e.search) | |
| for (var N in linkParameters = n(e.search), referenceParameters = n(i.search), linkParameters) { | |
| var b = linkParameters[N], | |
| x = N in referenceParameters ? referenceParameters[N] : null; | |
| if (x !== b) | |
| if (null === x && (x = ""), null === b && (b = ""), b.length < x.length) | |
| g++; | |
| else if (t(x, b, p, this.pageNumber)) { | |
| if (LinkURLSearchParameterKeyMatchRegex.test(N)) { | |
| if (o.toLowerCase() !== s.toLowerCase()) | |
| return 0; | |
| if (this.isWordPressSite() && h) | |
| return 0; | |
| A = !0 | |
| } | |
| if (LinkURLBadSearchParameterKeyMatchRegex.test(N)) { | |
| g++; | |
| continue | |
| } | |
| f = Math.max(f, 1 / LinkNextOrdinalValueBase) | |
| } else | |
| g++ | |
| } | |
| if (!f) | |
| return 0; | |
| if ((LinkURLPageSlashNumberMatchRegex.test(e.href) || LinkURLSlashDigitEndMatchRegex.test(e.href)) && (A = !0), !A && m === u && stringSimilarity(o, s) < LinkMinimumURLSimilarityRatio) | |
| return 0; | |
| if (LinkURLArchiveSlashDigitEndMatchRegex.test(e)) | |
| return 0; | |
| var C = LinkMatchWeight * (Math.pow(LinkMismatchValueBase, -g) + f) + LinkVerticalDistanceFromArticleWeight * l / LinkMaxVerticalDistanceFromArticle; | |
| A && (C += LinkURLSemanticMatchBonus), "li" === normalizedElementTagName(e.parentNode) && (C += LinkListItemBonus); | |
| p = e.innerText; | |
| return LinkNextMatchRegEx.test(p) && (C += LinkNextMatchBonus), LinkPageMatchRegEx.test(p) && (C += LinkPageMatchBonus), LinkContinueMatchRegEx.test(p) && (C += LinkContinueMatchBonus), C | |
| }, | |
| elementContainsEnoughTextOfSameStyle : function(e, t, n) { | |
| const i = 110; | |
| var r = "body" === normalizedElementTagName(e), | |
| a = getVisibleNonWhitespaceTextNodes(e, r ? 2 : 3, i, r, t); | |
| const l = .2, | |
| o = n / clamp(scoreMultiplierForElementTagNameAndAttributes(e), l, 1 / 0) / languageScoreMultiplierForTextNodes(a); | |
| for (var s = {}, c = a.length, m = 0; m < c; ++m) { | |
| var d = a[m], | |
| h = d.length, | |
| u = d.parentElement, | |
| g = window.getComputedStyle(u), | |
| f = g.fontFamily + "|" + g.fontSize, | |
| p = Math.pow(h, TextNodeLengthPower); | |
| if (s[f]) { | |
| if ((s[f] += p) > o) | |
| break | |
| } else | |
| s[f] = p | |
| } | |
| for (var f in s) | |
| if (s[f] > o) | |
| return !0; | |
| return !1 | |
| }, | |
| openGraphMetadataClaimsPageTypeIsArticle : function() { | |
| if (!this._openGraphMetadataClaimsPageTypeIsArticle) { | |
| var e = this.contentDocument.querySelector("head meta[property='og:type']"); | |
| this._openGraphMetadataClaimsPageTypeIsArticle = e && "article" === e.content | |
| } | |
| return this._openGraphMetadataClaimsPageTypeIsArticle | |
| }, | |
| prismGenreClaimsPageIsHomepage : function() { | |
| return "homePage" === this.contentFromUniqueMetadataSelector(this.contentDocument, "head meta[name='prism.genre']") | |
| }, | |
| pointsToUseForHitTesting : function() { | |
| const e = window.innerWidth, | |
| t = e / 4, | |
| n = e / 2, | |
| i = 128, | |
| r = 320; | |
| var a = [ | |
| [ n, 800 ], | |
| [ n, 600 ], | |
| [ t, 800 ], | |
| [ n, 400 ], | |
| [ n - i, 1100 ], | |
| [ r, 700 ], | |
| [ 3 * t, 800 ], | |
| [ e - r, 700 ] | |
| ]; | |
| return this.openGraphMetadataClaimsPageTypeIsArticle() && a.push([ n - i, 1400 ]), a | |
| }, | |
| findArticleByVisualExamination : function() { | |
| for (var e = new Set, t = this.pointsToUseForHitTesting(), n = t.length, i = AppleDotComAndSubdomainsRegex.test(this.contentDocument.location.hostname.toLowerCase()) ? 7200 : 1800, r = this.candidateElementFilter, a = 0; a < n; a++) | |
| for (var l = t[a][0], o = t[a][1], s = elementAtPoint(l, o, this.contentDocument); s && !e.has(s); s = s.parentElement) { | |
| if (VeryPositiveClassNameRegEx.test(s.className)) | |
| return new CandidateElement(s, this.contentDocument); | |
| if (!SetOfCandidateTagNamesToIgnore.has(normalizedElementTagName(s))) { | |
| var c = s.offsetWidth, | |
| m = s.offsetHeight; | |
| if (!c && !m) { | |
| var d = cachedElementBoundingRect(s); | |
| c = d.width, m = d.height | |
| } | |
| if (!(c < r.minimumWidth || m < r.minimumHeight || c * m < r.minimumArea)) { | |
| var h = this.elementContainsEnoughTextOfSameStyle(s, e, i); | |
| if (e.add(s), h && !(CandidateElement.candidateElementAdjustedHeight(s) < r.minimumHeight)) { | |
| var u = new CandidateElement(s, this.contentDocument); | |
| if (!u.shouldDisqualifyDueToSimilarElements()) { | |
| if (u.shouldDisqualifyDueToHorizontalRuleDensity()) | |
| return null; | |
| if (u.shouldDisqualifyDueToHeaderDensity()) | |
| return null; | |
| if (!u.shouldDisqualifyForDeepLinking()) | |
| return u | |
| } | |
| } | |
| } | |
| } | |
| } | |
| return null | |
| }, | |
| findTextSamplesByVisualExamination : function() { | |
| function e(e) | |
| { | |
| if (!e || !e.innerText) | |
| return null; | |
| let n = t(e.innerText.trim()); | |
| return n && a.add(e), n | |
| } | |
| function t(e) | |
| { | |
| const t = 10; | |
| let i = textContentAppearsToBeCJK(e, d) ? d : m, | |
| r = e.length; | |
| if (r < i) | |
| return null; | |
| if (r > f * c) | |
| return null; | |
| let a = n(e); | |
| return (a.match(/\n/g) || []).length > t ? null : a | |
| } | |
| function n(e) | |
| { | |
| return e.substring(0, h) | |
| } | |
| function i(t, n) | |
| { | |
| let i = [], | |
| r = s.querySelectorAll(t); | |
| for (let t of r) { | |
| if (i.length >= n) | |
| break; | |
| if (elementDescendsFromElementInSet(t, l)) | |
| continue; | |
| let r = e(t); | |
| r && i.push([ t, r ]) | |
| } | |
| return i | |
| } | |
| function r(e) | |
| { | |
| const n = document.querySelectorAll("div"), | |
| i = new Set; | |
| for (let r of n) { | |
| if (r.firstElementChild) | |
| continue; | |
| let n = t(r.textContent); | |
| if (n && (i.add(n), i.size >= e)) | |
| break | |
| } | |
| return i | |
| } | |
| this.setSuppressBoundingRectCalculationForSkippedElements(!0); | |
| var a = new Set, | |
| l = new Set, | |
| o = new Set, | |
| s = this.contentDocument, | |
| c = s.body.innerText.length; | |
| const m = 20, | |
| d = 10, | |
| h = 200, | |
| u = 5, | |
| g = 5, | |
| f = .8; | |
| let p = s.title, | |
| E = t(p); | |
| E && (o.add(E), l.add(p)); | |
| let v = this.pointsToUseForHitTesting(), | |
| T = v.length; | |
| for (var y = 0; y < T; y++) { | |
| let t = v[y][0], | |
| n = v[y][1], | |
| i = 0; | |
| for (let r = elementAtPoint(t, n, this.contentDocument); r && !a.has(r) && !(i > u); r = r.parentElement, i++) { | |
| let t = e(r); | |
| if (t) { | |
| if (elementDescendsFromElementMatchingSelector(r, "code, form")) | |
| break; | |
| o.add(t), l.add(r); | |
| break | |
| } | |
| } | |
| } | |
| let S = { | |
| p : 3, | |
| h1 : 2, | |
| h2 : 2, | |
| h3 : 1 | |
| }; | |
| for (let [e, t] of Object.entries(S)) { | |
| let n = i(e, t); | |
| for (let [e, t] of n) | |
| e && t && (o.add(t), l.add(e)) | |
| } | |
| if (o.size < g) { | |
| let e = [ "article", "header", "a", "footer", "body" ]; | |
| for (let t of e) { | |
| let e = i(t, 1) || [], | |
| [ n, r ] = e.length > 0 ? e[0] : [ null, null ]; | |
| if (n && r) { | |
| o.add(r), l.add(n); | |
| break | |
| } | |
| } | |
| } | |
| if (o.size < g) { | |
| const e = r(g - o.size); | |
| o = o.union(e) | |
| } | |
| return Array.from(o) | |
| }, | |
| findArticleFromMetadata : function(e) { | |
| var t = this.contentDocument.querySelectorAll(SchemaDotOrgArticleContainerSelector); | |
| if (1 === t.length) { | |
| var n = t[0]; | |
| if (n.matches("article, *[itemprop=articleBody]")) | |
| if (o = CandidateElement.candidateIfElementIsViable(n, this.contentDocument, !0)) | |
| return e === FindArticleMode.ExistenceOfElement || o; | |
| var i = n.querySelectorAll("article, *[itemprop=articleBody]"), | |
| r = elementWithLargestAreaFromElements(i); | |
| if (r) | |
| if (o = CandidateElement.candidateIfElementIsViable(r, this.contentDocument, !0)) | |
| return e === FindArticleMode.ExistenceOfElement || o; | |
| return new CandidateElement(n, this.contentDocument) | |
| } | |
| if (this.openGraphMetadataClaimsPageTypeIsArticle() && !this.prismGenreClaimsPageIsHomepage()) { | |
| var a = this.contentDocument.querySelectorAll("main article"), | |
| l = elementWithLargestAreaFromElements(a); | |
| if (l) | |
| if (o = CandidateElement.candidateIfElementIsViable(l, this.contentDocument, !0)) | |
| return e === FindArticleMode.ExistenceOfElement || o; | |
| var o, s = this.contentDocument.querySelectorAll("article"); | |
| if (1 === s.length) | |
| if (o = CandidateElement.candidateIfElementIsViable(s[0], this.contentDocument, !0)) | |
| return e === FindArticleMode.ExistenceOfElement || o | |
| } | |
| return null | |
| }, | |
| articleTextContent : function() { | |
| return this._articleTextContent || this.adoptableArticle(), this._articleTextContent | |
| }, | |
| unformattedArticleTextContentIncludingMetadata : function(e) { | |
| this.setSuppressBoundingRectCalculationForSkippedElements(!0); | |
| var t = this.articleNode(); | |
| if (t) { | |
| if (!e) | |
| return t.innerText; | |
| var n = "", | |
| i = this.articleTitle(); | |
| i && (n += i + "\n"); | |
| var r = this.articleSubhead(); | |
| r && (n += r + "\n"); | |
| var a = this.adoptableMetadataBlock(); | |
| return a && (n += this.plaintextVersionOfNodeAppendingNewlinesBetweenBlockElements(a) + "\n"), n + t.innerText | |
| } | |
| }, | |
| plaintextVersionOfNodeAppendingNewlinesBetweenBlockElements : function(e) { | |
| var t = this.contentDocument.createTreeWalker(e, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, null), | |
| n = ""; | |
| for (t.currentNode = e; t.nextNode();) { | |
| var i = t.currentNode; | |
| if (i.nodeType !== Node.TEXT_NODE) { | |
| var r = normalizedElementTagName(i); | |
| "p" !== r && "div" !== r || (n += "\n") | |
| } else | |
| n += i.textContent | |
| } | |
| return n | |
| }, | |
| pageDescription : function() { | |
| for (var e = this.contentDocument.querySelectorAll("head meta[name]"), t = e.length, n = 0; n < t; ++n) { | |
| var i = e[n]; | |
| if ("description" === i.getAttribute("name").toLowerCase()) { | |
| var r = i.getAttribute("content"); | |
| if (r) | |
| return r.trim() | |
| } | |
| } | |
| return null | |
| }, | |
| articleTitleAndSiteNameFromTitleString : function(e) { | |
| const t = [ " - ", " \u2013 ", " \u2014 ", ": ", " | ", " \xbb " ], | |
| n = t.length, | |
| i = .6; | |
| for (var r, a, l = this.contentDocument.location.host.replace(/^(www|m|secure)\./, ""), o = l.replace(/\.(com|info|net|org|edu|gov)$/, "").toLowerCase(), s = 0; s < n; ++s) { | |
| var c = e.split(t[s]); | |
| if (2 === c.length) { | |
| var m = c[0].trim(), | |
| d = c[1].trim(), | |
| h = m.toLowerCase(), | |
| u = d.toLowerCase(), | |
| g = Math.max(stringSimilarity(h, l), stringSimilarity(h, o)), | |
| f = Math.max(stringSimilarity(u, l), stringSimilarity(u, o)), | |
| p = Math.max(g, f); | |
| (!a || p > a) && (a = p, r = g > f ? { | |
| siteName : m, | |
| articleTitle : d | |
| } | |
| : { | |
| siteName : d, | |
| articleTitle : m | |
| }) | |
| } | |
| } | |
| return r && a >= i ? r : null | |
| }, | |
| pageInformation : function(e, t) { | |
| var n, i = this.pageDescription(), | |
| r = !1; | |
| this.adoptableArticle() ? (n = this.articleTitle(), i = i || this.articleTextContent(), r = !0) : (n = this.contentDocument.title, this.contentDocument.body && (i = i || this.contentDocument.body.innerText)); | |
| var a = "", | |
| l = this.buildMapOfMetaTags(), | |
| o = this.pageImageURLFromMetadata(l); | |
| if (o) | |
| a = o; | |
| else { | |
| var s = this.mainImageNode(); | |
| s && (a = s.src) | |
| } | |
| n || (n = userVisibleURLString(this.contentDocument.location.href)), n = n.trim(), e && (n = n.substring(0, e)); | |
| var c = this.contentFromUniqueMetadataSelector(this.contentDocument, "head meta[property='og:site_name']"); | |
| if (!c) { | |
| var m = this.articleTitleAndSiteNameFromTitleString(this.contentDocument.title); | |
| m && m.articleTitle === n && (c = m.siteName) | |
| } | |
| return c || (c = ""), i = i ? i.trim() : "", t && (i = i.substring(0, t)), | |
| { | |
| title: n, | |
| previewText: i = i.replace(/[\s]+/g, " "), | |
| siteName: c, | |
| mainImageURL: a, | |
| isReaderAvailable: r | |
| } | |
| }, | |
| readingListItemInformation : function() { | |
| const e = 220, | |
| t = 220; | |
| return this.pageInformation(e, t) | |
| }, | |
| buildMapOfMetaTags : function() { | |
| var e = {}; | |
| const t = this.contentDocument.head.getElementsByTagName("meta"), | |
| n = t.length; | |
| for (var i = 0; i < n; ++i) { | |
| const n = t[i], | |
| r = n.content; | |
| if (!r) | |
| continue; | |
| if (this.elementAttributesContainImproperQuote(n)) | |
| continue; | |
| n.name && (e["name:" + n.name.toLowerCase()] = r); | |
| const a = n.getAttribute("property"); | |
| a && (e["property:" + a.toLowerCase()] = r) | |
| } | |
| return e | |
| }, | |
| longestPageMetadataDescriptionForTextAnalysis : function(e) { | |
| var t = []; | |
| const n = e["name:description"]; | |
| n && n.length && t.push(n); | |
| const i = e["property:og:description"]; | |
| i && i.length && t.push(i); | |
| const r = e["name:twitter:description"]; | |
| return r && r.length && t.push(r), t.length ? t.reduce((function(e, t) { | |
| return e.length > t.length ? e : t | |
| })) | |
| : null | |
| }, | |
| pageTypeForTextAnalysis : function(e) { | |
| const t = this.contentDocument.documentElement.getAttribute("itemtype"); | |
| if ("http://schema.org/SearchResultsPage" === t || "https://schema.org/SearchResultsPage" === t) | |
| return PageType.searchResults; | |
| const n = e["name:section"]; | |
| if (n && "homepage" === n.toLowerCase()) | |
| return PageType.homepage; | |
| const i = e["property:og:type"]; | |
| if (i) { | |
| const e = i.toLowerCase(); | |
| if ("homepage" === e) | |
| return PageType.homepage; | |
| if ("article" === e) | |
| return PageType.article | |
| } | |
| const r = e["property:analytics-s-channel"]; | |
| return r && "homepage" === r.toLowerCase() ? PageType.homepage : null | |
| }, | |
| pageTitleForTextAnalysis : function(e) { | |
| const t = this.contentDocument; | |
| var n = e["property:og:title"]; | |
| return n || (n = e["name:twitter:title"]), n || (n = e["name:sailthru.headline"]), n || (n = t.title), n | |
| }, | |
| pageKeywordsForTextAnalysis : function(e) { | |
| return e["name:keywords"] | |
| }, | |
| pageAuthorForTextAnalysis : function(e) { | |
| return e["name:author"] || e["property:author"] | |
| }, | |
| pageMetadataCommonToTextAnalysisAndArticleContent : function() { | |
| var e = {}; | |
| const t = this.buildMapOfMetaTags(), | |
| n = this.pageTitleForTextAnalysis(t); | |
| n && (e.title = n); | |
| const i = this.pageAuthorForTextAnalysis(t); | |
| i && (e.author = i); | |
| const r = this.pageImageURLFromMetadata(t); | |
| return r && (e.imageURL = r), e | |
| }, | |
| pageMetadataForTextAnalysis : function() { | |
| let e = this.pageMetadataCommonToTextAnalysisAndArticleContent(); | |
| const t = this.pageTypeForTextAnalysis(metadataMap); | |
| t && (e.type = t); | |
| const n = this.longestPageMetadataDescriptionForTextAnalysis(metadataMap); | |
| n && (e.description = n); | |
| const i = this.pageKeywordsForTextAnalysis(metadataMap); | |
| return i && (e.keywords = i), e | |
| }, | |
| extractedArticleContent : function() { | |
| try { | |
| const e = this.adoptableArticle(!0), | |
| t = this.elementReaderUniqueIDAttributeKey(); | |
| for (let n of e.getElementsByTagName("*")) | |
| n.removeAttribute(t); | |
| let n = this.pageMetadataCommonToTextAnalysisAndArticleContent(); | |
| if (e) { | |
| const t = e.innerHTML; | |
| n.body = t | |
| } | |
| this.updateArticleBylineAndDateElementsIfNecessary(); | |
| const i = this.articleDateElement(); | |
| i && (n.publishedDate = trimmedInnerTextIgnoringTextTransform(i)); | |
| const r = this.articleBylineElement(); | |
| return !n.author && r && (n.author = trimmedInnerTextIgnoringTextTransform(r)), n | |
| } catch (e) { | |
| let t = {}; | |
| const n = e.message, | |
| i = e.stack; | |
| return n && (t.error = n), i && (t.stack = i), t | |
| } | |
| }, | |
| readerUniqueIDOfElementPinnedToTopOfViewport : function() { | |
| const e = 120; | |
| if (window.scrollY < e) | |
| return null; | |
| const t = this.articleNode(); | |
| if (!t) | |
| return null; | |
| const n = t.getBoundingClientRect(), | |
| i = (n.left + n.right) / 2; | |
| for (const e of [0, 15, 35, 50, 80, 110]) { | |
| const n = t.ownerDocument.elementFromPoint(i, e); | |
| if (n !== t && (t.contains(n) || n === this._articleTitleElement || n === this._articleSubheadElement)) { | |
| const e = this._weakMapOfOriginalElementToUniqueID.get(n); | |
| if (e) | |
| return e | |
| } | |
| } | |
| return null | |
| }, | |
| elementReaderUniqueIDAttributeKey : function() { | |
| return "data-reader-unique-id" | |
| }, | |
| titleUniqueID : function() { | |
| return "titleElement" | |
| }, | |
| subheadUniqueID : function() { | |
| return "subheadElement" | |
| }, | |
| rectOfElementWithReaderUniqueID : function(e) { | |
| function t(e) | |
| { | |
| return | |
| { | |
| top: e.top + window.scrollY, | |
| right: e.right + window.scrollX, | |
| bottom: e.bottom + window.scrollY, | |
| left: e.left + window.scrollX, | |
| width: e.width, | |
| height: e.height | |
| } | |
| } | |
| if (!this._mapOfUniqueIDToOriginalElement) | |
| return null; | |
| let n = this._mapOfUniqueIDToOriginalElement.get(e); | |
| return n && n.parentElement ? t(n.getBoundingClientRect()) : null | |
| }, | |
| scrollY : function() { | |
| return window.scrollY | |
| }, | |
| scrollToOffset : function(e) { | |
| if ("number" == typeof e) | |
| try { | |
| clearCachedElementBoundingRects(), this.cacheWindowScrollPosition(), this.contentDocument.scrollingElement.scrollTop = e | |
| } catch (e) { | |
| } | |
| }, | |
| documentURLString : function() { | |
| return this.contentDocument.location.href | |
| }, | |
| usesSearchEngineOptimizationMetadata : function() { | |
| return !!document.head.querySelector('meta[property^="og:"]') | |
| }, | |
| extractCanonicalLink : function() { | |
| var e = document.head.querySelector("link[rel='canonical']"); | |
| if (!e) | |
| return null; | |
| var t = e.getAttribute("href"); | |
| if (!t) | |
| return null; | |
| var n = document.baseURI, | |
| i = urlFromString(t, n); | |
| return "/" !== document.location.pathname && "/" === i.pathname || "localhost" === i.hostname && "localhost" !== document.location.hostname ? null : i.href | |
| }, | |
| setSuppressBoundingRectCalculationForSkippedElements : function(e) { | |
| this._shouldSuppressBoundingRectCalculationForSkippedElements = e | |
| }, | |
| shouldSuppressBoundingRectCalculationForSkippedElements : function() { | |
| return !!this._shouldSuppressBoundingRectCalculationForSkippedElements | |
| } | |
| }; | |
| var ReaderArticleFinderJS = new ReaderArticleFinder(document); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <meta name="disabled-adaptations" content="watch"> | |
| <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> | |
| <meta name="viewport" content="initial-scale=1"> | |
| <base> | |
| <title>Reader</title> | |
| <style id="assistant-content"> | |
| #summary-container { | |
| pointer-events: auto; | |
| -webkit-user-select: auto; | |
| background: transparent; | |
| } | |
| #summary-header { | |
| padding-top: 30px; | |
| margin: 0px; | |
| line-height: 1.6em; | |
| } | |
| #summary-text { | |
| padding-top: 4px; | |
| margin: 0px; | |
| line-height: 1.6em; | |
| padding-bottom: 30px | |
| } | |
| #tableOfContents-container { | |
| padding-bottom: 34px; | |
| } | |
| #tableOfContents-header { | |
| margin: 0px; | |
| line-height: 1.6em; | |
| padding-top: 30px | |
| } | |
| #tableOfContents-list { | |
| margin-left: 0px; | |
| margin-right: 0px; | |
| margin-top: 4px; | |
| padding-left: 1.8em; | |
| line-height: 1.6em; | |
| } | |
| .innerTableOfContents-listItem { | |
| border-bottom: 1px solid var(--separator-color); | |
| margin-bottom: 6px; | |
| margin-top: 6px; | |
| } | |
| .innerTableOfContents-listItem:last-child { | |
| border-bottom: none; | |
| } | |
| .collapsible { | |
| cursor: pointer; | |
| font-weight: 600; | |
| padding-left: 16px; | |
| padding-top: 18px; | |
| padding-bottom: 18px; | |
| padding-right: 0px; | |
| width: 100%; | |
| outline: none | |
| overflow: hidden; | |
| background: transparent; | |
| background-repeat: no-repeat; | |
| text-align: left; | |
| border: none; | |
| -webkit-tap-highlight-color: transparent; | |
| } | |
| .collapsible:nth-of-type(2):not(:first-of-type) { | |
| border-top: 1px solid var(--separator-color); | |
| } | |
| .collapsible:after { | |
| content: url('data:image/svg+xml,<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="7.15323" height="12.4569"><g><rect height="12.4569" opacity="0" width="7.15323" x="0" y="0"/><path d="M7.15323 6.22406C7.15165 5.96742 7.06077 5.74734 6.85599 5.54414L1.51768 0.255233C1.35263 0.0829682 1.14362 0 0.897181 0C0.395505 0 0 0.386716 0 0.885228C0 1.12446 0.105292 1.35175 0.272634 1.53034L5.01961 6.22248L0.272634 10.9178C0.106874 11.0964 0 11.3164 0 11.5645C0 12.063 0.395505 12.4497 0.897181 12.4497C1.14204 12.4497 1.35263 12.3667 1.51768 12.1945L6.85599 6.90397C7.06235 6.70077 7.15323 6.47911 7.15323 6.22406Z" fill="%23868686" fill-opacity="0.95"/></g></svg>'); | |
| width: 12px; | |
| height: 12px; | |
| float: right; | |
| padding-left: 12px; | |
| padding-right: 22px; | |
| } | |
| .collapsedContent { | |
| margin: 0; | |
| padding: 0; | |
| max-height: 0; | |
| overflow: auto; | |
| padding-left: 16px; | |
| margin-right: 1.25em; | |
| transition: max-height 0.2s ease-out; | |
| } | |
| .expandedContent:after { | |
| content:url('data:image/svg+xml,<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="12.4569" height="7.76214"><g><rect height="7.76214" opacity="0" width="12.4569" x="0" y="0"/><path d="M6.23285 7.76214C6.48949 7.76056 6.72239 7.6681 6.91276 7.4649L12.2017 2.12501C12.3667 1.95995 12.4569 1.75095 12.4569 1.50451C12.4569 1.00283 12.0702 0.607328 11.5717 0.607328C11.3324 0.607328 11.098 0.71262 10.9266 0.879962L5.86564 5.99169L6.5976 5.99169L1.53192 0.879962C1.36054 0.714202 1.14046 0.607328 0.892435 0.607328C0.393923 0.607328 0 1.00283 0 1.50451C0 1.74937 0.0917573 1.95837 0.255233 2.12501L5.55293 7.4649C5.75051 7.66968 5.97058 7.76214 6.23285 7.76214Z" fill="%23868686" fill-opacity="0.95"/></g></svg>'); | |
| width: 12px; | |
| height: 12px; | |
| padding-right: 30px; | |
| } | |
| #innerAssistantContainer { | |
| margin-top: 21px; | |
| margin-bottom: 21px; | |
| border-radius: 22px; | |
| background: var(--narrow-assistant-background-color); | |
| } | |
| #onDeviceSummaryButton { | |
| cursor: pointer; | |
| font-weight: bold; | |
| padding-left: 16px; | |
| padding-right: 22px; | |
| padding-top: 15px; | |
| padding-bottom: 12px; | |
| width: 100%; | |
| outline: none | |
| overflow: hidden; | |
| background: var(--narrow-assistant-background-color); | |
| background-repeat: no-repeat; | |
| text-align: left; | |
| font-size: 16px; | |
| margin-top: 21px; | |
| margin-bottom: 21px; | |
| border-radius: 18px; | |
| border: none; | |
| } | |
| #glyph { | |
| height: 30px; | |
| width: 30px; | |
| float: left; | |
| margin: -4px -4px 0px 0px; | |
| } | |
| #assistant-container { | |
| background: var(--assistant-sidebar-color); | |
| padding-top: 34px; | |
| padding-bottom: 34px; | |
| padding-left: 16px; | |
| padding-right: 16px; | |
| transition: right 0.5s cubic-bezier(.17,.67,.99,1); | |
| width: 350px; | |
| right: 20vw; | |
| } | |
| #sidebarButton { | |
| margin-top: 40px; | |
| position: fixed; | |
| right: 19vw; | |
| transition: right 0.5s cubic-bezier(.17,.67,.99,1); | |
| } | |
| #article { | |
| transition: left 0.5s cubic-bezier(.17,.67,.99,1); | |
| } | |
| </style> | |
| <style id="article-content"> | |
| h1, h2, h3, h4, h5, h6 { | |
| font-weight: bold; | |
| } | |
| h1 { | |
| font-size: 1.5em; | |
| line-height: 1.4em; | |
| } | |
| h2 { | |
| font-size: 1.43em; | |
| } | |
| h3 { | |
| font-size: 1.25em; | |
| } | |
| h4, h5, h6 { | |
| font-size: 1em; | |
| margin: 1em 0; | |
| } | |
| body.watch h1 { | |
| font-size: 1.1875rem; | |
| } | |
| body.watch h2 { | |
| font-size: 1.125rem; | |
| } | |
| body.watch h3 { | |
| font-size: 1.0625rem; | |
| } | |
| body.watch :matches(h4, h5, h6) { | |
| font-size: 1rem; | |
| } | |
| h1.title { | |
| font-weight: bold; | |
| font-size: 1.95552em; | |
| line-height: 1.2141em; | |
| margin-top: 0; | |
| margin-bottom: 0.5em; | |
| } | |
| .subhead { | |
| font-weight: normal; | |
| } | |
| .title, .subhead, .metadata { | |
| text-align: start; | |
| hyphens: manual; | |
| display: none; | |
| } | |
| :nth-child(1 of .page) :matches(.title, .subhead, .metadata) { | |
| display: block; | |
| } | |
| .subhead { | |
| color: rgba(27, 27, 27, 0.65); | |
| font-size: 1.46664em; | |
| margin-top: -0.35em; | |
| line-height: 1.27275em; | |
| } | |
| .metadata { | |
| margin-top: -0.75em; | |
| margin-bottom: 1.45em; | |
| } | |
| body.watch .metadata { | |
| line-height: 1.3em; | |
| } | |
| .metadata * { | |
| font-size: 1em !important; | |
| font-weight: normal !important; | |
| font-style: normal !important; | |
| display: inline !important; | |
| margin: 0; | |
| } | |
| .metadata :matches(.byline, .date) { | |
| display: inline !important; | |
| } | |
| .metadata :matches(ul, ol, li) { | |
| list-style-type: none; | |
| -webkit-padding-start: 0; | |
| } | |
| .title + .metadata { | |
| margin-top: -0.75em; | |
| } | |
| .subhead + .metadata { | |
| margin-top: -0.7em; | |
| } | |
| .page { | |
| text-align: start; | |
| word-wrap: break-word; | |
| } | |
| body.watch .page { | |
| hyphens: auto; | |
| } | |
| .page.rtl { | |
| direction: rtl; | |
| } | |
| a { | |
| text-decoration: none; | |
| } | |
| a[href] { | |
| color: rgb(65, 110, 210); | |
| } | |
| #article { | |
| text-rendering: optimizeLegibility; | |
| } | |
| #article * { | |
| /* Scale down anything larger than our view. Max-width maintains aspect ratios on images. */ | |
| max-width: 100%; | |
| } | |
| #article img { | |
| /* By default, images are centered on their own line. */ | |
| margin: 0.5em auto; | |
| display: block; | |
| height: auto; | |
| } | |
| #article img.reader-image-tiny { | |
| display: inline; | |
| margin: 0; | |
| } | |
| #article .leading-image, figure, .auxiliary { | |
| margin-bottom: 1.15em; | |
| } | |
| #article .leading-image img { | |
| margin: auto; | |
| display: block; | |
| clear: both; | |
| } | |
| #article .leading-image .credit { | |
| margin: 0; | |
| } | |
| #article .leading-image, | |
| #article figure { | |
| font-size: 0.75em; | |
| line-height: 1.5em; | |
| } | |
| body.watch #article .leading-image, | |
| body.watch #article figure { | |
| font-size: 0.8125rem; | |
| } | |
| #article .leading-image :matches(.caption, .credit), | |
| #article figcaption { | |
| margin-top: 0.8em; | |
| width: 100%; | |
| } | |
| body.watch #article .leading-image :matches(.caption, .credit), | |
| body.watch #article figcaption { | |
| margin-top: 4px; | |
| } | |
| body.watch #article figure img { | |
| margin-bottom: 0; | |
| } | |
| #article figcaption > * { | |
| margin-top: 0.25em; | |
| margin-bottom: 0.25em; | |
| } | |
| #article :matches(.leading-image, figure) p { | |
| margin-top: 0.4em; | |
| margin-bottom: 0.4em; | |
| } | |
| #article .leading-image .credit + .caption { | |
| margin-top: 0.1em; | |
| } | |
| #article .auxiliary { | |
| display: block; | |
| clear: both; | |
| font-size: 0.75em; | |
| line-height: 1.4em; | |
| text-align: start; | |
| } | |
| body.watch #article .auxiliary { | |
| font-size: 0.9em; | |
| } | |
| #article .pullquote { | |
| font-size: 1.42em; | |
| line-height: 1.38em; | |
| font-weight: 300; | |
| font-style: italic; | |
| } | |
| #article .pullquote:not(.float) { | |
| margin-top: 1em; | |
| margin-bottom: 1em; | |
| -webkit-margin-start: 1em; | |
| max-width: calc(100% - 1em); | |
| } | |
| #article .auxiliary > *:not(img) { | |
| -webkit-margin-start: 0; | |
| } | |
| #article .auxiliary.float img, #article .auxiliary > *:first-child:not(img) { | |
| margin: 0; | |
| } | |
| /* If the element immediately after an image is inline, it might bump up against the image. */ | |
| #article .auxiliary img + * { | |
| display: block; | |
| } | |
| #article .auxiliary figcaption { | |
| font-size: 100%; | |
| } | |
| #article .auxiliary * { | |
| margin-top: 0.5em; | |
| margin-bottom: 0.5em; | |
| } | |
| body:not(.watch) #article .float.left { | |
| float: left; | |
| margin-right: 20px; | |
| } | |
| body:not(.watch) #article .float.right { | |
| float: right; | |
| margin-left: 20px; | |
| } | |
| body.watch #article .float { | |
| width: auto !important; | |
| } | |
| #article .clear { | |
| clear: both; | |
| } | |
| #article ul.list-style-type-none, | |
| #article ol.list-style-type-none, | |
| #article .list-style-type-none > li { | |
| list-style-type: none; | |
| -webkit-padding-start: 0; | |
| } | |
| #article .page .list-style-type-none.code-block code { | |
| white-space: pre-wrap; | |
| } | |
| #article .page div.scrollable { | |
| overflow-x: scroll; | |
| word-wrap: normal; | |
| } | |
| #article .page div.scrollable table { | |
| max-width: none; | |
| } | |
| #article .leading-image, #article figure, #article .auxiliary:not(.pullquote) { | |
| font-family: -apple-system-font; | |
| } | |
| #article .leading-image, #article figure, #article .auxiliary, #article .pullquote { | |
| color: rgba(0, 0, 0, 0.65); | |
| } | |
| figure { | |
| margin: 0; | |
| } | |
| body:not(.watch) figure:not(.float) { | |
| margin-top: 1.4em; | |
| margin-bottom: 1.4em; | |
| } | |
| hr { | |
| background: rgba(0, 0, 0, 0.2); | |
| height: 1px; | |
| border: 0; | |
| } | |
| pre { | |
| font-family: -apple-system-ui-monospaced, Menlo; | |
| font-size: 0.87em; | |
| line-height: 1.45em; | |
| } | |
| blockquote, q { | |
| color: rgba(0, 0, 0, 0.65); | |
| } | |
| blockquote:not(.pullquote) { | |
| margin-left: 2px; | |
| margin-right: 6px; | |
| padding-left: 16px; | |
| } | |
| blockquote:not(.simple):not(.pullquote) { | |
| border-left: 3px solid rgba(0, 0, 0, 0.1); | |
| } | |
| q.pullquote { | |
| display: block; | |
| } | |
| .pullquote q::before, .pullquote q::after, q.pullquote::before, q.pullquote::after { | |
| content: ""; | |
| } | |
| /* Collapse excess whitespace. */ | |
| .page p > p:empty, | |
| .page div > p:empty, | |
| .page p > div:empty, | |
| .page div > div:empty, | |
| .page p + br, | |
| .page img + br | |
| { | |
| display: none; | |
| } | |
| .page table { | |
| font-size: 0.9em; | |
| text-align: start; | |
| word-wrap: break-word; | |
| border-collapse: collapse; | |
| } | |
| .page table td, .page table th { | |
| padding: 0.25em 0.5em; | |
| border: 1px solid rgb(216, 216, 216); | |
| } | |
| body.watch .page > * { | |
| margin-left: 0; | |
| margin-right: 0; | |
| } | |
| body.watch .page ol { | |
| padding: 0 0 0 35px; | |
| } | |
| body.watch .page ul { | |
| padding: 0 0 0 20px; | |
| } | |
| body.watch .page li { | |
| margin: 0.8em 0; | |
| } | |
| body.watch .page blockquote { | |
| padding: 0 0 0 8px; | |
| } | |
| .delimiter { | |
| margin-left: 0.45em; | |
| margin-right: 0.45em; | |
| margin-top: 0.07em; | |
| padding: 0; | |
| } | |
| .metadata.singleline .delimiter::after { | |
| content: "•"; | |
| } | |
| .metadata:not(.singleline) .delimiter { | |
| content: ""; | |
| display: block !important; | |
| } | |
| .page table th { | |
| background-color: rgba(0, 0, 0, 0.025); | |
| } | |
| .page sup, .page sub { | |
| line-height: 1; | |
| font-size: 0.75em; | |
| } | |
| .hidden { | |
| display: none; | |
| } | |
| /* Special Font Customizations */ | |
| .system { font-family: -apple-system-font; } | |
| .watch.system { font: -apple-system-body; } | |
| .yuantisc { | |
| letter-spacing: 1px; | |
| } | |
| .yuantitc { | |
| letter-spacing: 1px; | |
| } | |
| /* Printing and mailing. */ | |
| #article.exported { | |
| font-size: 1.2em; | |
| } | |
| .exported { | |
| line-height: 1.5em; | |
| } | |
| .exported a[href] { | |
| text-decoration: underline; | |
| } | |
| #article.exported { | |
| margin: 0; | |
| padding: 0; | |
| } | |
| .exported .float { | |
| float: none; | |
| margin-top: 1.4em; | |
| margin-bottom: 1.4em; | |
| } | |
| #article.exported .leading-image, | |
| #article.exported figcaption { | |
| font-size: 0.75rem; | |
| color: rgba(0, 0, 0, 0.8); | |
| } | |
| .exported .delimiter::after { | |
| content: ""; | |
| } | |
| </style> | |
| <style id="print"> | |
| @media print { | |
| body { | |
| margin: 2mm 9mm; | |
| } | |
| .original-url { | |
| display: none; | |
| } | |
| #article .float.left { | |
| float: left !important; | |
| } | |
| #article .float.right { | |
| float: right !important; | |
| } | |
| #article .float { | |
| margin-top: 0 !important; | |
| margin-bottom: 0 !important; | |
| } | |
| } | |
| </style> | |
| <style id="reader-ui"> | |
| @media screen { | |
| body { | |
| margin: 0; | |
| padding: 0; | |
| -webkit-user-select: none; | |
| overflow-x: hidden; | |
| -webkit-text-size-adjust: none; | |
| } | |
| body.mac { | |
| background-color: transparent; | |
| } | |
| #article { | |
| pointer-events: auto; | |
| -webkit-user-select: auto; | |
| overflow: visible; | |
| margin-bottom: 42vh !important; | |
| } | |
| #article:focus { | |
| outline: none; | |
| } | |
| .page-number { | |
| display: block; | |
| } | |
| #article :nth-child(1 of .page):nth-last-child(1 of .page) .page-number { | |
| display: none; | |
| } | |
| body.watch #article :nth-child(1 of .page):nth-last-child(1 of .page) { | |
| padding-top: 0.15em; | |
| } | |
| .page-number, #incoming-page-corner { | |
| font-weight: bold; | |
| position: absolute; | |
| -webkit-user-select: none; | |
| font: 12px "Helvetica Neue"; | |
| color: rgb(168, 168, 168); | |
| cursor: default; | |
| } | |
| body.watch :matches(.page-number, #incoming-page-corner) { | |
| top: 8px; | |
| right: 16px; | |
| } | |
| .page { | |
| margin-left: auto; | |
| margin-right: auto; | |
| padding-top: 35px; | |
| padding-bottom: 35px; | |
| position: relative; | |
| border-top: 1px solid rgba(0, 0, 0, 0.2); | |
| } | |
| body.watch .page { | |
| padding: 0 4px; | |
| } | |
| #article :nth-child(1 of .page) { | |
| margin-top: 0; | |
| border-top: none; | |
| padding-top: 32px; | |
| } | |
| .page:last-of-type { | |
| padding-bottom: 45px; | |
| } | |
| .page video { | |
| height: auto; | |
| position: relative; | |
| } | |
| #incoming-page-placeholder { | |
| height: 30px; | |
| margin-bottom: 0; | |
| } | |
| #incoming-page-corner { | |
| position: absolute; | |
| right: 10px; | |
| top: 8px; | |
| } | |
| #incoming-page-text { | |
| float: right; | |
| -webkit-user-select: none; | |
| } | |
| #next-page-container { | |
| position:absolute; | |
| /* Workaround for <rdar://problem/8662842> iOS Reader: loading multiple pages stops at the 2nd page. */ | |
| left: -1000px; | |
| /* The iframe needs to be wider than the width threshold value for Reader detection, see <rdar://problem/9599297>. */ | |
| width: 320px; | |
| height: 0px; | |
| } | |
| .page div.scrollable { | |
| -webkit-overflow-scrolling: touch; | |
| } | |
| } | |
| @media screen and (-webkit-min-device-pixel-ratio:2) { | |
| .page { | |
| border-top-width: 0.5px; | |
| } | |
| hr { | |
| height: 0.5px; | |
| } | |
| } | |
| #article .extendsBeyondTextColumn { | |
| max-width: none; | |
| } | |
| .iframe-wrapper { | |
| background-color: black; | |
| max-width: none; | |
| text-align: center; | |
| } | |
| iframe { | |
| border: 0; | |
| } | |
| @media screen and (min-width: 0px) { | |
| /* Includes iPhone 5 in portrait */ | |
| .page { padding-left: 16px; padding-right: 16px; } | |
| .page-number, #incoming-page-corner { | |
| top: 8px; | |
| right: 16px; | |
| } | |
| #article :nth-child(1 of .page):nth-last-child(1 of .page) { | |
| padding-top: 14px; | |
| } | |
| } | |
| @media screen and (min-width: 161px) { | |
| /* Apple Watch 40mm */ | |
| body.watch .page { | |
| padding: 0 8.5px; | |
| } | |
| } | |
| @media screen and (min-width: 183px) { | |
| /* Apple Watch 44mm */ | |
| body.watch .page { | |
| padding: 0 9.5px; | |
| } | |
| } | |
| @media screen and (min-width: 375px) { | |
| /* iPhone 6 in portrait */ | |
| .page { padding-left: 18px; padding-right: 18px; } | |
| .page-number, #incoming-page-corner { | |
| top: 6px; | |
| right: 18px; | |
| } | |
| #article :nth-child(1 of .page):nth-last-child(1 of .page) { | |
| padding-top: 16px; | |
| } | |
| } | |
| @media screen and (min-width: 414px) { | |
| /* iPhone 6 Plus in portrait */ | |
| .page { padding-left: 20px; padding-right: 20px; } | |
| .page-number, #incoming-page-corner { | |
| top: 6px; | |
| right: 20px; | |
| } | |
| #article :nth-child(1 of .page):nth-last-child(1 of .page) { | |
| padding-top: 18px; | |
| } | |
| } | |
| /* iPhone 5 in landscape (568px) */ | |
| @media screen and (min-width: 667px) { | |
| /* iPhone 6 in landscape */ | |
| .page { padding-left: 40px; padding-right: 40px; } | |
| .page-number, #incoming-page-corner { | |
| /* Stop lining this text up with .page's right margin. */ | |
| top: 10px; | |
| right: 10px; | |
| } | |
| #article :nth-child(1 of .page):nth-last-child(1 of .page) { | |
| padding-top: 26px; | |
| } | |
| } | |
| @media screen and (max-width: 569px) { | |
| /* iPhone 5 in landscape (568px) and smaller, including all iPhones in portrait */ | |
| h1.title { | |
| font-size: 1.5558em; | |
| } | |
| h1 { | |
| font-size: 1.4em; | |
| } | |
| h2 { | |
| font-size: 1.2777em; | |
| } | |
| h3 { | |
| font-size: 1.15em; | |
| } | |
| .subhead { | |
| font-size: 1.2222em; | |
| } | |
| .metadata { | |
| font-size: 0.9em; | |
| line-height: 1.6em; | |
| } | |
| .title + .metadata { | |
| margin-top: -0.65em; | |
| } | |
| } | |
| @media screen and (min-width: 704px) { | |
| /* iPad in landscape with the sidebar open */ | |
| .page { padding-left: 42px; padding-right: 42px; } | |
| } | |
| @media screen and (min-width: 736px) { | |
| /* iPhone 6 Plus in landscape */ | |
| .page { padding-left: 60px; padding-right: 60px; } | |
| #article :nth-child(1 of .page):nth-last-child(1 of .page) { | |
| padding-top: 46px; | |
| } | |
| } | |
| @media only screen and (min-width: 780px) { | |
| #article { | |
| max-width: 800px; | |
| margin: 0 auto; | |
| } | |
| /* Readable margins. */ | |
| body.system #article { max-width: 83.2ex; } | |
| body.athelas #article { max-width: 104ex; } | |
| body.charter #article { max-width: 86ex; } | |
| body.georgia #article { max-width: 94ex; } | |
| body.iowanoldstyle #article { max-width: 90ex; } | |
| body.palatino #article { max-width: 97ex; } | |
| body.seravek #article { max-width: 87ex; } | |
| body.timesnewroman #article { max-width: 97ex; } | |
| body.uiserif #article { max-width: 93ex; } | |
| :matches(body.pingfangsc, body.pingfangtc) #article { max-width: 87.6ex; } | |
| :matches(body.heitisc, body.heititc) #article { max-width: 74.8ex; } | |
| :matches(body.songtisc, body.songtitc) #article { max-width: 102ex; } | |
| :matches(body.kaitisc, body.kaititc) #article { max-width: 102ex; } | |
| :matches(body.yuantisc, body.yuantitc) #article { max-width: 86.2ex; } | |
| :matches(body.libiansc, body.libiantc) #article { max-width: 95ex; } | |
| :matches(body.weibeisc, body.weibeitc) #article { max-width: 99ex; } | |
| :matches(body.yuppysc, body.yuppytc) #article { max-width: 87.6ex; } | |
| body.hiraginosansw3 #article { max-width: 75.7ex; } | |
| body.hiraginokakugothicpron #article { max-width: 76.4ex; } | |
| body.hiraginominchopron #article { max-width: 77.5ex; } | |
| body.hiraginomarugothicpron #article { max-width: 75.1ex; } | |
| body.applesdgothicneo #article { max-width: 82ex; } | |
| body.nanumgothic #article { max-width: 88.6ex; } | |
| body.nanummyeongjo #article { max-width: 94.1ex; } | |
| .page { | |
| /* We don't want the lines seperating pages to extend beyond the primary text column. */ | |
| padding-left: 0px; | |
| padding-right: 0px; | |
| margin-left: 70px; | |
| margin-right: 70px; | |
| } | |
| } | |
| #article { | |
| -webkit-font-smoothing: subpixel-antialiased; | |
| } | |
| /* Reader's paper appearance. */ | |
| html.paper { | |
| height: 100%; | |
| } | |
| html.paper body { | |
| height: calc(100% - 44px); | |
| } | |
| html.paper body:after { | |
| content: ""; | |
| height: 22px; | |
| display: block; | |
| } | |
| /* Clearfix */ | |
| html.paper .page::after { | |
| content: ""; | |
| display: table; | |
| clear: both; | |
| } | |
| html.paper #article { | |
| min-height: 100%; | |
| margin: 22px auto 0 auto; | |
| } | |
| html.paper #article :nth-child(1 of .page), html.paper #article :nth-child(1 of .page):nth-last-child(1 of .page) { | |
| padding-top: 53px; | |
| } | |
| html.paper #article .page-number, html.paper #article #incoming-page-corner { | |
| /* Stop lining this text up with .page's right margin. */ | |
| top: 14px; | |
| right: 0px; | |
| } | |
| /* End Reader's paper appearance. */ | |
| /* Use slightly smaller page padding when vertically constrained. */ | |
| @media screen and (max-height: 700px) { | |
| .page { | |
| padding-top: 32px; | |
| padding-bottom: 32px; | |
| } | |
| } | |
| </style> | |
| <style id="theming"> | |
| body.white { | |
| --body-font-color: rgb(27, 27, 27); | |
| --assistant-secondary-color: rgb(27, 27, 27, 0.5); | |
| --horizontal-line-color: rgb(220, 220, 220); | |
| --assistant-sidebar-color: rgb(220, 220, 220); | |
| --paper-shadow-color: rgba(0, 0, 0, 0.2); | |
| --separator-color: rgb(220, 220, 220); | |
| --assistant-sidebar-color: rgb(220, 220, 220); | |
| --narrow-assistant-background-color: rgba(18, 18, 18, 0.1); | |
| } | |
| body.sepia { | |
| --body-font-color: rgb(79, 50, 28); | |
| --assistant-secondary-color: rgb(79, 50, 28, 0.5); | |
| --horizontal-line-color: rgb(230, 218, 201); | |
| --separator-color: rgb(204, 191, 157); | |
| --assistant-sidebar-color: rgb(230, 218, 201); | |
| --paper-shadow-color: rgba(0, 0, 0, 0.2); | |
| --narrow-assistant-background-color: rgba(18, 18, 18, 0.1); | |
| } | |
| body.gray { | |
| --body-font-color: rgba(255, 255, 255, 0.78); | |
| --assistant-secondary-color: rgba(255, 255, 255, 0.39); | |
| --horizontal-line-color: rgb(111, 111, 111); | |
| --separator-color: rgb(111, 111, 111); | |
| --assistant-sidebar-color: rgb(111, 111, 111); | |
| --narrow-assistant-background-color: rgba(18, 18, 18, 0.1); | |
| } | |
| body.night { | |
| --body-font-color: rgb(176, 176, 176); | |
| --assistant-secondary-color: rgb(176, 176, 176, 0.5); | |
| --horizontal-line-color: rgb(62, 62, 62); | |
| --separator-color: rgb(62, 62, 62); | |
| --assistant-sidebar-color: rgb(62, 62, 62); | |
| --narrow-assistant-background-color: rgba(50, 50, 50, 0.3); | |
| } | |
| body.night.oled { | |
| --body-font-color: rgb(210, 210, 210); | |
| --assistant-secondary-color: rgb(210, 210, 210, 0.5); | |
| --horizontal-line-color: rgba(210, 210, 210, 0.35); | |
| --separator-color: rgba(210, 210, 210, 0.35); | |
| --assistant-sidebar-color: rgba(210, 210, 210, 0.35); | |
| --narrow-assistant-background-color: rgba(50, 50, 50, 0.3); | |
| } | |
| body.watch.night.oled { | |
| --body-font-color: rgb(174, 180, 191); | |
| } | |
| html:not(.paper) body.white, body.white #article { | |
| background-color: white; | |
| } | |
| html:not(.paper) body.sepia, body.sepia #article { | |
| background-color: rgb(248, 241, 227); | |
| } | |
| html:not(.paper) body.gray, body.gray #article { | |
| background-color: rgb(74, 74, 77); | |
| } | |
| html:not(.paper) body.night, body.night #article { | |
| background-color: rgb(18, 18, 18); | |
| } | |
| html:not(.paper) body.night.oled, body.night.oled #article { | |
| background-color: black; | |
| } | |
| /* OS X Reader draws backdrop background colors outside of web content, so the follow set only applies to iOS. */ | |
| html.paper body.ios.white { | |
| background-color: rgb(230, 230, 230); | |
| } | |
| html.paper body.ios.sepia { | |
| background-color: rgb(224, 216, 200); | |
| } | |
| html.paper body.ios.gray { | |
| background-color: rgb(50, 50, 51); | |
| } | |
| html.paper body.ios.night { | |
| background-color: black; | |
| } | |
| body.watch.night .metadata * { | |
| color: rgb(214, 217, 223) !important; | |
| } | |
| html.paper body.white #article, html.paper body.sepia #article { | |
| box-shadow: 0px 6px 12px 3px var(--paper-shadow-color); | |
| } | |
| html.paper body.gray #article { | |
| box-shadow: 0px 6px 12px 3px rgba(0, 0, 0, 0.24); | |
| } | |
| html.paper body.night #article { | |
| outline: 1px solid #272727; | |
| } | |
| body.watch.night.oled :matches(h1, h2, h3, h4, h5, h6) { | |
| color: white; | |
| } | |
| body.sepia #article :matches(.leading-image, figure, .auxiliary, .pullquote) { | |
| color: rgba(79, 50, 28, 0.9); | |
| } | |
| body.gray #article :matches(.leading-image, figure, .auxiliary, .pullquote) { | |
| color: rgba(255, 255, 255, 0.7); | |
| } | |
| body.night #article :matches(.leading-image, figure, .auxiliary, .pullquote) { | |
| color: rgba(255, 255, 255, 0.67); | |
| } | |
| body.night.oled #article :matches(.leading-image, figure, .auxiliary, .pullquote) { | |
| color: rgba(210, 210, 210, 0.9); | |
| } | |
| body.sepia #article a[href] { | |
| color: rgb(209, 150, 0); | |
| } | |
| body.gray #article a[href], body.night #article a[href] { | |
| color: rgb(90, 200, 250); | |
| } | |
| body.watch.night.oled #article a[href] { | |
| color: rgb(32, 148, 250); | |
| } | |
| body #article :matches(.page, .metadata a[href]) { | |
| color: var(--body-font-color); | |
| } | |
| body #article .page { | |
| border-top-color: var(--horizontal-line-color); | |
| } | |
| body #article hr { | |
| background: var(--horizontal-line-color); | |
| } | |
| body #assistant-container p { | |
| color: var(--assistant-secondary-color); | |
| } | |
| body #assistant-container ol { | |
| color: var(--assistant-secondary-color); | |
| } | |
| body #assistant-container h2 { | |
| color: var(--body-font-color); | |
| font-size: 1.43em; | |
| } | |
| body #assistant-container h3 { | |
| color: var(--body-font-color); | |
| font-size: 1.25em; | |
| } | |
| body #assistant-container h1 { | |
| font-size: 1.5em; | |
| line-height: 1.4em; | |
| color: var(--body-font-color); | |
| margin: 0px; | |
| } | |
| body #assistant-container a { | |
| color: var(--assistant-secondary-color); | |
| } | |
| body #summary-container p { | |
| color: var(--assistant-secondary-color); | |
| margin: 0px; | |
| padding-top: 4px; | |
| } | |
| body #summary-container h2 { | |
| color: var(--body-font-color); | |
| } | |
| body #summary-container h1 { | |
| color: var(--body-font-color); | |
| } | |
| body #tableOfContentsInsideArticle-list a { | |
| color: var(--body-font-color); | |
| font-size: 1em; | |
| } | |
| body #innerAssistantContainer p { | |
| color: var(--body-font-color); | |
| margin-top: 0; | |
| margin-bottom: 0.4em; | |
| } | |
| body #innerAssistantContainer ol { | |
| color: var(--body-font-color); | |
| } | |
| body #innerAssistantContainer li { | |
| margin-left: 2em; | |
| } | |
| body #innerAssistantContainer ol li::marker { | |
| color: var(--assistant-secondary-color); | |
| } | |
| body #innerAssistantContainer button { | |
| color: var(--body-font-color); | |
| font-size: 1em; | |
| } | |
| body #onDeviceSummaryButton { | |
| color: var(--body-font-color); | |
| } | |
| body.sepia .subhead { | |
| color: rgba(79, 50, 28, 0.72); | |
| } | |
| body.gray .subhead { | |
| color: rgba(255, 255, 255, 0.65); | |
| } | |
| body.night .subhead { | |
| color: rgba(185, 185, 185, 0.9); | |
| } | |
| body.night.oled .subhead { | |
| color: rgba(210, 210, 210, 0.85); | |
| } | |
| body.sepia :matches(#article .page-number, #incoming-page-corner) { | |
| color: rgba(63, 41, 23, 0.5); | |
| } | |
| body.gray :matches(#article .page-number, #incoming-page-corner) { | |
| color: rgba(255, 255, 255, 0.45); | |
| } | |
| body.night :matches(#article .page-number, #incoming-page-corner) { | |
| color: rgba(255, 255, 255, 0.55); | |
| } | |
| body.night.oled :matches(#article .page-number, #incoming-page-corner) { | |
| color: rgba(210, 210, 210, 0.8); | |
| } | |
| body.sepia #article blockquote, body.sepia #article q { | |
| color: rgb(140, 112, 79); | |
| } | |
| body.sepia #article blockquote:not(.simple):not(.pullquote) { | |
| border-left-color: rgba(154, 128, 92, 0.1); | |
| } | |
| body.gray #article blockquote, body.gray #article q { | |
| color: rgba(255, 255, 255, 0.6); | |
| } | |
| body.gray #article blockquote:not(.simple):not(.pullquote) { | |
| border-left-color: rgba(255, 255, 255, 0.15); | |
| } | |
| body.night #article blockquote, body.night #article q { | |
| color: rgba(255, 255, 255, 0.6); | |
| } | |
| body.night #article blockquote:not(.simple):not(.pullquote) { | |
| border-left-color: rgba(255, 255, 255, 0.15); | |
| } | |
| body.night.oled #article blockquote, body.night.oled #article q { | |
| color: rgba(210, 210, 210, 0.85); | |
| } | |
| body.night.oled #article blockquote:not(.simple):not(.pullquote) { | |
| border-left-color: rgba(210, 210, 210, 0.2); | |
| } | |
| body.watch.night #article blockquote, body.watch.night #article q { | |
| color: var(--body-font-color); | |
| } | |
| body.watch.night #article blockquote:not(.simple):not(.pullquote) { | |
| border-left-color: rgb(51, 51, 51); | |
| } | |
| body.sepia table :matches(td, th) { | |
| border-color: rgb(230, 218, 202); | |
| } | |
| body.sepia table th { | |
| background-color: rgba(154, 128, 92, 0.06); | |
| } | |
| body.gray table :matches(td, th) { | |
| border-color: rgb(106, 106, 106); | |
| } | |
| body.gray table th { | |
| background-color: rgba(255, 255, 255, 0.035); | |
| } | |
| body.night table :matches(td, th) { | |
| border-color: rgb(50, 50, 50); | |
| } | |
| body.night table th { | |
| background-color: rgba(255, 255, 255, 0.045); | |
| } | |
| body.night.oled table th { | |
| background-color: rgba(255, 255, 255, 0.075); | |
| } | |
| @media (inverted-colors) { | |
| /* If the user has turned on the "smart invert" accessibility preference, they generally prefer | |
| their images, such as photos, to not be inverted. Provide this by applying a filter that | |
| inverts the colors again (effectively un-inverting). */ | |
| body:not(.gray):not(.night) #article :matches(img, video) { | |
| filter: invert(); | |
| } | |
| body:not(.gray):not(.night) #article picture { | |
| filter: none !important; | |
| } | |
| body.gray, body.night { | |
| filter: invert(); | |
| } | |
| body:matches(.gray, .night) #article :matches(img:not(picture > img), picture, video) { | |
| filter: none !important; | |
| } | |
| body:matches(.gray, .night) #article iframe { | |
| filter: invert(); | |
| } | |
| html.paper body.white #article, html.paper body.sepia #article { | |
| --paper-shadow-color: rgba(255, 255, 255, 0.2); | |
| } | |
| /* The background color of <body> is not inverted by the filter. Achieve this by manually | |
| setting the inverse color. */ | |
| html:not(.paper) body.gray { | |
| background-color: rgb(165, 165, 163) !important; | |
| } | |
| html.paper body.gray { | |
| background-color: rgb(205, 205, 204) !important; | |
| } | |
| html:not(.paper) body.night { | |
| background-color: rgb(237, 237, 237) !important; | |
| } | |
| html:not(.paper) body.night.oled { | |
| background-color: white !important; | |
| } | |
| html.paper body.night { | |
| background-color: white !important; | |
| } | |
| } | |
| </style> | |
| <style id="locale-specific-adjustments"> | |
| .locale-ja .page { | |
| text-align: justify; | |
| } | |
| .locale-zh-Hans .page { | |
| text-align: justify; | |
| } | |
| .locale-zh-Hant .page { | |
| text-align: justify; | |
| word-break: break-all; | |
| } | |
| .locale-hi .title { | |
| line-height: 1.65em; | |
| } | |
| /* See 32728279 and 54061051. */ | |
| .locale-ur.notonastaliqurdu :matches(h1, h2, h3, h4, h5, h6) { | |
| font-weight: normal; | |
| line-height: 2.55em; | |
| } | |
| </style> | |
| <style id="dynamic-article-content"></style> | |
| <!-- For Twitter’s script to find and script world to be created (see 34937240). --> | |
| <script> | |
| window.isReaderPage = true; | |
| </script> | |
| </head> | |
| <body> | |
| <iframe aria-hidden="true" id="next-page-container"></iframe> | |
| <div id="article" role="article"> | |
| <!-- This node will contain a number of div.page. --> | |
| </div> | |
| </body> | |
| </html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * Copyright (C) 2010 Apple Inc. All rights reserved. | |
| * | |
| * Redistribution and use in source and binary forms, with or without | |
| * modification, are permitted provided that the following conditions | |
| * are met: | |
| * | |
| * 1. Redistributions of source code must retain the above copyright | |
| * notice, this list of conditions and the following disclaimer. | |
| * 2. Redistributions in binary form must reproduce the above copyright | |
| * notice, this list of conditions and the following disclaimer in the | |
| * documentation and/or other materials provided with the distribution. | |
| * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of | |
| * its contributors may be used to endorse or promote products derived | |
| * from this software without specific prior written permission. | |
| * | |
| * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY | |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
| * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY | |
| * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
| * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| */ | |
| // Utilities taken from WebCore/inspector/front-end/utilities.js with some additions for Safari. | |
| Object.type = function(obj, win) | |
| { | |
| if (obj === null) | |
| return "null"; | |
| var type = typeof obj; | |
| if (type !== "object" && type !== "function") | |
| return type; | |
| win = win || window; | |
| if (obj instanceof win.Node) | |
| return "node"; | |
| if (obj instanceof win.String) | |
| return "string"; | |
| if (obj instanceof win.Array) | |
| return "array"; | |
| if (obj instanceof win.Boolean) | |
| return "boolean"; | |
| if (obj instanceof win.Number) | |
| return "number"; | |
| if (obj instanceof win.Date) | |
| return "date"; | |
| if (obj instanceof win.RegExp) | |
| return "regexp"; | |
| if (obj instanceof win.Error) | |
| return "error"; | |
| return type; | |
| } | |
| Function.prototype.bind = function(thisObject) | |
| { | |
| var func = this; | |
| var args = Array.prototype.slice.call(arguments, 1); | |
| return function() { return func.apply(thisObject, args.concat(Array.prototype.slice.call(arguments, 0))) }; | |
| } | |
| String.prototype.format = function() | |
| { | |
| var stringParts = this.split("%@"); | |
| for (var i = 0; i < arguments.length; ++i) | |
| stringParts.splice(i * 2 + 1, 0, arguments[i].toString()); | |
| return stringParts.join(""); | |
| } | |
| Element.prototype.indexOfChildNode = function(childNode) | |
| { | |
| var childNodes = this.childNodes; | |
| for (var i = 0; i < childNodes.length; ++i) { | |
| if (childNodes[i] === childNode) | |
| return i; | |
| } | |
| return -1; | |
| } | |
| Element.prototype.removeChildren = function() | |
| { | |
| while (this.firstChild) | |
| this.removeChild(this.firstChild); | |
| } | |
| Element.prototype.__defineGetter__("totalOffsetLeft", function() | |
| { | |
| var total = 0; | |
| for (var element = this; element; element = element.offsetParent) | |
| total += element.offsetLeft + (this !== element ? element.clientLeft : 0); | |
| return total; | |
| }); | |
| Element.prototype.__defineGetter__("totalOffsetTop", function() | |
| { | |
| var total = 0; | |
| for (var element = this; element; element = element.offsetParent) | |
| total += element.offsetTop + (this !== element ? element.clientTop : 0); | |
| return total; | |
| }); | |
| Element.prototype.__defineGetter__("totalScrollTop", function() | |
| { | |
| var total = 0; | |
| for (var element = this; element; element = element.offsetParent) | |
| total += element.scrollTop; | |
| return total; | |
| }); | |
| Array.prototype.remove = function(value, onlyFirst) | |
| { | |
| if (onlyFirst) { | |
| var index = this.indexOf(value); | |
| if (index !== -1) | |
| this.splice(index, 1); | |
| return; | |
| } | |
| var length = this.length; | |
| for (var i = 0; i < length; ++i) { | |
| if (this[i] === value) | |
| this.splice(i, 1); | |
| } | |
| } | |
| // @param element (HTML Element) The element whose total offset from left edge of the | |
| // page is desired. | |
| // @return (integer) The total offset from the left edge of the page if the element is | |
| // not null or undefined or does not have a defined offsetLeft. -1 otherwise. | |
| function totalLeftOffset(element) | |
| { | |
| if (!element || typeof element.offsetLeft === "undefined") | |
| return -1; | |
| return element.totalOffsetLeft; | |
| } | |
| // @param element (HTML Element) The element whose total offset from top edge of the | |
| // page is desired. | |
| // @return (integer) The total offset from the top edge of the page if the element is | |
| // not null or undefined or does not have a defined offsetTop. -1 otherwise. | |
| function totalTopOffset(element) | |
| { | |
| if (!element || typeof element.offsetTop === "undefined") | |
| return -1; | |
| return element.totalOffsetTop; | |
| } | |
| Node.prototype.enclosingNodeOrSelfWithNodeNameInArray = function(nameArray) | |
| { | |
| for (var node = this; node && node !== this.ownerDocument; node = node.parentNode) | |
| for (var i = 0; i < nameArray.length; ++i) | |
| if (node.nodeName.toLowerCase() === nameArray[i].toLowerCase()) | |
| return node; | |
| return null; | |
| } | |
| Node.prototype.enclosingNodeOrSelfWithNodeName = function(nodeName) | |
| { | |
| return this.enclosingNodeOrSelfWithNodeNameInArray([nodeName]); | |
| } | |
| Number.constrain = function(num, min, max) | |
| { | |
| if (num < min) | |
| num = min; | |
| else if (num > max) | |
| num = max; | |
| return num; | |
| } | |
| // JS class inheritance. NOTE: You should use the __proto__ approach instead of this. | |
| var JSClass = { | |
| inherit: function(subclass, baseClass) { | |
| function inheritance() { } | |
| inheritance.prototype = baseClass.prototype; | |
| subclass.prototype = new inheritance(); | |
| subclass.prototype.constructor = subclass; | |
| subclass.baseConstructor = baseClass; | |
| subclass.superClass = baseClass.prototype; | |
| } | |
| } | |
| // Dragging utilities --------------------------------------------------------- | |
| var Direction = { | |
| HORIZONTAL: 0, | |
| VERTICAL: 1, | |
| }; | |
| var Dragger = { | |
| // Sets up and starts the drag of an HTML element. | |
| // | |
| // @param element (HTML element) Element to drag. | |
| // @param elementDragging (function (event)) Function to be called while | |
| // element is dragging. | |
| // @param elementDragEnd (function (event)) Function to be called when the | |
| // drag ends. | |
| // @param event (event) The event that triggered the drag. | |
| // @param cursor (string) The cursor style to use while dragging. | |
| elementDragStart: function(element, elementDragging, elementDragEnd, event, cursor) | |
| { | |
| if (this._elementDraggingEventListener || this._elementEndDraggingEventListener) | |
| this.elementDragEnd(event); | |
| this._elementDraggingEventListener = elementDragging; | |
| this._elementEndDraggingEventListener = elementDragEnd; | |
| document.addEventListener("mousemove", elementDragging, true); | |
| document.addEventListener("mouseup", elementDragEnd, true); | |
| document.body.style.cursor = cursor; | |
| event.preventDefault(); | |
| }, | |
| // Finishes and tears down the drag of an element. | |
| // | |
| // @param event (event) Event that causes the drag to end. | |
| elementDragEnd: function(event) | |
| { | |
| document.removeEventListener("mousemove", this._elementDraggingEventListener, true); | |
| document.removeEventListener("mouseup", this._elementEndDraggingEventListener, true); | |
| document.body.style.removeProperty("cursor"); | |
| delete this._elementDraggingEventListener; | |
| delete this._elementEndDraggingEventListener; | |
| event.preventDefault(); | |
| }, | |
| // Updates the position of the element and all the elements around it. | |
| // If the direction of movement is horizontal (Dragger.HORIZONTAL), then A | |
| // is "left" and B is "right". | |
| // If the direction of movement is vertical (Dragger.VERTICAL), then A is | |
| // "above" and B is "below". | |
| // | |
| // @param element (HTML element) The element whose position to update. | |
| // @param direction (Direction.HORIZONTAL | Direction.VERTICAL) The direction | |
| // in which the element is moving. | |
| // @param elementsToA (array of HTML elements) The elements to the A of the | |
| // element. | |
| // @param elementsToB (array of HTML elements) The elements to the B of the | |
| // element. | |
| // @param distanceToDragPoint (integer) The distance in pixels from the | |
| // dragPoint to where the element should be placed. | |
| // @param minPos (integer) The minimum position the element can be at. | |
| // @param maxPos (integer) The maximum position the element can be at. | |
| // @param dragPoint (integer) The point at which the element has been | |
| // dragged to. | |
| updateElementPosition: function(element, direction, elementsToA, elementsToB, | |
| distanceToDragPoint, minPos, maxPos, dragPoint) | |
| { | |
| if ((direction == Direction.HORIZONTAL && elementsToA[0].offsetWidth <= 0) | |
| || (elementsToA[0].offsetHeight <= 0)) { | |
| // The stylesheet hasn't loaded yet or the window is closed, | |
| // so we can't calculate what is need. Return early. | |
| return; | |
| } | |
| if (!("_currentElementPosition" in elementsToA[0])) { | |
| if (direction == Direction.HORIZONTAL) | |
| elementsToA[0]._currentElementPosition = elementsToA[0].offsetWidth; | |
| else | |
| elementsToA[0]._currentElementPosition = elementsToA[0].offsetHeight; | |
| } | |
| if (typeof dragPoint === "undefined") | |
| dragPoint = elementsToA[0]._currentElementPosition; | |
| dragPoint = Number.constrain(dragPoint, minPos, maxPos); | |
| elementsToA[0]._currentElementPosition = dragPoint; | |
| for (var i = 0; i < elementsToA.length; i++) { | |
| if (direction == Direction.HORIZONTAL) | |
| elementsToA[i].style.width = dragPoint + "px"; | |
| else | |
| elementsToA[i].style.height = dragPoint + "px"; | |
| } | |
| for (var j = 0; j < elementsToB.length; j++) { | |
| if (direction == Direction.HORIZONTAL) | |
| elementsToB[j].style.left = dragPoint + "px"; | |
| else | |
| elementsToB[j].style.top = dragPoint + "px"; | |
| } | |
| if (direction == Direction.HORIZONTAL) | |
| element.style.left = (dragPoint - distanceToDragPoint) + "px"; | |
| else | |
| element.style.top = (dragPoint - distanceToDragPoint) + "px"; | |
| } | |
| }; | |
| // Listeners (taken from the WebInspector.Object in | |
| // WebCore\inspector\frontend\Object.js) | |
| Listeners = function() { | |
| } | |
| Listeners.prototype = { | |
| addEventListener: function(eventType, listener, thisObject) { | |
| if (!("_listeners" in this)) | |
| this._listeners = {}; | |
| if (!(eventType in this._listeners)) | |
| this._listeners[eventType] = []; | |
| this._listeners[eventType].push({ thisObject: thisObject, listener: listener }); | |
| }, | |
| removeEventListener: function(eventType, listener, thisObject) { | |
| if (!("_listeners" in this) || !(eventType in this._listeners)) | |
| return; | |
| var listeners = this._listeners[eventType]; | |
| for (var i = 0; i < listeners.length; ++i) { | |
| if (listener && listeners[i].listener === listener && listeners[i].thisObject === thisObject) | |
| listeners.splice(i, 1); | |
| else if (!listener && thisObject && listeners[i].thisObject === thisObject) | |
| listeners.splice(i, 1); | |
| } | |
| if (!listeners.length) | |
| delete this._listeners[eventType]; | |
| }, | |
| dispatchEventToListeners: function(eventType) { | |
| if (!("_listeners" in this) || !(eventType in this._listeners)) | |
| return; | |
| var stoppedPropagation = false; | |
| function stopPropagation() | |
| { | |
| stoppedPropagation = true; | |
| } | |
| function preventDefault() | |
| { | |
| this.defaultPrevented = true; | |
| } | |
| var event = {target: this, type: eventType, defaultPrevented: false}; | |
| event.stopPropagation = stopPropagation.bind(event); | |
| event.preventDefault = preventDefault.bind(event); | |
| var listeners = this._listeners[eventType]; | |
| for (var i = 0; i < listeners.length; ++i) { | |
| listeners[i].listener.call(listeners[i].thisObject, event); | |
| if (stoppedPropagation) | |
| break; | |
| } | |
| return event.defaultPrevented; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "1rx.io": { | |
| "d": "RhythmOne" | |
| }, | |
| "2mdn.net": { | |
| "d": "Google" | |
| }, | |
| "2o7.net": { | |
| "d": "Adobe" | |
| }, | |
| "33across.com": { | |
| "d": "33Across" | |
| }, | |
| "360yield.com": { | |
| "d": "Improve Digital" | |
| }, | |
| "3lift.com": { | |
| "d": "TripleLift" | |
| }, | |
| "abtasty.com": { | |
| "d": "AB Tasty" | |
| }, | |
| "acuityplatform.com": { | |
| "d": "AcuityAds" | |
| }, | |
| "addthis.com": { | |
| "d": "Oracle" | |
| }, | |
| "addtoany.com": { | |
| "d": "AddToAny" | |
| }, | |
| "adentifi.com": { | |
| "d": "AdTheorent" | |
| }, | |
| "adform.net": { | |
| "d": "Adform" | |
| }, | |
| "adgrx.com": { | |
| "d": "AdGear" | |
| }, | |
| "adhigh.net": { | |
| "d": "GetIntent" | |
| }, | |
| "adition.com": { | |
| "d": "Virtual Minds" | |
| }, | |
| "adkernel.com": { | |
| "d": "Adkernel" | |
| }, | |
| "adlightning.com": { | |
| "d": "Ad Lightning" | |
| }, | |
| "admedo.com": { | |
| "d": "Admedo" | |
| }, | |
| "admixer.net": { | |
| "d": "Admixer" | |
| }, | |
| "adnxs.com": { | |
| "d": "Microsoft" | |
| }, | |
| "adobedtm.com": { | |
| "d": "Adobe" | |
| }, | |
| "adotmob.com": { | |
| "d": "A.Mob" | |
| }, | |
| "adriver.ru": { | |
| "d": "Internest-holding" | |
| }, | |
| "adroll.com": { | |
| "d": "AdRoll" | |
| }, | |
| "ads-twitter.com": { | |
| "d": "Twitter" | |
| }, | |
| "adsafeprotected.com": { | |
| "d": "Integral Ad Science" | |
| }, | |
| "adscale.de": { | |
| "d": "Ströer Group" | |
| }, | |
| "adsco.re": { | |
| "d": "Adscore" | |
| }, | |
| "adsrvr.org": { | |
| "d": "The Trade Desk" | |
| }, | |
| "adstanding.com": { | |
| "d": "AdStanding" | |
| }, | |
| "adswizz.com": { | |
| "d": "Sirius XM" | |
| }, | |
| "adtdp.com": { | |
| "d": "CyberAgent" | |
| }, | |
| "adthrive.com": { | |
| "d": "AdThrive" | |
| }, | |
| "advertising.com": { | |
| "d": "Verizon Media" | |
| }, | |
| "affec.tv": { | |
| "d": "Affectv" | |
| }, | |
| "agkn.com": { | |
| "d": "Neustar" | |
| }, | |
| "aidata.io": { | |
| "d": "Aidata" | |
| }, | |
| "amazon-adsystem.com": { | |
| "d": "Amazon" | |
| }, | |
| "amplitude.com": { | |
| "d": "Amplitude" | |
| }, | |
| "amung.us": { | |
| "d": "whos.amung.us" | |
| }, | |
| "app.link": { | |
| "d": "Branch Metrics" | |
| }, | |
| "appdynamics.com": { | |
| "d": "Cisco Systems" | |
| }, | |
| "appier.net": { | |
| "d": "Appier" | |
| }, | |
| "attn.tv": { | |
| "d": "Attentive Mobile" | |
| }, | |
| "basis.net": { | |
| "d": "Centro" | |
| }, | |
| "betrad.com": { | |
| "d": "Crownpeak" | |
| }, | |
| "betweendigital.com": { | |
| "d": "SSP Network" | |
| }, | |
| "bfmio.com": { | |
| "d": "Beachfront Media" | |
| }, | |
| "bidr.io": { | |
| "d": "Beeswax" | |
| }, | |
| "bidswitch.net": { | |
| "d": "IPONWEB" | |
| }, | |
| "bing.com": { | |
| "d": "Microsoft" | |
| }, | |
| "bkrtx.com": { | |
| "d": "Oracle" | |
| }, | |
| "blismedia.com": { | |
| "d": "Blis" | |
| }, | |
| "bluecava.com": { | |
| "d": "ALC" | |
| }, | |
| "blueconic.net": { | |
| "d": "BlueConic" | |
| }, | |
| "bluekai.com": { | |
| "d": "Oracle" | |
| }, | |
| "bounceexchange.com": { | |
| "d": "Bounce Exchange" | |
| }, | |
| "branch.io": { | |
| "d": "Branch Metrics" | |
| }, | |
| "brealtime.com": { | |
| "d": "EMX Digital" | |
| }, | |
| "browser-update.org": { | |
| "d": "Browser Update" | |
| }, | |
| "bttrack.com": { | |
| "d": "Bidtellect" | |
| }, | |
| "buysellads.com": { | |
| "d": "BuySellAds" | |
| }, | |
| "casalemedia.com": { | |
| "d": "Index Exchange" | |
| }, | |
| "cdnwidget.com": { | |
| "d": "CDNWIDGET.COM" | |
| }, | |
| "chartbeat.com": { | |
| "d": "Chartbeat" | |
| }, | |
| "chaturbate.com": { | |
| "d": "Chaturbate" | |
| }, | |
| "clickagy.com": { | |
| "d": "Clickagy" | |
| }, | |
| "clickcertain.com": { | |
| "d": "ClickCertain" | |
| }, | |
| "clicktale.net": { | |
| "d": "ClickTale" | |
| }, | |
| "colossusssp.com": { | |
| "d": "Colossus Media" | |
| }, | |
| "company-target.com": { | |
| "d": "Demandbase" | |
| }, | |
| "consentmanager.net": { | |
| "d": "ConsentManager" | |
| }, | |
| "contentsquare.net": { | |
| "d": "ContentSquare" | |
| }, | |
| "contextweb.com": { | |
| "d": "Pulsepoint" | |
| }, | |
| "cookiepro.com": { | |
| "d": "OneTrust" | |
| }, | |
| "cpx.to": { | |
| "d": "Captify" | |
| }, | |
| "cquotient.com": { | |
| "d": "Salesforce.com" | |
| }, | |
| "crazyegg.com": { | |
| "d": "Crazy Egg" | |
| }, | |
| "creative-serving.com": { | |
| "d": "Platform161" | |
| }, | |
| "creativecdn.com": { | |
| "d": "RTB House" | |
| }, | |
| "criteo.com": { | |
| "d": "Criteo" | |
| }, | |
| "criteo.net": { | |
| "d": "Criteo" | |
| }, | |
| "crsspxl.com": { | |
| "d": "Cross Pixel Media" | |
| }, | |
| "crwdcntrl.net": { | |
| "d": "Lotame Solutions" | |
| }, | |
| "ctnsnet.com": { | |
| "d": "Crimtan Holdings" | |
| }, | |
| "cxense.com": { | |
| "d": "Piano Software" | |
| }, | |
| "deepintent.com": { | |
| "d": "DeepIntent" | |
| }, | |
| "demandbase.com": { | |
| "d": "Demandbase" | |
| }, | |
| "demdex.net": { | |
| "d": "Adobe" | |
| }, | |
| "disqus.com": { | |
| "d": "Disqus" | |
| }, | |
| "dotomi.com": { | |
| "d": "Conversant" | |
| }, | |
| "doubleclick.net": { | |
| "d": "Google" | |
| }, | |
| "doubleverify.com": { | |
| "d": "DoubleVerify" | |
| }, | |
| "driftt.com": { | |
| "d": "Drift.com" | |
| }, | |
| "dtscout.com": { | |
| "d": "DTS" | |
| }, | |
| "dwin1.com": { | |
| "d": "Awin" | |
| }, | |
| "dynamicyield.com": { | |
| "d": "Dynamic Yield" | |
| }, | |
| "e-planning.net": { | |
| "d": "Teroa" | |
| }, | |
| "eloqua.com": { | |
| "d": "Oracle" | |
| }, | |
| "emxdgt.com": { | |
| "d": "Engine USA" | |
| }, | |
| "en25.com": { | |
| "d": "Oracle" | |
| }, | |
| "ensighten.com": { | |
| "d": "Ensighten" | |
| }, | |
| "everestjs.net": { | |
| "d": "Adobe" | |
| }, | |
| "everesttech.net": { | |
| "d": "Adobe" | |
| }, | |
| "evidon.com": { | |
| "d": "Crownpeak" | |
| }, | |
| "exelator.com": { | |
| "d": "The Nielsen Company" | |
| }, | |
| "exoclick.com": { | |
| "d": "ExoClick" | |
| }, | |
| "exosrv.com": { | |
| "d": "ExoClick" | |
| }, | |
| "exponential.com": { | |
| "d": "Exponential Interactive" | |
| }, | |
| "eyeota.net": { | |
| "d": "eyeota" | |
| }, | |
| "ezoic.net": { | |
| "d": "Ezoic" | |
| }, | |
| "facebook.com": { | |
| "d": "Facebook" | |
| }, | |
| "facebook.net": { | |
| "d": "Facebook" | |
| }, | |
| "fastly-insights.com": { | |
| "d": "Fastly" | |
| }, | |
| "flashtalking.com": { | |
| "d": "Flashtalking" | |
| }, | |
| "foresee.com": { | |
| "d": "ForeSee Results" | |
| }, | |
| "forter.com": { | |
| "d": "Forter" | |
| }, | |
| "fullstory.com": { | |
| "d": "FullStory" | |
| }, | |
| "fwmrm.net": { | |
| "d": "FreeWheel" | |
| }, | |
| "gemius.pl": { | |
| "d": "Gemius" | |
| }, | |
| "getclicky.com": { | |
| "d": "Roxr Software" | |
| }, | |
| "getsitecontrol.com": { | |
| "d": "GetWebCraft" | |
| }, | |
| "go-mpulse.net": { | |
| "d": "Akamai" | |
| }, | |
| "google-analytics.com": { | |
| "d": "Google" | |
| }, | |
| "googleadservices.com": { | |
| "d": "Google" | |
| }, | |
| "googlesyndication.com": { | |
| "d": "Google" | |
| }, | |
| "googletagmanager.com": { | |
| "d": "Google" | |
| }, | |
| "googletagservices.com": { | |
| "d": "Google" | |
| }, | |
| "gumgum.com": { | |
| "d": "GumGum" | |
| }, | |
| "heapanalytics.com": { | |
| "d": "Heap" | |
| }, | |
| "hellobar.com": { | |
| "d": "Crazy Egg" | |
| }, | |
| "histats.com": { | |
| "d": "wisecode" | |
| }, | |
| "hotjar.com": { | |
| "d": "Hotjar" | |
| }, | |
| "hs-analytics.net": { | |
| "d": "HubSpot" | |
| }, | |
| "hsadspixel.net": { | |
| "d": "HubSpot" | |
| }, | |
| "hsleadflows.net": { | |
| "d": "HubSpot" | |
| }, | |
| "hubspot.com": { | |
| "d": "HubSpot" | |
| }, | |
| "hybrid.ai": { | |
| "d": "Hybrid Adtech" | |
| }, | |
| "ib-ibi.com": { | |
| "d": "KBM Group" | |
| }, | |
| "id5-sync.com": { | |
| "d": "ID5" | |
| }, | |
| "igodigital.com": { | |
| "d": "Salesforce.com" | |
| }, | |
| "impactradius-event.com": { | |
| "d": "Impact" | |
| }, | |
| "imrworldwide.com": { | |
| "d": "The Nielsen Company" | |
| }, | |
| "indexww.com": { | |
| "d": "Index Exchange" | |
| }, | |
| "innovid.com": { | |
| "d": "Innovid Media" | |
| }, | |
| "insightexpressai.com": { | |
| "d": "Kantar Operations" | |
| }, | |
| "inspectlet.com": { | |
| "d": "Inspectlet" | |
| }, | |
| "instagram.com": { | |
| "d": "Facebook" | |
| }, | |
| "intentiq.com": { | |
| "d": "Intent IQ" | |
| }, | |
| "ipredictive.com": { | |
| "d": "Adelphic" | |
| }, | |
| "ispot.tv": { | |
| "d": "iSpot.tv" | |
| }, | |
| "juicyads.com": { | |
| "d": "JuicyAds" | |
| }, | |
| "justpremium.com": { | |
| "d": "JustPremium" | |
| }, | |
| "kampyle.com": { | |
| "d": "Medallia" | |
| }, | |
| "kargo.com": { | |
| "d": "Kargo" | |
| }, | |
| "klaviyo.com": { | |
| "d": "Klaviyo" | |
| }, | |
| "krxd.net": { | |
| "d": "Salesforce.com" | |
| }, | |
| "liadm.com": { | |
| "d": "LiveIntent" | |
| }, | |
| "lijit.com": { | |
| "d": "Sovrn Holdings" | |
| }, | |
| "linkedin.com": { | |
| "d": "Microsoft" | |
| }, | |
| "linksynergy.com": { | |
| "d": "Rakuten" | |
| }, | |
| "list-manage.com": { | |
| "d": "Intuit" | |
| }, | |
| "listrak.com": { | |
| "d": "Listrak" | |
| }, | |
| "listrakbi.com": { | |
| "d": "Listrak" | |
| }, | |
| "livechatinc.com": { | |
| "d": "LiveChat" | |
| }, | |
| "liveperson.net": { | |
| "d": "LivePerson" | |
| }, | |
| "lkqd.net": { | |
| "d": "Nexstar Media Group" | |
| }, | |
| "loopme.me": { | |
| "d": "LoopMe" | |
| }, | |
| "lpsnmedia.net": { | |
| "d": "LivePerson" | |
| }, | |
| "mail.ru": { | |
| "d": "VK" | |
| }, | |
| "mailchimp.com": { | |
| "d": "Intuit" | |
| }, | |
| "marketo.com": { | |
| "d": "Adobe" | |
| }, | |
| "marketo.net": { | |
| "d": "Adobe" | |
| }, | |
| "mathtag.com": { | |
| "d": "MediaMath" | |
| }, | |
| "maxmind.com": { | |
| "d": "MaxMind" | |
| }, | |
| "media.net": { | |
| "d": "Media.net Advertising" | |
| }, | |
| "media6degrees.com": { | |
| "d": "Dstillery" | |
| }, | |
| "mediarithmics.com": { | |
| "d": "mediarithmics" | |
| }, | |
| "mediavine.com": { | |
| "d": "Mediavine" | |
| }, | |
| "mediawallahscript.com": { | |
| "d": "MediaWallah" | |
| }, | |
| "mfadsrvr.com": { | |
| "d": "IPONWEB" | |
| }, | |
| "mgid.com": { | |
| "d": "MGID" | |
| }, | |
| "micpn.com": { | |
| "d": "Movable Ink" | |
| }, | |
| "microad.jp": { | |
| "d": "MicroAd" | |
| }, | |
| "mktoresp.com": { | |
| "d": "Adobe" | |
| }, | |
| "ml314.com": { | |
| "d": "Bombora" | |
| }, | |
| "moatads.com": { | |
| "d": "Oracle" | |
| }, | |
| "monetate.net": { | |
| "d": "Monetate" | |
| }, | |
| "mookie1.com": { | |
| "d": "WPP" | |
| }, | |
| "mouseflow.com": { | |
| "d": "Mouseflow" | |
| }, | |
| "mxpnl.com": { | |
| "d": "Mixpanel" | |
| }, | |
| "mxptint.net": { | |
| "d": "Valassis Digital" | |
| }, | |
| "navdmp.com": { | |
| "d": "Navegg" | |
| }, | |
| "newrelic.com": { | |
| "d": "New Relic" | |
| }, | |
| "ninthdecimal.com": { | |
| "d": "NinthDecimal" | |
| }, | |
| "npttech.com": { | |
| "d": "Piano Software" | |
| }, | |
| "nr-data.net": { | |
| "d": "New Relic" | |
| }, | |
| "ntv.io": { | |
| "d": "Nativo" | |
| }, | |
| "o333o.com": { | |
| "d": "AdSpyglass" | |
| }, | |
| "olark.com": { | |
| "d": "Olark" | |
| }, | |
| "omnitagjs.com": { | |
| "d": "Adyoulike" | |
| }, | |
| "omtrdc.net": { | |
| "d": "Adobe" | |
| }, | |
| "onesignal.com": { | |
| "d": "OneSignal" | |
| }, | |
| "online-metrix.net": { | |
| "d": "RELX Group" | |
| }, | |
| "openx.net": { | |
| "d": "OpenX" | |
| }, | |
| "opmnstr.com": { | |
| "d": "Retyp" | |
| }, | |
| "optimizely.com": { | |
| "d": "Optimizely" | |
| }, | |
| "outbrain.com": { | |
| "d": "Outbrain" | |
| }, | |
| "owneriq.net": { | |
| "d": "Inmar" | |
| }, | |
| "pardot.com": { | |
| "d": "Salesforce.com" | |
| }, | |
| "parsely.com": { | |
| "d": "Parsely" | |
| }, | |
| "paypal.com": { | |
| "d": "PayPal" | |
| }, | |
| "permutive.com": { | |
| "d": "Permutive" | |
| }, | |
| "pingdom.net": { | |
| "d": "Pingdom" | |
| }, | |
| "pippio.com": { | |
| "d": "LiveRamp" | |
| }, | |
| "postrelease.com": { | |
| "d": "Nativo" | |
| }, | |
| "pro-market.net": { | |
| "d": "Datonics" | |
| }, | |
| "pswec.com": { | |
| "d": "Proclivity Media" | |
| }, | |
| "pubmatic.com": { | |
| "d": "PubMatic" | |
| }, | |
| "px-cloud.net": { | |
| "d": "Human Security" | |
| }, | |
| "qualtrics.com": { | |
| "d": "SAP" | |
| }, | |
| "quantserve.com": { | |
| "d": "Quantcast" | |
| }, | |
| "quora.com": { | |
| "d": "Quora" | |
| }, | |
| "rambler.ru": { | |
| "d": "Rambler Internet Holding" | |
| }, | |
| "realsrv.com": { | |
| "d": "ExoClick" | |
| }, | |
| "reddit.com": { | |
| "d": "Reddit" | |
| }, | |
| "redditstatic.com": { | |
| "d": "Reddit" | |
| }, | |
| "reson8.com": { | |
| "d": "Resonate Networks" | |
| }, | |
| "revcontent.com": { | |
| "d": "RevContent" | |
| }, | |
| "rezync.com": { | |
| "d": "Zeta Global" | |
| }, | |
| "rfihub.com": { | |
| "d": "Zeta Global" | |
| }, | |
| "rfihub.net": { | |
| "d": "Zeta Global" | |
| }, | |
| "rkdms.com": { | |
| "d": "Merkle" | |
| }, | |
| "rlcdn.com": { | |
| "d": "LiveRamp" | |
| }, | |
| "rmtag.com": { | |
| "d": "Rakuten" | |
| }, | |
| "rqtrk.eu": { | |
| "d": "Roq.ad" | |
| }, | |
| "rtmark.net": { | |
| "d": "Propeller Ads" | |
| }, | |
| "rubiconproject.com": { | |
| "d": "Magnite" | |
| }, | |
| "rutarget.ru": { | |
| "d": "RuTarget" | |
| }, | |
| "s-onetag.com": { | |
| "d": "Sovrn Holdings" | |
| }, | |
| "s3xified.com": { | |
| "d": "AdMedia" | |
| }, | |
| "sail-horizon.com": { | |
| "d": "CM Group" | |
| }, | |
| "salesforceliveagent.com": { | |
| "d": "Salesforce.com" | |
| }, | |
| "samplicio.us": { | |
| "d": "Lucid Holdings" | |
| }, | |
| "sascdn.com": { | |
| "d": "Smartadserver" | |
| }, | |
| "sc-static.net": { | |
| "d": "Snap" | |
| }, | |
| "scarabresearch.com": { | |
| "d": "SAP" | |
| }, | |
| "scorecardresearch.com": { | |
| "d": "comScore" | |
| }, | |
| "securedvisit.com": { | |
| "d": "4Cite Marketing" | |
| }, | |
| "segment.com": { | |
| "d": "Segment.io" | |
| }, | |
| "segment.io": { | |
| "d": "Segment.io" | |
| }, | |
| "semasio.net": { | |
| "d": "Semasio" | |
| }, | |
| "serving-sys.com": { | |
| "d": "Amazon" | |
| }, | |
| "shareaholic.com": { | |
| "d": "Shareaholic" | |
| }, | |
| "sharethis.com": { | |
| "d": "ShareThis" | |
| }, | |
| "sharethrough.com": { | |
| "d": "Sharethrough" | |
| }, | |
| "simpli.fi": { | |
| "d": "Simplifi Holdings" | |
| }, | |
| "siteimproveanalytics.com": { | |
| "d": "Siteimprove" | |
| }, | |
| "sitescout.com": { | |
| "d": "Centro" | |
| }, | |
| "skimresources.com": { | |
| "d": "Skimbit" | |
| }, | |
| "smaato.net": { | |
| "d": "Smaato" | |
| }, | |
| "smartadserver.com": { | |
| "d": "Smartadserver" | |
| }, | |
| "snapchat.com": { | |
| "d": "Snap" | |
| }, | |
| "socdm.com": { | |
| "d": "Supership" | |
| }, | |
| "sojern.com": { | |
| "d": "Sojern" | |
| }, | |
| "sonobi.com": { | |
| "d": "Sonobi" | |
| }, | |
| "springserve.com": { | |
| "d": "SpringServe" | |
| }, | |
| "stackadapt.com": { | |
| "d": "Collective Roll" | |
| }, | |
| "statcounter.com": { | |
| "d": "StatCounter" | |
| }, | |
| "steelhousemedia.com": { | |
| "d": "Steel House" | |
| }, | |
| "stickyadstv.com": { | |
| "d": "FreeWheel" | |
| }, | |
| "storygize.net": { | |
| "d": "Storygize" | |
| }, | |
| "sundaysky.com": { | |
| "d": "SundaySky" | |
| }, | |
| "t.co": { | |
| "d": "Twitter" | |
| }, | |
| "taboola.com": { | |
| "d": "Taboola" | |
| }, | |
| "tagcommander.com": { | |
| "d": "Fjord" | |
| }, | |
| "tapad.com": { | |
| "d": "Tapad" | |
| }, | |
| "teads.tv": { | |
| "d": "Teads" | |
| }, | |
| "tealiumiq.com": { | |
| "d": "Tealium" | |
| }, | |
| "technoratimedia.com": { | |
| "d": "Synacor" | |
| }, | |
| "thrtle.com": { | |
| "d": "Throtle" | |
| }, | |
| "tinypass.com": { | |
| "d": "Piano Software" | |
| }, | |
| "tiqcdn.com": { | |
| "d": "Tealium" | |
| }, | |
| "tns-counter.ru": { | |
| "d": "ADFACT" | |
| }, | |
| "trackcmp.net": { | |
| "d": "ActiveCampaign" | |
| }, | |
| "treasuredata.com": { | |
| "d": "Treasure Data" | |
| }, | |
| "tremorhub.com": { | |
| "d": "Telaria" | |
| }, | |
| "tribalfusion.com": { | |
| "d": "Exponential Interactive" | |
| }, | |
| "tru.am": { | |
| "d": "trueAnthem" | |
| }, | |
| "truoptik.com": { | |
| "d": "21 Productions" | |
| }, | |
| "truste.com": { | |
| "d": "TrustArc" | |
| }, | |
| "trustpilot.com": { | |
| "d": "Trustpilot" | |
| }, | |
| "tsyndicate.com": { | |
| "d": "Traffic Stars" | |
| }, | |
| "tubemogul.com": { | |
| "d": "Adobe" | |
| }, | |
| "turn.com": { | |
| "d": "Amobee" | |
| }, | |
| "tvsquared.com": { | |
| "d": "TVSquared" | |
| }, | |
| "twitter.com": { | |
| "d": "Twitter" | |
| }, | |
| "tynt.com": { | |
| "d": "33Across" | |
| }, | |
| "ubembed.com": { | |
| "d": "Unbounce" | |
| }, | |
| "undertone.com": { | |
| "d": "Undertone Networks" | |
| }, | |
| "unrulymedia.com": { | |
| "d": "Unruly Group" | |
| }, | |
| "usabilla.com": { | |
| "d": "Momentive" | |
| }, | |
| "usemessages.com": { | |
| "d": "HubSpot" | |
| }, | |
| "usercentrics.eu": { | |
| "d": "Usercentrics" | |
| }, | |
| "userreport.com": { | |
| "d": "AudienceProject" | |
| }, | |
| "viglink.com": { | |
| "d": "Sovrn Holdings" | |
| }, | |
| "visualwebsiteoptimizer.com": { | |
| "d": "Wingify" | |
| }, | |
| "vk.com": { | |
| "d": "VK" | |
| }, | |
| "w55c.net": { | |
| "d": "Roku" | |
| }, | |
| "walmart.com": { | |
| "d": "Walmart" | |
| }, | |
| "weborama.fr": { | |
| "d": "Weborama" | |
| }, | |
| "webvisor.org": { | |
| "d": "Yandex" | |
| }, | |
| "xg4ken.com": { | |
| "d": "Kenshoo TLD" | |
| }, | |
| "xiti.com": { | |
| "d": "AT Internet" | |
| }, | |
| "yadro.ru": { | |
| "d": "ECO PC - Complex Solutions" | |
| }, | |
| "yahoo.co.jp": { | |
| "d": "LY-Corporation" | |
| }, | |
| "yahoo.com": { | |
| "d": "Verizon Media" | |
| }, | |
| "yandex.ru": { | |
| "d": "Yandex" | |
| }, | |
| "yieldlab.net": { | |
| "d": "Virtual Minds" | |
| }, | |
| "yieldmo.com": { | |
| "d": "YieldMo" | |
| }, | |
| "yieldoptimizer.com": { | |
| "d": "WarnerMedia" | |
| }, | |
| "yimg.jp": { | |
| "d": "LY-Corporation" | |
| }, | |
| "yotpo.com": { | |
| "d": "Yotpo" | |
| }, | |
| "ywxi.net": { | |
| "d": "PathDefender" | |
| }, | |
| "zemanta.com": { | |
| "d": "Outbrain" | |
| }, | |
| "zopim.com": { | |
| "d": "Zendesk" | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "LoginFormTypeKeywords": { | |
| "@me": 1, | |
| "welcome back": 1, | |
| "log on": 1, | |
| "登录": 1, | |
| "iniciar sesión": 1, | |
| "login": 1, | |
| "log in": 1, | |
| "sign in": 1, | |
| "forgot user": 1, | |
| "enter your password": 2, | |
| "登入": 1, | |
| "signon": 1, | |
| "reauth": 2, | |
| "anmelden": 1, | |
| "signin": 1, | |
| "log_on": 1, | |
| "sign on": 1, | |
| "connexion": 1, | |
| "absenden": 1, | |
| "logg inn": 1 | |
| }, | |
| "ForgotEmailAffordanceRegularExpressions": [ | |
| "^forgot.*email", | |
| "email\\?$" | |
| ], | |
| "ForgotUserNameAffordanceRegularExpressions": [ | |
| "^forgot.*user.*name" | |
| ], | |
| "NonAccountPasswordSecureTextEntryFieldLabels": [ | |
| "debit", | |
| "answer", | |
| "account number", | |
| "routing number", | |
| "date of birth", | |
| "zip code" | |
| ], | |
| "ChangePasswordFormTypeKeywords": { | |
| "forgotpassword": 1, | |
| "forgot password": 1, | |
| "reset": 1, | |
| "update": 1, | |
| "change": 1, | |
| "再設定": 1 | |
| }, | |
| "NewAccountFormTypeKeywords": { | |
| "set up": 1, | |
| "signup": 1, | |
| "create": 1, | |
| "create an account": 1, | |
| "create account": 1, | |
| "setup": 1, | |
| "sign up": 1, | |
| "enrollment": 1, | |
| "reg": 1, | |
| "activate": 1, | |
| "注册": 1 | |
| }, | |
| "IgnoredDataTypeFieldLabels": [ | |
| "search", | |
| "social security", | |
| "socialsecurity", | |
| "tax id number", | |
| "ssn", | |
| "ssno", | |
| "ssnum", | |
| "airport", | |
| "gate code", | |
| "relationship" | |
| ], | |
| "NonAutoFillableFormTypeKeywords": [ | |
| "import" | |
| ], | |
| "OldPasswordFieldLabels": [ | |
| "current", | |
| "old", | |
| "original" | |
| ], | |
| "ConfirmEmailFieldLabels": [ | |
| "confirm" | |
| ], | |
| "ConfirmPasswordFieldLabels": [ | |
| "repeat", | |
| "retype", | |
| "confirm", | |
| "verify", | |
| "new" | |
| ], | |
| "ShowHideButtonLabels": [ | |
| "show", | |
| "hide" | |
| ], | |
| "SearchFieldLabels": [ | |
| "search" | |
| ], | |
| "NonUsernameFieldLabels": [ | |
| "login code", | |
| "otpcode", | |
| "password", | |
| "captcha", | |
| "recaptcha", | |
| "sound", | |
| "answer", | |
| "confirmation code", | |
| "verification code", | |
| "zip code", | |
| "stock symbol", | |
| "chart", | |
| "table", | |
| "certificate", | |
| "cash card number" | |
| ], | |
| "PasswordFieldLabels": [ | |
| "password", | |
| "passwd", | |
| "设置密码", | |
| "passwort" | |
| ], | |
| "ForgotPasswordAffordanceRegularExpressions": [ | |
| "^forgot.*password" | |
| ], | |
| "NonEmailFieldLabels": [ | |
| "確認コード" | |
| ], | |
| "UsernameFieldLabels": [ | |
| "username", | |
| "user name", | |
| "screenname", | |
| "screen name", | |
| "loginname", | |
| "login name", | |
| "account name", | |
| "userID", | |
| "user ID", | |
| "loginID", | |
| "accountID", | |
| "Online ID", | |
| "GmailAddress", | |
| "Gmail Address", | |
| "usuario", | |
| "Library Card Number", | |
| "E-Mail-Adresse" | |
| ], | |
| "OneTimeCodeFieldLabels": [ | |
| "security code", | |
| "login code", | |
| "enter the code", | |
| "enter code", | |
| "otp", | |
| "onetimecode", | |
| "onetimepasscode", | |
| "one time password", | |
| "one time passcode", | |
| "verification code", | |
| "verificationCode", | |
| "confirmation code", | |
| "identification code", | |
| "identificationCode", | |
| "activation code", | |
| "access code", | |
| "SMS", | |
| "digit code", | |
| "2fa", | |
| "twofactor", | |
| "two-factor", | |
| "two factor", | |
| "authentication code", | |
| "two step sign in", | |
| "two-step sign in", | |
| "MFA code", | |
| "sign-in code", | |
| "passcode texted", | |
| "passcode expires", | |
| "验证码", | |
| "校验码", | |
| "驗證碼", | |
| "驗証碼", | |
| "確認碼", | |
| "認證碼", | |
| "確認コード", | |
| "認証コード", | |
| "인증번호", | |
| "확인코드", | |
| "code de sécurité", | |
| "code de vérification", | |
| "code de validation", | |
| "code d'identification", | |
| "code d'authentification", | |
| "code d'autorisation", | |
| "code de confirmation", | |
| "code SMS de vérification", | |
| "code de connexion", | |
| "Authorisierungscode", | |
| "Sicherheitscode", | |
| "Überprüfungscode", | |
| "Bestätigungscode", | |
| "Bestatigungscode", | |
| "Verifizierungscode", | |
| "Aktivierungscode", | |
| "Codice di sicurezza", | |
| "Codice attivazione", | |
| "codice di attivazione", | |
| "codice di conferma", | |
| "codice di verifica", | |
| "Kod bezpieczeństwa", | |
| "Kod autoryzacyjny", | |
| "Kod weryfikacyjny", | |
| "código de seguridad", | |
| "código de confirmación", | |
| "código de seguranca", | |
| "digite o codigo", | |
| "código de verificación", | |
| "código de verificação", | |
| "código de confirmacao", | |
| "Код проверки", | |
| "код безопасности", | |
| "код подтверждения", | |
| "Код аутентификации", | |
| "код підтвердження", | |
| "dogrulama kodu", | |
| "mã bảo mật", | |
| "Mã Xác Minh", | |
| "mã kích hoạt", | |
| "รหัสความปลอดภัย", | |
| "รหัสยืนยัน", | |
| "รหัสOTP", | |
| "รหัสการตรวจสอบยืนยัน", | |
| "รหัสการยืนยัน", | |
| "Kode keamanan", | |
| "Kode konfirmasi", | |
| "Kode verifikasi", | |
| "सत्यापन कोड", | |
| "Kod pengesahan", | |
| "Masukkan Kod", | |
| "Codul de confirmare" | |
| ], | |
| "WeakOneTimeCodeFieldLabels": [ | |
| "code", | |
| "passcode", | |
| "PIN", | |
| "token", | |
| "código", | |
| "코드", | |
| "コード", | |
| "код" | |
| ], | |
| "DayFieldLabels": [ | |
| "day", | |
| "jour" | |
| ], | |
| "MonthFieldLabels": [ | |
| "month", | |
| "date m", | |
| "date mo", | |
| "mois" | |
| ], | |
| "YearFieldLabels": [ | |
| "year", | |
| "date y", | |
| "date yr", | |
| "année" | |
| ] | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| var pageArguments = {}; | |
| var HTMLViewController = { | |
| trySubmit: function(button) | |
| { | |
| var computedStyle = window.getComputedStyle(button); | |
| // Don't use button.type here, since the default type for button is annoyingly "submit". | |
| // Check for an explicit type attribute value of "submit". | |
| if (button.getAttribute("type") !== "submit" || computedStyle.visibility === "hidden" || computedStyle.display === "none") | |
| return false; | |
| button.click(); | |
| return true; | |
| }, | |
| // On Mac, the submit button always has the default button look. | |
| keyDown: function(event) | |
| { | |
| if (event.target.tagName === "TEXTAREA" || event.keyIdentifier !== "Enter") | |
| return; | |
| var buttons = document.getElementsByTagName("button"); | |
| for (var i = 0; i < buttons.length; ++i) { | |
| if (HTMLViewController.trySubmit(buttons[i])) { | |
| event.preventDefault(); | |
| return; | |
| } | |
| } | |
| var inputButtons = document.getElementsByTagName("input"); | |
| for (var i = 0; i < inputButtons.length; ++i) { | |
| if (HTMLViewController.trySubmit(inputButtons[i])) { | |
| event.preventDefault(); | |
| return; | |
| } | |
| } | |
| }, | |
| setItemText: function(itemID, value) | |
| { | |
| var ele = document.getElementById(itemID); | |
| if (ele.tagName == "INPUT" || ele.tagName == "SELECT" || ele.tagName == "TEXTAREA") | |
| ele.value = value; | |
| else | |
| ele.innerText = value; | |
| }, | |
| itemText: function(itemID) | |
| { | |
| var ele = document.getElementById(itemID); | |
| if (ele.tagName == "INPUT" || ele.tagName == "SELECT" || ele.tagName == "TEXTAREA") | |
| return ele.value; | |
| else if (ele.firstChild) | |
| return ele.firstChild.data; | |
| else return ""; | |
| }, | |
| setItemChecked: function(itemID, value) | |
| { | |
| document.getElementById(itemID).checked = value; | |
| }, | |
| itemChecked: function(itemID) | |
| { | |
| return document.getElementById(itemID).checked; | |
| }, | |
| setItemEnabled: function(itemID, value) | |
| { | |
| var item = document.getElementById(itemID); | |
| item.disabled = !value; | |
| if (item.parentElement.tagName == "LABEL") { | |
| if (value) | |
| item.parentElement.classList.remove("disabled"); | |
| else | |
| item.parentElement.classList.add("disabled"); | |
| } | |
| }, | |
| insertOptionInSelect: function(selectID, position, label, value) | |
| { | |
| var select = document.getElementById(selectID); | |
| var option = document.createElement("option"); | |
| option.appendChild(document.createTextNode(label)); | |
| option.value = value; | |
| select.add(option, select.options[position]); | |
| }, | |
| appendToSelect: function(itemID, label, itemValue, itemStyle) | |
| { | |
| var selectEle = document.getElementById(itemID); | |
| var o; | |
| if (label == "") | |
| o = document.createElement("hr"); | |
| else { | |
| o = document.createElement("option"); | |
| o.appendChild(document.createTextNode(label)); | |
| o.value = itemValue ? itemValue : selectEle.length; | |
| o.style.cssText = itemStyle; | |
| } | |
| selectEle.add(o, null); | |
| }, | |
| setSelectIndex: function(itemID, index) | |
| { | |
| var selectEle = document.getElementById(itemID); | |
| selectEle.selectedIndex = index; | |
| }, | |
| setOptionEnabled: function(selectID, optionIndex, enabled) | |
| { | |
| document.getElementById(selectID)[optionIndex].disabled = !enabled; | |
| }, | |
| indexOfItemWithValue: function(selectID, value) | |
| { | |
| var select = document.getElementById(selectID); | |
| for (var i = 0; i < select.options.length; ++i) { | |
| if (select.options[i].value == value) | |
| return i; | |
| } | |
| return -1; | |
| }, | |
| clearSelect: function(itemID) | |
| { | |
| var selectEle = document.getElementById(itemID); | |
| selectEle.removeChildren(); | |
| }, | |
| setWidth: function(width) | |
| { | |
| window.resizeTo(width); | |
| }, | |
| htmlOffsetHeight: function() | |
| { | |
| return document.getElementsByTagName("html")[0].offsetHeight; | |
| }, | |
| addClass: function(itemID, itemClass) | |
| { | |
| document.getElementById(itemID).classList.add(itemClass); | |
| }, | |
| removeClass: function(itemID, itemClass) | |
| { | |
| document.getElementById(itemID).classList.remove(itemClass); | |
| }, | |
| setAttribute: function(itemID, attrName, attrValue) | |
| { | |
| document.getElementById(itemID).setAttribute(attrName, attrValue); | |
| }, | |
| setTitle: function(newTitle) | |
| { | |
| document.title = newTitle; | |
| }, | |
| focusItem: function(itemID) | |
| { | |
| var ele = document.getElementById(itemID); | |
| ele.focus(); | |
| ele.selectionStart = 0; | |
| ele.selectionEnd = ele.value.length; | |
| }, | |
| contextMenu: function(event) | |
| { | |
| if (event.target.tagName === "TEXTAREA") | |
| return; | |
| if (event.target.tagName === "INPUT" && (event.target.type === "password" || event.target.type === "text" || event.target.type == "search")) | |
| return; | |
| event.preventDefault(); | |
| }, | |
| pageLoaded: function() | |
| { | |
| var query = document.location.search; | |
| if (query) { | |
| query = query.substr(1); | |
| var args = query.split("&"); | |
| for (var i = 0; i < args.length; i++) { | |
| var nameValue = args[i].split("="); | |
| pageArguments[nameValue[0]] = nameValue[1]; | |
| } | |
| } | |
| document.body.addEventListener("keydown", HTMLViewController.keyDown); | |
| document.addEventListener("contextmenu", HTMLViewController.contextMenu); | |
| HTMLViewController.localize(); | |
| }, | |
| UIString: function(string) | |
| { | |
| if (window.localizedStrings && string in window.localizedStrings) | |
| string = window.localizedStrings[string]; | |
| else { | |
| console.error("Localized string \"" + string + "\" not found."); | |
| string = "LOCALIZED STRING NOT FOUND"; | |
| } | |
| return string; | |
| }, | |
| loadLocalizedStrings: function(controller) | |
| { | |
| document.write("<script type='text/javascript' charset='utf-8' src='safari-resource:/WBSLocalizedStrings.js'></" + "script>"); | |
| }, | |
| localize: function() | |
| { | |
| var elements = document.getElementsByClassName("l12n"); | |
| for (var i = 0; i < elements.length; ++i) | |
| elements[i].firstChild.data = HTMLViewController.UIString(elements[i].firstChild.data); | |
| var toolTipElements = document.getElementsByClassName("l12n-tooltip"); | |
| for (var i = 0; i < toolTipElements.length; ++i) | |
| toolTipElements[i].title = HTMLViewController.UIString(toolTipElements[i].title); | |
| } | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment