-
-
Save hackerxian/77dc164d102d490d07f7a8343ddba8cd to your computer and use it in GitHub Desktop.
This file contains 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. | |
*/ | |
function characterNeedsScoreMultiplier(e) { | |
if (!e || e.length === 0) | |
return !1; | |
var t = e.charCodeAt(0); | |
return t > 11904 && t < 12031?!0 : t > 12352 && t < 12543?!0 : t > 12736 && t < 19903?!0 : t > 19968 && t < 40959?!0 : t > 44032 && t < 55215?!0 : t > 63744 && t < 64255?!0 : t > 65072 && t < 65103?!0 : t > 131072 && t < 173791?!0 : t > 194560 && t < 195103?!0 : !1 | |
} | |
function domDistance(e, t, n) { | |
var r = [], i = e; | |
while (i) | |
r.unshift(i), i = i.parentNode; | |
var s = []; | |
i = t; | |
while (i) | |
s.unshift(i), i = i.parentNode; | |
var o = Math.min(r.length, s.length), u = Math.abs(r.length - s.length); | |
for (var a = o; a >= 0; --a) { | |
if (r[a] === s[a]) | |
break; | |
u += 2; | |
if (n && u >= n) | |
return n | |
} | |
return u | |
} | |
function fontSizeFromComputedStyle(e, t) { | |
var n = parseInt(e.fontSize); | |
return isNaN(n) && (n = t ? t : BaseFontSize), n | |
} | |
function contentTextStyleForNode(e, t) { | |
function n(e) { | |
if (isNodeWhitespace(e)) | |
return null; | |
var t = getComputedStyle(e.parentNode); | |
return t.float !== "none" ? null : t | |
} | |
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), s = i.snapshotLength; | |
for (var o = 0; o < s; ++o) { | |
var u = i.snapshotItem(o), a=!1; | |
for (var f = u.parentElement; f !== t; f = f.parentElement) | |
if (NegativeRegEx.test(f.className)) { | |
a=!0; | |
break | |
} | |
if (a) | |
continue; | |
var l = n(u); | |
if (l) | |
return l | |
} | |
return null | |
} | |
function isNodeWhitespace(e) { | |
return !e || e.nodeType !== Node.TEXT_NODE?!1 : !/\S/.test(e.data) | |
} | |
function removeWhitespace(e) { | |
return e.replace(/\s+/g, "") | |
} | |
function isElementNode(e) { | |
return e && e.nodeType === Node.ELEMENT_NODE?!0 : !1 | |
} | |
function computedStyleIndicatesElementIsInvisibleDueToClipping(e) { | |
if (e.position !== "absolute") | |
return !1; | |
var t = e.clip.match(/^rect\((\d+px|auto), (\d+px|auto), (\d+px|auto), (\d+px|auto)\)$/); | |
if (!t || t.length !== 5) | |
return !1; | |
var n = t.map(function(e) { | |
return parseInt(e) | |
}), r = n[1]; | |
isNaN(r) && (r = 0); | |
var i = n[2], s = n[3], o = n[4]; | |
return isNaN(o) && (o = 0), r >= s || i >= o | |
} | |
function isElementVisible(e) { | |
var t = getComputedStyle(e); | |
if (t.visibility !== "visible" || t.display === "none") | |
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?!1 : t.bottom <= 0 || t.right <= 0?!0 : !1 | |
} | |
function elementDepth(e) { | |
var t = 0; | |
for (; e; e = e.parentElement) | |
t++; | |
return t | |
} | |
function depthOfElementWithinElement(e, t) { | |
var n = 0; | |
for (; e !== t; e = e.parentElement) | |
n++; | |
return n | |
} | |
function nearestAncestorElementWithTagName(e, t) { | |
while (e = e.parentElement) | |
if (e.tagName === t) | |
return e; | |
return null | |
} | |
function cachedElementBoundingRect(e) { | |
if (e._cachedElementBoundingRect) | |
return e._cachedElementBoundingRect; | |
var t = e.getBoundingClientRect(); | |
return ReaderArticleFinderJS._elementsWithCachedBoundingRects.push(e), !ReaderArticleFinderJS._cachedScrollX&&!ReaderArticleFinderJS._cachedScrollY ? (e._cachedElementBoundingRect = t, e._cachedElementBoundingRect) : (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) | |
} | |
function clearCachedElementBoundingRects() { | |
var e = ReaderArticleFinderJS._elementsWithCachedBoundingRects, t = e.length; | |
for (var n = 0; n < t; ++n) | |
e[n]._cachedElementBoundingRect = null; | |
ReaderArticleFinderJS._elementsWithCachedBoundingRects = [] | |
} | |
function innerTextOrTextContent(e) { | |
var t = e.innerText; | |
return /\S/.test(t) || (t = e.textContent), t | |
} | |
function levenshteinDistance(e, t) { | |
var n = e.length, r = t.length, i = new Array(n + 1); | |
for (var s = 0; s < n + 1; ++s) | |
i[s] = new Array(r + 1), i[s][0] = s; | |
for (var o = 0; o < r + 1; ++o) | |
i[0][o] = o; | |
for (var o = 1; o < r + 1; ++o) | |
for (var s = 1; s < n + 1; ++s) | |
if (e[s - 1] === t[o - 1]) | |
i[s][o] = i[s - 1][o - 1]; | |
else { | |
var u = i[s - 1][o] + 1, a = i[s][o - 1] + 1, f = i[s - 1][o - 1] + 1; | |
i[s][o] = Math.min(u, a, f) | |
} | |
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?!0 : stringSimilarity(e, t) > StringSimilarityToDeclareStringsNearlyIdentical | |
} | |
function elementIsCommentBlock(e) { | |
if (/(^|\s)comment/.test(e.className)) | |
return !0; | |
var t = e.getAttribute("id"); | |
return t && t.indexOf("comment") === 0?!0 : !1 | |
} | |
function elementLooksLikeEmbeddedTweet(e) { | |
const t = /http.+twitter.com.*status.*[0-9]+/i; | |
if (e.tagName !== "IFRAME") | |
return !1; | |
if (!e.contentDocument) | |
return !1; | |
var n = e.contentDocument.documentElement, r = 0, i = n.querySelector("blockquote"); | |
return i && t.test(i.getAttribute("cite"))&&++r, e.classList.contains("twitter-tweet")&&++r, n.querySelector("[data-iframe-title='Embedded Tweet']")&&++r, n.querySelector("[data-tweet-id]")&&++r, r > 2 | |
} | |
function elementLooksLikePartOfACarousel(e) { | |
const t = /carousel-|carousel_|-carousel|_carousel/, n = 3; | |
var r = e; | |
for (var i = 0; i < n; ++i) { | |
if (!r) | |
return !1; | |
if (t.test(r.className) || t.test(r.getAttribute("data-analytics"))) | |
return !0; | |
r = r.parentElement | |
} | |
} | |
function shouldPruneIframe(e, t) { | |
return HostnamesKnownToContainEmbeddableMediaRegex.test(anchorForURL(e.src, t).hostname)?!1 : elementLooksLikeEmbeddedTweet(e.originalElement)?!1 : !0 | |
} | |
function languageScoreMultiplierForTextNodes(e) { | |
if (!e ||!e.length) | |
return 1; | |
var t = Math.min(e.length, DefaultNumberOfTextNodesToCheckForLanguageMultiplier), n = 0, r = 0; | |
for (var i = 0; i < t; i++) { | |
var s = e[i].nodeValue.trim(), o = Math.min(s.length, NumberOfCharactersPerTextNodeToEvaluateForLanguageMultiplier); | |
for (var u = 0; u < o; u++) | |
characterNeedsScoreMultiplier(s[u]) && n++; | |
r += o | |
} | |
return n >= r * MinimumRatioOfCharactersForLanguageMultiplier ? ScoreMultiplierForChineseJapaneseKorean : 1 | |
} | |
function scoreMultiplierForElementTagNameAndAttributes(e) { | |
var t = 1; | |
for (var n = e; n; n = n.parentElement) { | |
var r = n.getAttribute("id"); | |
r && (ArticleRegEx.test(r) && (t += ArticleMatchBonus), CommentRegEx.test(r) && (t -= CommentMatchPenalty)); | |
var i = n.className; | |
i && (ArticleRegEx.test(i) && (t += ArticleMatchBonus), CommentRegEx.test(i) && (t -= CommentMatchPenalty)), n.tagName === "ARTICLE" && (t += ArticleMatchBonus) | |
} | |
return t < 0 ? 0 : t | |
} | |
function elementAtPoint(e, t) { | |
if (typeof ReaderArticleFinderJSController != "undefined" && ReaderArticleFinderJSController.nodeAtPoint) { | |
var n = ReaderArticleFinderJSController.nodeAtPoint(e, t); | |
return n && n.nodeType !== Node.ELEMENT_NODE && (n = n.parentElement), n | |
} | |
return document.elementFromPoint(e, t) | |
} | |
function userVisibleURLString(e) { | |
return typeof ReaderArticleFinderJSController != "undefined" && ReaderArticleFinderJSController.userVisibleURLString ? ReaderArticleFinderJSController.userVisibleURLString(e) : e | |
} | |
function anchorForURL(e, t) { | |
var n = t.createElement("a"); | |
return n.href = e, n | |
} | |
function anchorLinksToAttachment(e) { | |
return /\battachment\b/i.test(e.getAttribute("rel")) | |
} | |
function anchorLinksToTagOrCategoryPage(e) { | |
return /\bcategory|tag\b/i.test(e.getAttribute("rel")) | |
} | |
function elementsHaveSameTagAndClassNames(e, t) { | |
return e.tagName === t.tagName && e.className === t.className | |
} | |
function selectorForElement(e) { | |
var t = e.tagName, n = e.classList, r = n.length; | |
for (var i = 0; i < r; i++) | |
t += "." + n[i]; | |
return t | |
} | |
function elementFingerprintForDepth(e, t) { | |
function s(e, t) { | |
if (!e) | |
return ""; | |
var o = []; | |
o.push(selectorForElement(e)); | |
var u = e.children, a = u.length; | |
if (a && t > 0) { | |
o.push(n); | |
for (var f = 0; f < a; ++f) | |
o.push(s(u[f], t - 1)), f !== a - 1 && o.push(i); | |
o.push(r) | |
} | |
return o.join("") | |
} | |
const n = " / ", r = " \\", i = " | "; | |
return s(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) | |
return; | |
var r = e.children, i = r.length, s = t - 1; | |
for (var o = 0; o < i; ++o) | |
walkElementSubtree(r[o], s, n); | |
n(e, t) | |
} | |
function childrenWithParallelStructure(e) { | |
var t = e.children; | |
if (!t) | |
return []; | |
var n = t.length; | |
if (!n) | |
return []; | |
var r = {}; | |
for (var i = 0; i < n; ++i) { | |
var s = t[i]; | |
if (CandidateTagNamesToIgnore[s.tagName] ||!s.className) | |
continue; | |
var o = s.classList, u = o.length; | |
for (var a = 0; a < u; ++a) { | |
var f = o[a], l = r[f]; | |
l ? l.push(s) : r[f] = [s] | |
} | |
} | |
var c = Math.floor(n / 2); | |
for (var f in r) { | |
var l = r[f]; | |
if (l.length > c) | |
return l | |
} | |
return [] | |
} | |
const ReaderMinimumScore = 1600, ReaderMinimumAdvantage = 15, ArticleMinimumScoreDensity = 4.25, BlacklistedHostsAllowedPathRegexMap = { | |
"www.apple.com": /^\/([a-z]{2,4}\/){0,2}pr\/|^\/hotnews\//, | |
"extensions.apple.com": null | |
}, ListOfHostnameAndTrustedArticleNodeSelectorPairs = [[/.*\.apple.com$/, "article"]], CandidateMinimumWidth = 280, CandidateMinimumHeight = 295, CandidateMinimumArea = 17e4, CandidateMaximumTop = 1300, CandidateMinimumWidthPortionForIndicatorElements = .5, CandidateMinumumListItemLineCount = 4, CandidateTagNamesToIgnore = { | |
A: 1, | |
EMBED: 1, | |
FORM: 1, | |
HTML: 1, | |
IFRAME: 1, | |
OBJECT: 1, | |
OL: 1, | |
OPTION: 1, | |
SCRIPT: 1, | |
STYLE: 1, | |
svg: 1, | |
UL: 1 | |
}, PrependedArticleCandidateMinimumHeight = 50, AppendedArticleCandidateMinimumHeight = 200, AppendedArticleCandidateMaximumVerticalDistanceFromArticle = 150, StylisticClassNames = { | |
justfy: 1, | |
justify: 1, | |
left: 1, | |
right: 1, | |
small: 1 | |
}, CommentRegEx = /comment|meta|footer|footnote/, CommentMatchPenalty = .75, ArticleRegEx = /(?:(?:^|\s)(?:(post|hentry|entry)[-_]?(?:content|text|body)?|article[-_]?(?:content|text|body|page)?)(?:\s|$))/i, ArticleMatchBonus = .5, DensityExcludedElementSelector = "#disqus_thread, #comments, .userComments", AttributesToRemoveRegEx = /^on|^id$|^class$|^style$/, PositiveRegEx = /article|body|content|entry|hentry|page|pagination|post|text/i, NegativeRegEx = /advertisement|breadcrumb|combx|comment|contact|disqus|footer|link|meta|mod-conversations|promo|related|scroll|share|shoutbox|sidebar|social|sponsor|subscribe|tags|toolbox|widget|_ad$/i, VeryPositiveClassNameRegEx = /instapaper_body/, VeryNegativeClassNameRegEx = /instapaper_ignore/, SharingRegex = /email|print|rss|digg|slashdot|delicious|reddit|share/i, HostnamesKnownToContainEmbeddableMediaRegex = /youtube|vimeo|dailymotion/, 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, HeaderMinimumDistanceFromArticleTop = 200, HeaderLevenshteinDistanceToLengthRatio = .75, MinimumRatioOfListItemsBeingRelatedToSharingToPruneEntireList = .5, FloatMinimumHeight = 130, ImageSizeTiny = 32, ToleranceForLeadingImageWidthToArticleWidthForFullWidthPresentation = 50, MaximumFloatWidth = 325, AnchorImageMinimumWidth = 100, AnchorImageMinimumHeight = 100, MinimumHeightForImagesAboveTheArticleTitle = 50, MainImageMinimumWidthAndHeight = 83, BaseFontSize = 16, BaseLineHeightRatio = 1.125, MaximumExactIntegralValue = 9007199254740992, TitleCandidateDepthScoreMultiplier = .1, DocumentPositionDisconnected = 1, DocumentPositionPreceding = 2, DocumentPositionFollowing = 4, DocumentPositionContains = 8, DocumentPositionContainedBy = 16, TextNodeLengthPower = 1.25, KnownImageLazyLoadingAttributes = { | |
"data-lazy-src": 1, | |
"data-original": 1, | |
"data-src": 1, | |
"original-src": 1, | |
"rel:bf_image_src": 1 | |
}, StringSimilarityToDeclareStringsNearlyIdentical = .97; | |
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(t, n, r, i) { | |
const s = "a, b, strong, i, em, u, span"; | |
var o = cachedElementBoundingRect(t), u = cachedElementBoundingRect(n.element); | |
if (i && o.height < PrependedArticleCandidateMinimumHeight ||!i && o.height < AppendedArticleCandidateMinimumHeight) | |
if (t.childElementCount && t.querySelectorAll("*").length !== t.querySelectorAll(s).length) | |
return null; | |
if (i) { | |
if (o.bottom > u.top) | |
return null | |
} else if (o.top < u.bottom) | |
return null; | |
if (!i) { | |
var a = o.top - u.bottom; | |
if (a > AppendedArticleCandidateMaximumVerticalDistanceFromArticle) | |
return null | |
} | |
if (o.left > u.right || o.right < u.left) | |
return null; | |
if (elementLooksLikePartOfACarousel(t)) | |
return null; | |
var f = new CandidateElement(t, r); | |
return f.isPrepended = i, f | |
}, CandidateElement.candidateIfElementIsViable = function(t, n, r) { | |
var i = cachedElementBoundingRect(t); | |
return i.width < CandidateMinimumWidth || i.height < CandidateMinimumHeight ? null : i.width * i.height < CandidateMinimumArea ? null : !r && i.top > CandidateMaximumTop ? null : CandidateElement.candidateElementAdjustedHeight(t) < CandidateMinimumHeight ? null : new CandidateElement(t, n) | |
}, CandidateElement.candidateElementAdjustedHeight = function(t) { | |
var n = cachedElementBoundingRect(t), r = n.height, i = t.getElementsByTagName("form"), s = i.length; | |
for (var o = 0; o < s; ++o) { | |
var u = i[o], a = cachedElementBoundingRect(u); | |
a.width > n.width * CandidateMinimumWidthPortionForIndicatorElements && (r -= a.height) | |
} | |
var f = t.querySelectorAll("ol, ul"), l = f.length, c = null; | |
for (var o = 0; o < l; ++o) { | |
var h = f[o]; | |
if (c && c.compareDocumentPosition(h) & DocumentPositionContainedBy) | |
continue; | |
var p = h.getElementsByTagName("li"), d = p.length, v = cachedElementBoundingRect(h); | |
if (!d) { | |
r -= v.height; | |
continue | |
} | |
var m = v.height / d, g = getComputedStyle(p[0]), y = parseInt(g.lineHeight); | |
if (isNaN(y)) { | |
var b = fontSizeFromComputedStyle(g); | |
y = b * BaseLineHeightRatio | |
} | |
v.width > n.width * CandidateMinimumWidthPortionForIndicatorElements && m / y < CandidateMinumumListItemLineCount && (r -= v.height, c = h) | |
} | |
return r | |
}, CandidateElement.prototype = { | |
calculateRawScore: function() { | |
var t = 0, n = this.textNodes, r = n.length; | |
for (var i = 0; i < r; ++i) | |
t += this.rawScoreForTextNode(n[i]); | |
return t | |
}, | |
calculateElementTagNameAndAttributesScoreMultiplier: function() { | |
return scoreMultiplierForElementTagNameAndAttributes(this.element) | |
}, | |
calculateLanguageScoreMultiplier: function() { | |
if (this.languageScoreMultiplier !== 0) | |
return; | |
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 t = 0, n = this.element.querySelector(DensityExcludedElementSelector); | |
n && (t = n.clientWidth * n.clientHeight); | |
var r = this.element.children || [], i = r.length; | |
for (var s = 0; s < i; ++s) { | |
var o = r[s]; | |
elementIsCommentBlock(o) && (t += o.clientWidth * o.clientHeight) | |
} | |
var u = cachedElementBoundingRect(this.element).width * cachedElementBoundingRect(this.element).height, a = u * MaximumContentMediaAreaToArticleAreaRatio, f = cachedElementBoundingRect(this.element).width * MinimumContentMediaWidthToArticleWidthRatio, l = this.element.querySelectorAll("img, object, video"), c = l.length; | |
for (var s = 0; s < c; ++s) { | |
var h = cachedElementBoundingRect(l[s]); | |
if (h.width >= f && h.height > MinimumContentMediaHeight) { | |
var p = h.width * h.height; | |
p < a && (t += p) | |
} | |
} | |
var d = this.basicScore(), v = u - t, m = this.textNodes.length, g = 0, y = 0; | |
for (var s = 0; s < m; ++s) { | |
var b = this.textNodes[s].parentNode; | |
b && (y += fontSizeFromComputedStyle(getComputedStyle(b)), g++) | |
} | |
var w = BaseFontSize; | |
return g && (w = y/=g), this.calculateLanguageScoreMultiplier(), d / v * 1e3 * (w / BaseFontSize) * this.languageScoreMultiplier | |
}, | |
usableTextNodesInElement: function(t) { | |
var n = []; | |
if (!t) | |
return n; | |
const r = { | |
A: 1, | |
DD: 1, | |
DT: 1, | |
NOSCRIPT: 1, | |
OL: 1, | |
OPTION: 1, | |
PRE: 1, | |
SCRIPT: 1, | |
STYLE: 1, | |
TD: 1, | |
UL: 1, | |
IFRAME: 1 | |
}; | |
var i = this.contentDocument, s = function(e) { | |
const t = "text()|*/text()|*/a/text()|*/li/text()|*/span/text()|*/em/text()|*/i/text()|*/strong/text()|*/b/text()|*/font/text()|blockquote/*/text()|div[count(./p)=count(./*)]/p/text()"; | |
var s = i.evaluate(t, e, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null), o = s.snapshotLength; | |
for (var u = 0; u < o; ++u) { | |
var a = s.snapshotItem(u); | |
if (r[a.parentNode.tagName] || a._countedTextNode || isNodeWhitespace(a)) | |
continue; | |
a._countedTextNode=!0, n.push(a) | |
} | |
}; | |
s(t); | |
var o = childrenWithParallelStructure(t), u = o.length; | |
for (var a = 0; a < u; ++a) { | |
var f = o[a]; | |
s(f) | |
} | |
var l = n.length; | |
for (var a = 0; a < l; ++a) | |
delete n[a]._countedTextNode; | |
return n | |
}, | |
addTextNodesFromCandidateElement: function(t) { | |
var n = this.textNodes.length; | |
for (var r = 0; r < n; ++r) | |
this.textNodes[r].alreadyCounted=!0; | |
var i = t.textNodes, s = i.length; | |
for (var r = 0; r < s; ++r) | |
i[r].alreadyCounted || this.textNodes.push(i[r]); | |
var n = this.textNodes.length; | |
for (var r = 0; r < n; ++r) | |
this.textNodes[r].alreadyCounted = null; | |
this.rawScore = this.calculateRawScore() | |
}, | |
rawScoreForTextNode: function(t) { | |
const n = 20; | |
if (!t) | |
return 0; | |
var r = t.length; | |
if (r < n) | |
return 0; | |
var i = t.parentNode; | |
if (!isElementVisible(i)) | |
return 0; | |
var s = 1; | |
while (i && i !== this.element) | |
s -= .1, i = i.parentNode; | |
return Math.pow(r * s, TextNodeLengthPower) | |
}, | |
shouldDisqualifyDueToScoreDensity: function() { | |
return this.scoreDensity() < ArticleMinimumScoreDensity?!0 : !1 | |
}, | |
shouldDisqualifyDueToHorizontalRuleDensity: function() { | |
var t = this.element.getElementsByTagName("hr"), n = t.length, r = 0, i = cachedElementBoundingRect(this.element), s = i.width * .7; | |
for (var o = 0; o < n; ++o) | |
t[o].clientWidth > s && r++; | |
if (r) { | |
var u = i.height / r; | |
if (u < MinimumAverageDistanceBetweenHRElements) | |
return !0 | |
} | |
return !1 | |
}, | |
shouldDisqualifyDueToHeaderDensity: function() { | |
var t = "(h1|h2|h3|h4|h5|h6|*/h1|*/h2|*/h3|*/h4|*/h5|*/h6)[a[@href]]", n = this.contentDocument.evaluate(t, this.element, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null), r = n.snapshotLength; | |
if (r > 2) { | |
var i = 0, s = cachedElementBoundingRect(this.element), o = s.height * PortionOfCandidateHeightToIgnoreForHeaderCheck; | |
for (var u = 0; u < r; ++u) { | |
var a = n.snapshotItem(u), f = cachedElementBoundingRect(a); | |
f.top - s.top > o && s.bottom - f.bottom > o && i++ | |
} | |
var l = s.height / i; | |
if (l < MinimumAverageDistanceBetweenHeaderElements) | |
return !0 | |
} | |
return !1 | |
}, | |
shouldDisqualifyDueToSimilarElements: function(t) { | |
function i(e) { | |
return !!{ | |
H1: 1, | |
H2: 1, | |
H3: 1, | |
H4: 1, | |
H5: 1, | |
H6: 1 | |
} | |
[e.tagName] | |
} | |
function s(e, t) { | |
if (!e ||!t) | |
return !1; | |
const n = 1; | |
return e.className ? e.className === t.className : elementFingerprintForDepth(e, n) === elementFingerprintForDepth(t, n) | |
} | |
const n = /clearfix/i, r = "h1, h2, h3, h4, h5, h6"; | |
var o = this.element; | |
if (o.tagName === "LI" || o.tagName === "DD") { | |
var u = o.parentNode, a = u.children.length; | |
for (var f = 0; f < a; ++f) { | |
var l = u.children[f]; | |
if (l.tagName === o.tagName && l.className === o.className && l !== o) | |
return !0 | |
} | |
} | |
var c = o.getAttribute("class"); | |
c || (o = o.parentElement, o && (c = o.getAttribute("class"), c || (o = o.parentElement, o && (c = o.getAttribute("class"))))); | |
if (c) { | |
t || (t = []); | |
var h = t.length; | |
for (var f = 0; f < h; ++f) | |
t[f].element.candidateElement = t[f]; | |
var p; | |
try { | |
var d = c.split(" "), v = ""; | |
for (var f = 0; f < d.length; ++f) { | |
if (n.test(d[f])) | |
continue; | |
d[f].length && (v += "." + d[f]) | |
} | |
p = this.contentDocument.querySelectorAll(v) | |
} catch (m) { | |
p = [] | |
} | |
var g=!1, y = elementDepth(o), b = p.length; | |
for (var f = 0; f < b; ++f) { | |
var l = p[f]; | |
if (l === o) | |
continue; | |
if (l.parentElement === o || o.parentElement === l) | |
continue; | |
if (!isElementVisible(l)) | |
continue; | |
var w = l.candidateElement; | |
if (!w) { | |
w = new CandidateElement(l, this.contentDocument); | |
if (!w) | |
continue | |
} | |
if (w.basicScore() * ReaderMinimumAdvantage > this.basicScore()) { | |
if (!g && cachedElementBoundingRect(l).bottom < cachedElementBoundingRect(this.element).top) { | |
g=!0; | |
continue | |
} | |
if (s(o.previousElementSibling, l.previousElementSibling) || s(o.nextElementSibling, l.nextElementSibling)) { | |
var E = o.querySelector(r), S = l.querySelector(r); | |
if (E && S && elementsHaveSameTagAndClassNames(E, S)) | |
return !0; | |
E = o.previousElementSibling, S = l.previousElementSibling; | |
if (E && S && i(E) && i(S) && elementsHaveSameTagAndClassNames(E, S)) | |
return !0 | |
} | |
if (elementDepth(l) === y) | |
while (l.parentElement && o.parentElement) { | |
if (l.parentElement === o.parentElement) | |
break; | |
l = l.parentElement, o = o.parentElement | |
} | |
while (o.childElementCount <= 1) { | |
if (!o.childElementCount ||!l.childElementCount) | |
return !1; | |
if (l.childElementCount > 1) | |
return !1; | |
if (o.firstElementChild.tagName !== l.firstElementChild.tagName) | |
return !1; | |
o = o.firstElementChild, l = l.firstElementChild | |
} | |
if (l.childElementCount <= 1) | |
return !1; | |
var S = l.firstElementChild, x = l.lastElementChild, E = o.firstElementChild, T = o.lastElementChild; | |
if (S.tagName !== E.tagName) | |
return !1; | |
if (x.tagName !== T.tagName) | |
return !1; | |
var N = S.className, C = x.className, k = E.className, L = x.className, A = L === k ? 2: 1; | |
if (N.length || k.length) { | |
if (!N.length ||!k.length) | |
return !1; | |
if (N === k && o.querySelectorAll("." + k.replace(/\s+/, ".")).length <= A) | |
return !0 | |
} | |
if (C.length || L.length) { | |
if (!C.length ||!L.length) | |
return !1; | |
if (C === L && o.querySelectorAll("." + L.replace(/\s+/, ".")).length <= A) | |
return !0 | |
} | |
var O = E.clientHeight, M = T.clientHeight; | |
return !O ||!S.clientHeight?!1 : !M ||!x.clientHeight?!1 : O === S.clientHeight || M === x.clientHeight?!0 : !1 | |
} | |
} | |
for (var f = 0; f < h; ++f) | |
t[f].element.candidateElement = null | |
} | |
return !1 | |
}, | |
shouldDisqualifyForDeepLinking: function() { | |
function n(e) { | |
var t = e.pathname.substring(1).split("/"); | |
return t[t.length - 1] || t.pop(), t | |
} | |
const t = 5; | |
var r = this.element, i = this.contentDocument.location, s = n(i), o = s.length, u = [], a = r.getElementsByTagName("a"), f = a.length; | |
for (var l = 0; l < f; l++) { | |
var c = a[l]; | |
if (i.host !== c.host) | |
continue; | |
if (n(c).length <= o) | |
continue; | |
if ((c.host + c.pathname).indexOf(i.host + i.pathname) !== 0) | |
continue; | |
if (anchorLinksToAttachment(c)) | |
continue; | |
u.push(c); | |
if (u.length < t) | |
continue; | |
var h = r.offsetTop + r.offsetHeight / t; | |
return u[0].offsetTop < h | |
} | |
return !1 | |
} | |
}, String.prototype.lastInteger = function() { | |
const t = /[0-9]+/g; | |
var n = this.match(t); | |
return n ? parseInt(n[n.length - 1]) : NaN | |
}, String.prototype.escapeCharacters = function(e) { | |
var t=!1, n = e.length; | |
for (var r = 0; r < n; ++r) | |
if (this.indexOf(e.charAt(r))!==-1) { | |
t=!0; | |
break | |
} | |
if (!t) | |
return this; | |
var i = "", s = this.length; | |
for (var r = 0; r < s; ++r) | |
e.indexOf(this.charAt(r))!==-1 && (i += "\\"), i += this.charAt(r); | |
return i | |
}, String.prototype.escapeForRegExp = function() { | |
return this.escapeCharacters("^[]{}()\\.$*+?|") | |
}, ReaderArticleFinder = function(e) { | |
this.contentDocument = e, this.didSearchForArticleNode=!1, this.article = null, this.didSearchForExtraArticleNode=!1, this.extraArticle = null, this.leadingImage = null, this._cachedScrollY = 0, this._cachedScrollX = 0, this._elementsWithCachedBoundingRects = [], this._cachedContentTextStyle = null, this.pageNumber = 1, this.prefixWithDateForNextPageURL = null, this._elementsEvaluatedForTextContent = [], this.previouslyDiscoveredPageURLStrings = [] | |
}, ReaderArticleFinder.prototype = { | |
isReaderModeAvailable: function() { | |
return this.canRunReaderDetection() ? this.findArticleBySearchingWhitelist()?!0 : (this.cacheWindowScrollPosition(), this.article = this.findArticleByVisualExamination(), this.article && this.articleIsLTR(), !!this.article) : null | |
}, | |
prepareToTransitionToReader: function() { | |
this.adoptableArticle(!0), this.nextPageURL(), this.articleIsLTR() | |
}, | |
nextPageURL: function() { | |
if (!this._nextPageURL) { | |
var t = this.nextPageURLString(); | |
typeof ReaderArticleFinderJSController != "undefined" && t && (t = ReaderArticleFinderJSController.substituteURLForNextPageURL(t)), this._nextPageURL = t | |
} | |
return this._nextPageURL | |
}, | |
containerElementsForMultiPageContent: function() { | |
const e = /(.*page.*)(\d{1,2})(.*)/i, t = 3; | |
var n = [], r = this.articleNode(), i, s = 0; | |
for (; ;) { | |
i = e.exec(r.getAttribute("id")); | |
if (i) | |
break; | |
r = r.parentElement; | |
if (!r || s++===t) | |
return [] | |
} | |
var o = childrenOfParentElement(r), u = o.length; | |
for (var a = 0; a < u; ++a) { | |
var f = o[a]; | |
if (f === r) | |
continue; | |
var l = e.exec(f.getAttribute("id")); | |
if (!l || l[1] !== i[1] || l[3] !== i[3]) | |
continue; | |
if (isElementVisible(f)&&!isElementPositionedOffScreen(f)) | |
continue; | |
n.push(f) | |
} | |
return n | |
}, | |
adoptableMultiPageContentElements: function() { | |
return this.containerElementsForMultiPageContent().map(function(e) { | |
return this.cleanArticleNode(e, e.cloneNode(!0), !1) | |
}, this) | |
}, | |
classNameIsSignificantInRouteComputation: function(t) { | |
return t?!(t.toLowerCase()in StylisticClassNames) : !1 | |
}, | |
shouldIgnoreInRouteComputation: function(t) { | |
return t.tagName === "SCRIPT" || t.tagName === "LINK" || t.tagName === "STYLE"?!0 : t.tagName !== "TR"?!1 : t.offsetHeight?!1 : !0 | |
}, | |
routeToArticleNode: function() { | |
var t = [], n = this.articleNode(); | |
while (n) { | |
var r = {}; | |
r.tagName = n.tagName; | |
var i = n.getAttribute("id"); | |
i && (r.id = i), this.classNameIsSignificantInRouteComputation(n.className) && (r.className = n.className), r.index = 1; | |
for (var s = n.previousElementSibling; s; s = s.previousElementSibling) | |
this.shouldIgnoreInRouteComputation(s) || r.index++; | |
t.unshift(r), n = n.parentElement | |
} | |
return t | |
}, | |
adjustArticleNode: function() { | |
if (!this.article) | |
return; | |
var t; | |
for (t = this.article.element; t; t = t.parentElement) | |
if (VeryPositiveClassNameRegEx.test(t.className)) { | |
this.article.element = t; | |
return | |
} | |
t = this.article.element; | |
if (t.tagName === "SECTION" && t.parentElement && t.parentElement.getAttribute("itemprop") === "articleBody") { | |
this.article.element = t.parentElement; | |
return | |
} | |
t = this.article.element; | |
if (t.getAttribute("id") ||!t.className) | |
return; | |
var n = t.tagName, r = t.className, i = t.parentElement, s = i.children; | |
for (var o = 0, u = s.length; o < u; ++o) { | |
var a = s[o]; | |
if (a === t) | |
continue; | |
if (a.tagName !== n || a.className !== r) | |
continue; | |
var f = CandidateElement.candidateIfElementIsViable(a, this.contentDocument, !0); | |
if (!f || f.finalScore() < ReaderMinimumScore) | |
continue; | |
this.article.element = i; | |
return | |
} | |
}, | |
findArticleBySearchingWhitelist: function() { | |
var t = ListOfHostnameAndTrustedArticleNodeSelectorPairs.length; | |
for (var n = 0; n < t; ++n) { | |
var r = ListOfHostnameAndTrustedArticleNodeSelectorPairs[n], i = r[0]; | |
if (!i.test(this.contentDocument.location.hostname)) | |
continue; | |
var s = r[1], o = this.contentDocument.querySelectorAll(s); | |
if (o.length === 1) | |
return new CandidateElement(o[0], this.contentDocument) | |
} | |
return null | |
}, | |
articleNode: function(t) { | |
return this.didSearchForArticleNode || (this.article = this.findArticleBySearchingWhitelist(), this.article || (this.article = this.findArticleBySearchingAllElements()), this.article || (this.article = this.findArticleByVisualExamination()), !this.article && t && (this.article = this.findArticleBySearchingAllElements(!0)), this.adjustArticleNode(), this.didSearchForArticleNode=!0, 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 : (this._cachedContentTextStyle = contentTextStyleForNode(this.contentDocument, this.articleNode()), this._cachedContentTextStyle || (this._cachedContentTextStyle = getComputedStyle(this.articleNode())), this._cachedContentTextStyle) | |
}, | |
commaCountIsLessThan: function(t, n) { | |
var r = 0, i = t.textContent, s =- 1; | |
while (r < n && (s = i.indexOf(",", s + 1)) >= 0) | |
r++; | |
return r < n | |
}, | |
calculateLinkDensity: function(t) { | |
var n = removeWhitespace(t.textContent).length; | |
if (!n) | |
return 0; | |
var r = t.getElementsByTagName("a"), i = 0, s = r.length; | |
for (var o = 0; o < s; ++o) | |
i += removeWhitespace(r[o].textContent).length; | |
return i / n | |
}, | |
shouldPruneElement: function(t, n) { | |
const r = .33, i = .5, s = .2, o = 25, u = 4e4; | |
var a = t.tagName; | |
if (!t.parentElement) | |
return !1; | |
if (a === "IFRAME") | |
return shouldPruneIframe(t, this.contentDocument); | |
if (a !== "OBJECT" && a !== "EMBED" && a !== "CANVAS") { | |
var f=!1, l = t.childNodes.length; | |
for (var c = 0; c < l; ++c) { | |
var h = t.childNodes[c], p = h.nodeType; | |
if (p === Node.ELEMENT_NODE || p === Node.TEXT_NODE&&!isNodeWhitespace(h)) { | |
f=!0; | |
break | |
} | |
} | |
if (!f) { | |
if (a === "P") { | |
var d = t.previousSibling, v = t.nextSibling; | |
if (d && d.nodeType === Node.TEXT_NODE&&!isNodeWhitespace(d) && v && v.nodeType === Node.TEXT_NODE&&!isNodeWhitespace(v)) | |
return !1 | |
} | |
return !0 | |
} | |
if (a === "P") | |
return !1 | |
} | |
if (a === "CANVAS") | |
return t.parentNode.tagName === "CUFON"; | |
var m = 0; | |
if (n) { | |
if (VeryNegativeClassNameRegEx.test(n.className)) | |
return !0; | |
var g = n.className, y = n.getAttribute("id"); | |
PositiveRegEx.test(g) && m++, PositiveRegEx.test(y) && m++, NegativeRegEx.test(g) && m--, NegativeRegEx.test(y) && m-- | |
} | |
if (m < 0) | |
return !0; | |
if (t.querySelector(".tweet-wrapper")) | |
return !1; | |
if (a === "UL" || a === "OL") { | |
if (n.querySelector("iframe") && n.querySelector("script")) | |
return !0; | |
var b = n.children, w = b.length; | |
if (!w) | |
return !0; | |
var E = 0, S = 0; | |
for (var c = 0; c < w; ++c) | |
SharingRegex.test(b[c].className) && E++, NegativeRegEx.test(b[c].className) && S++; | |
return E / w >= MinimumRatioOfListItemsBeingRelatedToSharingToPruneEntireList?!0 : S / w >= MinimumRatioOfListItemsBeingRelatedToSharingToPruneEntireList?!0 : !1 | |
} | |
if (a === "OBJECT") { | |
var x = t.querySelector("embed[src]"), T = x ? anchorForURL(x.src, this.contentDocument): null; | |
if (T && HostnamesKnownToContainEmbeddableMediaRegex.test(T.hostname)) | |
return !1; | |
var N = t.getAttribute("data"); | |
return T = N ? anchorForURL(N, this.contentDocument) : null, T && HostnamesKnownToContainEmbeddableMediaRegex.test(T.hostname)?!1 : !0 | |
} | |
if (t.childElementCount === 1) { | |
var C = t.firstElementChild; | |
if (C.tagName === "A") | |
return !1; | |
if (C.tagName === "SPAN" && C.className === "converted-anchor" && nearestAncestorElementWithTagName(C, "TABLE")) | |
return !1 | |
} | |
var k = t.getElementsByTagName("img"), L = k.length; | |
if (L) { | |
var A = 0; | |
for (var c = 0; c < L; ++c) { | |
var O = k[c].originalElement; | |
if (!isElementVisible(O)) | |
continue; | |
var M = cachedElementBoundingRect(O); | |
A += M.width / L * (M.height / L) | |
} | |
if (A > u) | |
return !1 | |
} | |
if (!this.commaCountIsLessThan(t, 10)) | |
return !1; | |
var _ = t.getElementsByTagName("p").length, D = t.getElementsByTagName("br").length, P = _ + Math.floor(D / 2); | |
if (L > P) | |
return !0; | |
if (t.getElementsByTagName("li").length > P) | |
return !0; | |
if (t.getElementsByTagName("input").length / P > r) | |
return !0; | |
if (t.textContent.length < o && L !== 1) | |
return !0; | |
if (t.querySelector("embed")) | |
return !0; | |
var H = this.calculateLinkDensity(t); | |
if (m >= 1 && H > i) | |
return !0; | |
if (m < 1 && H > s) | |
return !0; | |
if (a === "TABLE") { | |
var B = removeWhitespace(t.innerText).length, j = removeWhitespace(n.innerText).length; | |
if (B <= j * .5) | |
return !0 | |
} | |
return !1 | |
}, | |
wordCountIsLessThan: function(t, n) { | |
var r = 0, i = t.textContent, s =- 1; | |
while ((s = i.indexOf(" ", s + 1)) >= 0 && r < n) | |
r++; | |
return r < n | |
}, | |
leadingImageIsAppropriateWidth: function(t) { | |
return !this.article ||!t?!1 : t.getBoundingClientRect().width >= this.article.element.getBoundingClientRect().width - ToleranceForLeadingImageWidthToArticleWidthForFullWidthPresentation | |
}, | |
newDivFromNode: function(t) { | |
var n = this.contentDocument.createElement("div"); | |
return t && (n.innerHTML = t.innerHTML), n | |
}, | |
adoptableLeadingImage: function() { | |
const t = 5, n = /credit/, r = /caption/, i = /src|alt/; | |
if (!this.article ||!this.leadingImage ||!this.leadingImageIsAppropriateWidth(this.leadingImage)) | |
return null; | |
var s = this.leadingImage.parentNode, o = null, u = null, a = s.children.length; | |
if (s.tagName === "DIV" && a > 1 && a < t) { | |
var f = s.cloneNode(!0).querySelectorAll("p, div"), l = f.length; | |
for (var c = 0; c < l; ++c) { | |
var h = f[c]; | |
n.test(h.className) ? o = h.cloneNode(!0) : r.test(h.className) && (u = h.cloneNode(!0)) | |
} | |
} | |
var p = this.leadingImage.cloneNode(!1), d = p.attributes; | |
for (var c = 0; c < d.length; ++c) { | |
var v = d[c].nodeName; | |
i.test(v) || (p.removeAttribute(v), c--) | |
} | |
var m = this.contentDocument.createElement("div"); | |
m.className = "leading-image", m.appendChild(p); | |
if (o) { | |
var g = this.newDivFromNode(o); | |
g.className = "credit", m.appendChild(g) | |
} | |
if (u) { | |
var y = this.newDivFromNode(u); | |
y.className = "caption", m.appendChild(y) | |
} | |
return m | |
}, | |
adoptableArticle: function(t) { | |
if (this._adoptableArticle) | |
return this._adoptableArticle.cloneNode(!0); | |
clearCachedElementBoundingRects(), this.cacheWindowScrollPosition(); | |
var n = this.articleNode(t); | |
this._adoptableArticle = n ? n.cloneNode(!0) : null; | |
if (!this._adoptableArticle) | |
return this._adoptableArticle; | |
this._articleBoundingRect = cachedElementBoundingRect(this.article.element), this._adoptableArticle = this.cleanArticleNode(n, this._adoptableArticle, !1); | |
if (this._adoptableArticle.tagName === "P") { | |
var r = document.createElement("div"); | |
r.appendChild(this._adoptableArticle), this._adoptableArticle = r | |
} | |
var i = this.extraArticleNode(); | |
if (i) { | |
var s = this.cleanArticleNode(i, i.cloneNode(!0), !0); | |
s && (this.extraArticle.isPrepended ? this._adoptableArticle.insertBefore(s, this._adoptableArticle.firstChild) : this._adoptableArticle.appendChild(s)); | |
var o = cachedElementBoundingRect(this.article.element), u = cachedElementBoundingRect(this.extraArticle.element), a = { | |
top: Math.min(o.top, u.top), | |
right: Math.max(o.right, u.right), | |
bottom: Math.max(o.bottom, u.bottom), | |
left: Math.min(o.left, u.left) | |
}; | |
a.width = a.right - a.left, a.height = a.bottom - a.top, this._articleBoundingRect = a | |
} | |
this._articleTextContent = this._adoptableArticle.innerText; | |
var f = this.adoptableLeadingImage(); | |
return f && this._adoptableArticle.insertBefore(f, this._adoptableArticle.firstChild), this._adoptableArticle | |
}, | |
elementPinToEdge: function(t) { | |
const n = { | |
AREA: 1, | |
BR: 1, | |
CANVAS: 1, | |
EMBED: 1, | |
FRAME: 1, | |
HR: 1, | |
IMG: 1, | |
INPUT: 1 | |
}, r = 120; | |
if (window.scrollY < r) | |
return null; | |
var i = cachedElementBoundingRect(t), s = t.ownerDocument.elementFromPoint((i.left + i.right) / 2, 0); | |
s && s.tagName in n && (s = s.parentElement); | |
var o = s; | |
while (o && o !== t) | |
o = o.parentNode; | |
return o ? s : null | |
}, | |
dominantContentSelectorAndDepth: function(e) { | |
const t = 2; | |
var n = {}, r = {}; | |
walkElementSubtree | |
(e, t, function(e, t) { | |
if (!isElementVisible(e)) | |
return; | |
var i = selectorForElement(e) + " | " + t; | |
r[i] ? r[i] += 1 : (r[i] = 1, n[i] = e) | |
}); | |
var i, s = arrayOfKeysAndValuesOfObjectSortedByValueDescending(r); | |
switch (s.length) { | |
case 0: | |
break; | |
case 1: | |
i = s[0].key; | |
break; | |
default: | |
var o = s[0]; | |
o.value > s[1].value && (i = o.key) | |
} | |
if (!i) | |
return null; | |
var u = n[i]; | |
return { | |
selector: selectorForElement(u), | |
depth: depthOfElementWithinElement(u, e) | |
} | |
}, | |
functionToPreventPruningElementDueToInvisibility: function() { | |
const e = [[/nytimes.com/, function(e, t) { | |
var n = e; | |
if (!t) | |
return !1; | |
while (n && n !== t) { | |
if (n.classList.contains("hidden")) | |
return !0; | |
n = n.parentElement | |
} | |
return !1 | |
} | |
]]; | |
var t = e.length; | |
for (var n = 0; n < t; ++n) { | |
var r = e[n], i = r[0]; | |
if (i.test(this.contentDocument.location.hostname)) | |
return r[1] | |
} | |
return function() { | |
return !1 | |
} | |
}, | |
cleanArticleNode: function(t, n, r) { | |
function S(e) { | |
f += e, l && (l += e), c && (c += e), h && (h += e), p && (p += e) | |
} | |
function x() { | |
l === 1 && (l = 0), c === 1 && (c = 0), h === 1 && (h = 0), p === 1 && (p = 0) | |
} | |
function T() { | |
const e = .8; | |
var n = cachedElementBoundingRect(t); | |
if (n.width === 0 || n.height === 0) | |
return !0; | |
var r = childrenWithParallelStructure(t), i = r.length, s; | |
if (i) { | |
s = []; | |
for (var o = 0; o < i; ++o) { | |
var u = r[o]; | |
if (getComputedStyle(u).float === "none") { | |
var a = u.children, f = a.length; | |
for (var l = 0; l < f; ++l) | |
s.push(a[l]) | |
} else | |
s.push(u) | |
} | |
} else | |
s = t.children; | |
var c = s.length, h = 0; | |
for (var o = 0; o < c; ++o) { | |
var p = s[o]; | |
getComputedStyle(p).float !== "none" && (h += p.innerText.length) | |
} | |
var d = t.innerText.length, v = h / d; | |
return v > e | |
} | |
function N(e) { | |
const n = 50; | |
if (cachedElementBoundingRect(e).height > n) | |
return !1; | |
const r = { | |
UL: 1, | |
LI: 1, | |
NAV: 1 | |
}; | |
return r[e.tagName]?!0 : e.parentElement === t&&!e.nextElementSibling?!0 : !1 | |
} | |
const i = { | |
FORM: 1, | |
SCRIPT: 1, | |
STYLE: 1, | |
LINK: 1 | |
}, s = { | |
DIV: 1, | |
TABLE: 1, | |
OBJECT: 1, | |
UL: 1, | |
CANVAS: 1, | |
P: 1, | |
IFRAME: 1, | |
ASIDE: 1, | |
SECTION: 1, | |
FOOTER: 1, | |
NAV: 1, | |
OL: 1 | |
}, o = { | |
I: 1, | |
EM: 1 | |
}, u = { | |
B: 1, | |
STRONG: 1, | |
H1: 1, | |
H2: 1, | |
H3: 1, | |
H4: 1, | |
H5: 1, | |
H6: 1 | |
}; | |
var a = [], f = 0, l = 0, c = 0, h = 0, p = 0, d = t, v = d.ownerDocument.defaultView, m = n, g = this.articleTitle(), y = this._articleTitleElement, b = this.elementPinToEdge(t), w = null, E = isElementVisible(t), C = this.dominantContentSelectorAndDepth(t), k = T(), L = new Set; | |
this.previouslyDiscoveredPageURLStrings.forEach(function(e) { | |
L.add(e) | |
}); | |
var A = this.nextPageURL(); | |
A && L.add(A); | |
var O = null; | |
this._articleTitleElement && (O = cachedElementBoundingRect(this._articleTitleElement)); | |
var M = this.functionToPreventPruningElementDueToInvisibility(); | |
while (d) { | |
var _ = null, D = m.tagName; | |
m.originalElement = d, d === b && (w = m), D in i && (_ = m), !_ && d === y && (_ = m); | |
if (!_ && (D === "H1" || D === "H2")) { | |
var P = d.offsetTop - t.offsetTop; | |
if (P < HeaderMinimumDistanceFromArticleTop) { | |
var H = innerTextOrTextContent(d), B = H.length * HeaderLevenshteinDistanceToLengthRatio; | |
levenshteinDistance(g, H) <= B && (_ = m) | |
} | |
} | |
_ || this.isMediaWikiPage() && /editsection/.test(d.className) && (_ = m); | |
var j; | |
_ || (j = getComputedStyle(d)); | |
if (!_ && D === "DIV" && m.parentNode) { | |
var F = d.querySelectorAll("a, blockquote, dl, div, img, ol, p, pre, table, ul"), I = l || j["float"] !== "none"; | |
if (!I&&!F.length) { | |
var q = m.parentNode, R = this.contentDocument.createElement("p"); | |
while (m.firstChild) { | |
var U = m.firstChild; | |
R.appendChild(U) | |
} | |
q.replaceChild(R, m), w === m && (w = R), m = R, m.originalElement = d, D = m.tagName | |
} | |
} | |
!_ && m.parentNode && D in s && a.push(m); | |
if (!_) { | |
if (E) { | |
var z = j.display === "none" || j.visibility !== "visible" || computedStyleIndicatesElementIsInvisibleDueToClipping(j); | |
if (z) { | |
var W = C ? f === C.depth && selectorForElement(d) === C.selector: !1; | |
!W&&!M(d, t) && (_ = m) | |
} | |
} | |
isElementPositionedOffScreen(d) ? _ = m : d !== t&&!l && j["float"] !== "none"&&!k && (cachedElementBoundingRect(d).height >= FloatMinimumHeight || d.childElementCount > 1) && (l = 1) | |
} | |
if (!_) { | |
var X = m.attributes; | |
for (var V = 0; V < X.length; ++V) { | |
var $ = X[V].nodeName; | |
AttributesToRemoveRegEx.test($) && (m.removeAttribute($), V--) | |
} | |
j.clear === "both" && m.classList.add("clear"); | |
if ((D === "UL" || D === "OL") && j["list-style-type"] === "none" && j["background-image"] === "none") { | |
var J = d.children, K = J.length, Q=!0; | |
for (var V = 0; V < K; ++V) { | |
var G = getComputedStyle(J[V]); | |
if (G["list-style-type"] !== "none" || parseInt(G["-webkit-padding-start"]) !== 0) { | |
Q=!1; | |
break | |
} | |
} | |
Q && m.classList.add("list-style-type-none") | |
} | |
!h && j.fontStyle !== "normal" && (D in o || (m.style.fontStyle = j.fontStyle), h = 1), !p && j.fontWeight !== "normal" && (D in u || (m.style.fontWeight = j.fontWeight), p = 1); | |
if (l) { | |
l === 1 && (cachedElementBoundingRect(d).width <= MaximumFloatWidth ? m.setAttribute("class", "auxiliary float " + j["float"]) : m.classList.add("auxiliary")); | |
var Y = d.style.getPropertyValue("width"); | |
if (Y) | |
m.style.width = Y; | |
else { | |
var Z = v.getMatchedCSSRules(d, "", !0); | |
if (Z) { | |
var et = Z.length; | |
for (var V = et - 1; V >= 0; --V) { | |
Y = Z[V].style.getPropertyValue("width"); | |
if (Y) { | |
m.style.width = Y; | |
break | |
} | |
} | |
} | |
} | |
l === 1&&!Y && (m.style.width = cachedElementBoundingRect(d).width + "px"); | |
var tt = m.parentNode === n ? 36: 12, nt = m.style.width; | |
nt && parseInt(nt) >= screen.width - tt && m.setAttribute("class", "large-element") | |
} | |
if (D === "TABLE") | |
c || (c = 1); | |
else if (D === "VIDEO") { | |
var rt = cachedElementBoundingRect(d); | |
const it = 36; | |
rt.width > screen.width - it && m.setAttribute("class", "large-element") | |
} else if (D === "IMG") { | |
var st=!1, ot = X.length; | |
for (var V = 0; V < ot; ++V) { | |
var $ = X[V].nodeName; | |
if (KnownImageLazyLoadingAttributes[$.toLowerCase()]) { | |
m.setAttribute("src", m.getAttribute($)), st=!0; | |
break | |
} | |
} | |
m.removeAttribute("border"), m.removeAttribute("hspace"), m.removeAttribute("vspace"); | |
var ut = m.getAttribute("align"); | |
m.removeAttribute("align"); | |
if (ut === "left" || ut === "right") | |
m.classList.add("float"), m.classList.add(ut); | |
if (!l&&!st) { | |
var at = cachedElementBoundingRect(d), ft = at.width, lt = at.height; | |
ft === 1 && lt === 1 ? _ = m : O && lt < MinimumHeightForImagesAboveTheArticleTitle && at.bottom < O.top ? _ = m : ft < ImageSizeTiny && lt < ImageSizeTiny && m.setAttribute("class", "reader-image-tiny") | |
} | |
} else if (D === "FONT") | |
m.removeAttribute("size"), m.removeAttribute("face"), m.removeAttribute("color"); | |
else if (D === "A" && m.parentNode) { | |
var ct = m.getAttribute("href"); | |
if (ct && ct.length && (ct[0] === "#" || ct.substring(0, 11) === "javascript:")) { | |
if (!c&&!m.childElementCount && m.parentElement.childElementCount === 1 && m.parentElement.tagName !== "LI") { | |
var ht = this.contentDocument.evaluate("text()", m.parentElement, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); | |
ht.snapshotLength || (_ = m) | |
} | |
if (!_) { | |
var R = this.contentDocument.createElement("span"); | |
if (m.childElementCount === 1 && m.firstElementChild.tagName === "IMG") { | |
var pt = m.firstElementChild; | |
pt.width > AnchorImageMinimumWidth && pt.height > AnchorImageMinimumHeight && R.setAttribute("class", "converted-image-anchor") | |
} | |
R.className || R.setAttribute("class", "converted-anchor"); | |
while (m.firstChild) | |
R.appendChild(m.firstChild); | |
m.parentNode.replaceChild(R, m), m = R, w === m && (w = R) | |
} | |
} | |
} | |
} | |
!_ && elementIsCommentBlock(d) && (_ = m); | |
if (!_ && D === "A" && L.has(d.href)) { | |
var dt = d, vt = m, mt, gt; | |
while ((dt = dt.parentElement) && (vt = vt.parentElement)) { | |
const yt = 10; | |
if (cachedElementBoundingRect(dt).top - cachedElementBoundingRect(d).top > yt) | |
break; | |
if (dt === t) | |
break; | |
N(dt) && (mt = dt, gt = vt) | |
} | |
mt && (_ = gt, d = mt, m = gt, m.originalElement = d, D = m.tagName), dt = null, vt = null, mt = null, gt = null | |
} | |
var bt = _ ? null: d.firstElementChild; | |
if (bt) | |
d = bt, m = m.firstElementChild, S(1); | |
else { | |
var wt; | |
while (d !== t&&!(wt = d.nextElementSibling)) | |
d = d.parentElement, m = m.parentElement, S( - 1); | |
if (d === t) { | |
if (_) | |
if (_.parentElement) | |
_.remove(); | |
else if (r) | |
return null; | |
break | |
} | |
d = wt, m = m.nextElementSibling, x() | |
} | |
if (_) | |
if (_.parentElement) | |
_.remove(); | |
else if (r) | |
return null | |
} | |
var Et = n.querySelectorAll("iframe"), St = Et.length; | |
for (var V = 0; V < St; ++V) { | |
var xt = Et[V]; | |
if (elementLooksLikeEmbeddedTweet(xt.originalElement)) { | |
var Tt = this.adoptableSimpleTweetFromTwitterIframe(xt); | |
Tt && xt.parentElement.replaceChild(Tt, xt) | |
} | |
} | |
for (var V = a.length - 1; V >= 0; --V) { | |
var Nt = a[V]; | |
Nt.parentNode && this.shouldPruneElement(Nt, Nt.originalElement) && (w === Nt && ((w = Nt.nextElementSibling) || (w = Nt.parentElement)), Nt.remove()) | |
} | |
var Ct = n.querySelectorAll(".float"); | |
for (var V = 0; V < Ct.length; ++V) { | |
var kt=!1, Lt = Ct[V]; | |
if (!kt) { | |
var At = Lt.querySelectorAll("a, span.converted-image-anchor"), Ot = Lt.querySelectorAll("span.converted-anchor"); | |
kt = Lt.parentNode && Ot.length > At.length | |
} | |
if (!kt) { | |
var Mt = Lt.querySelectorAll("embed, object").length, _t = Lt.originalElement.querySelectorAll("embed, object").length; | |
!Mt && _t && (kt=!0) | |
} | |
if (!kt) { | |
var Dt = Lt.originalElement.getElementsByTagName("img"), Pt = Dt.length, Ht = 0; | |
for (var Bt = 0; Bt < Pt; ++Bt) { | |
E && isElementVisible(Dt[Bt]) && Ht++; | |
if (Ht > 1) | |
break | |
} | |
if (Ht === 1) { | |
var jt = Lt.getElementsByTagName("img").length; | |
jt || (kt=!0) | |
} | |
} | |
kt && (w === Lt && ((w = Lt.nextElementSibling) || (w = Lt.parentElement)), Lt.remove()) | |
} | |
if (r&&!removeWhitespace(n.innerText).length) | |
return null; | |
if (w) { | |
var Ft = document.createElement("div"), It = w.originalElement.getBoundingClientRect(), qt = It.height > 0 ? It.top * 100 / It.height: 0; | |
Ft.style.position = "relative", Ft.style.top = Math.round( - qt) + "%", Ft.setAttribute("id", "safari-reader-element-marker"), w.insertBefore(Ft, w.firstChild) | |
} | |
return n | |
}, | |
adoptableSimpleTweetFromTwitterIframe: function(t) { | |
var n = t.originalElement.contentDocument.documentElement, r = n.querySelector("[data-tweet-id].expanded"); | |
if (!r) | |
return null; | |
var i = this.contentDocument.createElement("div"); | |
i.classList.add("tweet-wrapper"); | |
var s = this.contentDocument.createElement("blockquote"); | |
s.classList.add("simple-tweet"), i.appendChild(s); | |
var o = r.getAttribute("data-tweet-id"); | |
i.setAttribute("data-reader-tweet-id", o); | |
var u = r.querySelector(".dateline"), a = r.querySelector('[data-scribe="element:screen_name"]'), f = r.querySelector('[data-scribe="element:name"]'), l = r.querySelector(".e-entry-title"); | |
if (!u ||!a ||!f ||!l) | |
return i; | |
var c = "— " + f.innerText + " (" + a.innerText + ")", h = this.contentDocument.createElement("p"); | |
h.innerHTML = l.innerHTML, s.appendChild(h), s.insertAdjacentHTML("beforeend", c); | |
var p = this.contentDocument.createElement("span"); | |
p.innerHTML = u.innerHTML, s.appendChild(p); | |
var d = s.querySelectorAll("img.twitter-emoji"), v = d.length; | |
for (var m = 0; m < v; ++m) { | |
var g = d[m], y = g.getAttribute("alt"); | |
if (y && y.length > 0) { | |
var b = this.contentDocument.createElement("span"); | |
b.innerText = y, g.parentNode.replaceChild(b, g) | |
} | |
} | |
return i | |
}, | |
leadingImageNode: function() { | |
const t = 250, n = .5, r = 3; | |
if (!this.article ||!this.article.element) | |
return null; | |
var i = this.article.element; | |
for (var s = 0; s < r; ++s) { | |
if (!i.parentNode) | |
break; | |
i = i.parentNode; | |
var o = i.getElementsByTagName("img")[0]; | |
if (o) { | |
var u = cachedElementBoundingRect(o); | |
if (u.height >= t && u.width >= this._articleWidth * n) { | |
var a = this.article.element.compareDocumentPosition(o); | |
if (!(a & DocumentPositionPreceding) || a & DocumentPositionContainedBy) | |
continue; | |
a = this.extraArticle ? this.extraArticle.element.compareDocumentPosition(o) : null; | |
if (a && (!(a & DocumentPositionPreceding) || a & DocumentPositionContainedBy)) | |
continue; | |
return o | |
} | |
} | |
} | |
return null | |
}, | |
mainImageNode: function() { | |
var t = this.leadingImageNode(); | |
if (t) | |
return t; | |
if (this.article && this.article.element) { | |
var n = this.article.element.querySelectorAll("img"), r = n.length; | |
for (var i = 0; i < r; ++i) { | |
var s = n[i], o = s._cachedElementBoundingRect; | |
o || (o = s.getBoundingClientRect()); | |
if (o.width >= MainImageMinimumWidthAndHeight && o.height >= MainImageMinimumWidthAndHeight) | |
return s | |
} | |
} | |
return null | |
}, | |
articleTitle: function() { | |
function m(e, t) { | |
var n = e ? t.indexOf(e): - 1; | |
return n!==-1 && (n === 0 || n + e.length === t.length) | |
} | |
function g(e, t) { | |
return e.host === t.host && e.pathname === t.pathname | |
} | |
if (!this.articleNode()) | |
return; | |
if (this._articleTitle) | |
return this._articleTitle; | |
const t = 500, n = 20, r = 8, i = 1.1, s = 1.25, o = /header|title|headline|instapaper_title/i, u = 1.5, a = 1.8, f = 1.5, l = .6, c = 3, h = 1.5, p = 9, d = 1.5, v = /byline|author/i; | |
var y = function(e) { | |
var t = this.contentDocument.querySelector(e), n = t && t.attributes.length === 2 ? t.content: null; | |
if (n) { | |
var r = this.articleTitleAndSiteNameFromTitleString(n); | |
r && (n = r.articleTitle) | |
} | |
return n | |
}.bind(this), b = this.contentDocument.title, w = y("head meta[property='og:title']"), E = y("head meta[name='twitter:title']"), S = cachedElementBoundingRect(this.articleNode()); | |
this.extraArticleNode() && this.extraArticle.isPrepended && (S = cachedElementBoundingRect(this.extraArticleNode())); | |
var x = S.left + S.width / 2, T = S.top, N = T; | |
this._articleWidth = S.width, this.leadingImage = this.leadingImageNode(); | |
if (this.leadingImage) { | |
var C = cachedElementBoundingRect(this.leadingImage); | |
N = (C.top + T) / 2 | |
} | |
var k = "h1, h2, h3, h4, h5, .headline, .article_title, #hn-headline, .inside-head, .instapaper_title", L = this.article.element.tagName; | |
if (L === "DL" || L === "DD") | |
k += ", dt"; | |
var A = this.contentDocument.querySelectorAll(k); | |
A = Array.prototype.slice.call(A, 0); | |
var O = this.contentDocument.location, M = this.article.element.getElementsByTagName("a"); | |
for (var _ = 0; _ < M.length; _++) { | |
var D = M[_]; | |
if (D.offsetTop > this.articleNode().offsetTop + n) | |
break; | |
if (g(D, O)) { | |
A.push(D); | |
break | |
} | |
} | |
var P, H = A.map(innerTextOrTextContent), B = A.length, j = 0, F = [], I = [], q = []; | |
for (var _ = 0; _ < B; ++_) { | |
var R = A[_], U = H[_], z = stringSimilarity(b, U); | |
if (w) { | |
var W = stringSimilarity(w, U); | |
z += W, W > StringSimilarityToDeclareStringsNearlyIdentical && I.push(R) | |
} | |
if (E) { | |
var X = stringSimilarity(E, U); | |
z += X, X > StringSimilarityToDeclareStringsNearlyIdentical && q.push(R) | |
} | |
z === j ? F.push(R) : z > j && (j = z, F = [R]) | |
} | |
I.length === 1 ? (P = I[0], P.headerText = innerTextOrTextContent(P)) : q.length === 1 && (P = q[0], P.headerText = innerTextOrTextContent(P)); | |
if (!P) | |
for (var _ = 0; _ < B; ++_) { | |
var R = A[_]; | |
if (!isElementVisible(R)) | |
continue; | |
var V = cachedElementBoundingRect(R), $ = V.left + V.width / 2, J = V.top + V.height / 2, K = $ - x, Q = J - N, G = I.indexOf(R)!==-1, Y = q.indexOf(R)!==-1, Z = R.classList.contains("instapaper_title"), et = R.getAttribute("itemprop") === "headline", tt = G || Y || Z || et, nt = Math.sqrt(K * K + Q * Q), rt = tt ? t: Math.max(t - nt, 0), U = H[_], it = R.getAttribute("property"); | |
if (it) { | |
var st = /dc.title/i.exec(it); | |
if (st && st[0]) { | |
var ot = this.contentDocument.querySelectorAll('*[property~="' + st[0] + '"]'); | |
if (ot.length === 1) { | |
P = R, P.headerText = U; | |
break | |
} | |
} | |
} | |
if (v.test(R.className)) | |
continue; | |
if (!tt) { | |
if (nt > t) | |
continue; | |
if ($ < S.left || $ > S.right) | |
continue | |
} | |
if (b && stringsAreNearlyIdentical(U, b)) | |
rt*=c; | |
else if (m(U, b)) | |
rt*=h; | |
else if (U.length < r) | |
continue; | |
var ut=!1, at = nearestAncestorElementWithTagName(R, "A"); | |
at || (at = R.querySelector("a")); | |
if (at) { | |
var ft = at.host === O.host, lt = at.pathname === O.pathname; | |
if (ft && lt) | |
rt*=f; | |
else { | |
if (ft && nearestAncestorElementWithTagName(R, "LI")) | |
continue; | |
rt*=l, ut=!0 | |
} | |
} | |
var ct = fontSizeFromComputedStyle(getComputedStyle(R)); | |
ut || (rt*=ct / BaseFontSize), rt*=1 + TitleCandidateDepthScoreMultiplier * elementDepth(R); | |
var ht = parseInt(this.contentTextStyle().fontSize); | |
parseInt(ct) > ht * i && (rt*=s); | |
if (o.test(R.className) || o.test(R.getAttribute("id"))) | |
rt*=u; | |
var pt = R.parentElement; | |
pt && (o.test(pt.className) || o.test(pt.getAttribute("id"))) && (rt*=u), F.indexOf(R)!==-1 && (rt*=a); | |
if (!P || rt > P.headerScore) | |
P = R, P.headerScore = rt, P.headerText = U | |
} | |
P && domDistance(P, this.articleNode(), p + 1) > p && parseInt(getComputedStyle(P).fontSize) < d * ht && (P = null); | |
if (P) { | |
this._articleTitleElement = P; | |
var dt = P.headerText.trim(); | |
w && m(w, dt) ? this._articleTitle = w : b && m(b, dt) ? this._articleTitle = b : this._articleTitle = dt | |
} | |
return this._articleTitle || (w && m(w, b) ? this._articleTitle = w : this._articleTitle = b), this._articleTitle | |
}, | |
articleIsLTR: function() { | |
if (!this._articleIsLTR) { | |
var t = getComputedStyle(this.article.element); | |
this._articleIsLTR = t ? t.direction === "ltr" : !0 | |
} | |
return this._articleIsLTR | |
}, | |
findSuggestedCandidate: function() { | |
var t = this.suggestedRouteToArticle; | |
if (!t ||!t.length) | |
return null; | |
var n, r; | |
for (r = t.length - 1; r >= 0; --r) | |
if (t[r].id) { | |
n = this.contentDocument.getElementById(t[r].id); | |
if (n) | |
break | |
} | |
r++, n || (n = this.contentDocument); | |
while (r < t.length) { | |
var i = t[r], s = n.nodeType === Node.DOCUMENT_NODE ? n.documentElement: n.firstElementChild; | |
for (var o = 1; s && o < i.index; s = s.nextElementSibling) | |
this.shouldIgnoreInRouteComputation(s) || o++; | |
if (!s) | |
return null; | |
if (s.tagName !== i.tagName) | |
return null; | |
if (i.className && s.className !== i.className) | |
return null; | |
n = s, r++ | |
} | |
return isElementVisible(n) ? new CandidateElement(n, this.contentDocument) : null | |
}, | |
canRunReaderDetection: function() { | |
var e = this.contentDocument.location.hostname, t = this.contentDocument.location.pathname; | |
for (var n in BlacklistedHostsAllowedPathRegexMap) { | |
var r = new RegExp(n.escapeForRegExp()); | |
if (!r.test(e)) | |
continue; | |
var i = BlacklistedHostsAllowedPathRegexMap[n]; | |
return i instanceof RegExp ? i.test(t) : !1 | |
} | |
return !0 | |
}, | |
findArticleBySearchingAllElements: function(t) { | |
var n = this.findSuggestedCandidate(), r = this.findCandidateElements(); | |
if (!r ||!r.length) | |
return n; | |
if (n && n.basicScore() >= ReaderMinimumScore) | |
return n; | |
var i = this.highestScoringCandidateFromCandidates(r); | |
for (var s = i.element; s !== this.contentDocument; s = s.parentNode) | |
if (s.tagName === "BLOCKQUOTE") { | |
var o = s.parentNode, u = r.length; | |
for (var a = 0; a < u; ++a) { | |
var f = r[a]; | |
if (f.element === o) { | |
i = f; | |
break | |
} | |
} | |
break | |
} | |
if (n && i.finalScore() < ReaderMinimumScore) | |
return n; | |
if (!t) { | |
if (i.shouldDisqualifyDueToScoreDensity()) | |
return null; | |
if (i.shouldDisqualifyDueToHorizontalRuleDensity()) | |
return null; | |
if (i.shouldDisqualifyDueToHeaderDensity()) | |
return null; | |
if (i.shouldDisqualifyDueToSimilarElements(r)) | |
return null | |
} | |
return i | |
}, | |
findExtraArticle: function() { | |
if (!this.article) | |
return null; | |
for (var t = 0, n = this.article.element; t < 3 && n; ++t, n = n.parentNode) { | |
var r = this.findExtraArticleCandidateElements(n); | |
if (!r ||!r.length) | |
continue; | |
var i = this.sortCandidateElementsInDescendingScoreOrder(r), s; | |
for (var o = 0; o < i.length; o++) { | |
s = i[o]; | |
if (!s ||!s.basicScore()) | |
break; | |
if (s.shouldDisqualifyDueToScoreDensity()) | |
continue; | |
if (s.shouldDisqualifyDueToHorizontalRuleDensity()) | |
continue; | |
if (s.shouldDisqualifyDueToHeaderDensity()) | |
continue; | |
if (cachedElementBoundingRect(s.element).height < PrependedArticleCandidateMinimumHeight && cachedElementBoundingRect(this.article.element).width !== cachedElementBoundingRect(s.element).width) | |
continue; | |
var u = contentTextStyleForNode(this.contentDocument, s.element); | |
if (!u) | |
continue; | |
if (u.fontFamily !== this.contentTextStyle().fontFamily || u.fontSize !== this.contentTextStyle().fontSize) | |
continue; | |
if (s) | |
return s | |
} | |
} | |
return null | |
}, | |
highestScoringCandidateFromCandidates: function(t) { | |
var n = 0, r = null, i = t.length; | |
for (var s = 0; s < i; ++s) { | |
var o = t[s], u = o.basicScore(); | |
u >= n && (n = u, r = o) | |
} | |
return r | |
}, | |
sortCandidateElementsInDescendingScoreOrder: function(t) { | |
function n(e, t) { | |
return e.basicScore() !== t.basicScore() ? t.basicScore() - e.basicScore() : t.depth() - e.depth() | |
} | |
return t.sort(n) | |
}, | |
findCandidateElements: function() { | |
const t = 1e3; | |
var n = Date.now() + t, r = this.contentDocument.getElementsByTagName("*"), i = r.length, s = []; | |
for (var o = 0; o < i; ++o) { | |
var u = r[o]; | |
if (CandidateTagNamesToIgnore[u.tagName]) | |
continue; | |
var a = CandidateElement.candidateIfElementIsViable(u, this.contentDocument); | |
a && s.push(a); | |
if (Date.now() > n) { | |
s = []; | |
break | |
} | |
} | |
var f = s.length; | |
for (var o = 0; o < f; ++o) | |
s[o].element.candidateElement = s[o]; | |
for (var o = 0; o < f; ++o) { | |
var l = s[o]; | |
if (l.element.tagName !== "BLOCKQUOTE") | |
continue; | |
var c = l.element.parentElement.candidateElement; | |
if (!c) | |
continue; | |
c.addTextNodesFromCandidateElement(l) | |
} | |
for (var o = 0; o < f; ++o) | |
s[o].element.candidateElement = null; | |
return s | |
}, | |
findExtraArticleCandidateElements: function(t) { | |
if (!this.article) | |
return []; | |
t || (t = this.article.element); | |
var n = "preceding-sibling::*/descendant-or-self::*", r = this.contentDocument.evaluate(n, t, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null), i = r.snapshotLength, s = []; | |
for (var o = 0; o < i; ++o) { | |
var u = r.snapshotItem(o); | |
if (CandidateTagNamesToIgnore[u.tagName]) | |
continue; | |
var a = CandidateElement.extraArticleCandidateIfElementIsViable(u, this.article, this.contentDocument, !0); | |
a && s.push(a) | |
} | |
n = "following-sibling::*/descendant-or-self::*", r = this.contentDocument.evaluate(n, t, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null), i = r.snapshotLength; | |
for (var o = 0; o < i; ++o) { | |
var u = r.snapshotItem(o); | |
if (CandidateTagNamesToIgnore[u.tagName]) | |
continue; | |
var a = CandidateElement.extraArticleCandidateIfElementIsViable(u, this.article, this.contentDocument, !1); | |
a && s.push(a) | |
} | |
return s | |
}, | |
isGeneratedBy: function(t) { | |
var n = this.contentDocument.head ? this.contentDocument.head.querySelector("meta[name=generator]"): null; | |
if (!n) | |
return !1; | |
var r = n.content; | |
return r ? t.test(r) : !1 | |
}, | |
isMediaWikiPage: function() { | |
return this.isGeneratedBy(/^MediaWiki /) | |
}, | |
isWordPressSite: function() { | |
return this.isGeneratedBy(/^WordPress/) | |
}, | |
nextPageURLString: function() { | |
if (!this.article) | |
return null; | |
if (this.isMediaWikiPage()) | |
return null; | |
var t, n = 0, r = this.article.element; | |
r.parentNode && getComputedStyle(r).display === "inline" && (r = r.parentNode); | |
var i = r, s = cachedElementBoundingRect(r).bottom + LinkMaxVerticalDistanceFromArticle; | |
while (isElementNode(i) && cachedElementBoundingRect(i).bottom <= s) | |
i = i.parentNode; | |
i !== r && (i === this.contentDocument || isElementNode(i)) && (r = i); | |
var o = this.contentDocument.evaluate(LinkCandidateXPathQuery, r, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null), u = o.snapshotLength; | |
if (this.pageNumber <= 2&&!this.prefixWithDateForNextPageURL) { | |
var a = this.contentDocument.location.pathname, f = a.match(LinkDateRegex); | |
f && (f = f[0], this.prefixWithDateForNextPageURL = a.substring(0, a.indexOf(f) + f.length)) | |
} | |
for (var l = 0; l < u; ++l) { | |
var c = o.snapshotItem(l), h = this.scoreNextPageLinkCandidate(c); | |
h > n && (t = c, n = h) | |
} | |
return t ? t.href : null | |
}, | |
scoreNextPageLinkCandidate: function(t) { | |
function n(e, t, n, r) { | |
t.substring(0, e.length) === e && (t = t.substring(e.length), e = ""); | |
var i = t.lastInteger(); | |
if (isNaN(i)) | |
return !1; | |
var s = e ? e.lastInteger(): NaN; | |
if (isNaN(s) || s >= MaximumExactIntegralValue) | |
s = r; | |
return i === s ? n.lastInteger() === s + 1 : i === s + 1 | |
} | |
function r(e) { | |
var t = {}, n = e.substring(1).split("&"), r = n.length; | |
for (var i = 0; i < r; ++i) { | |
var s = n[i], o = s.indexOf("="); | |
o===-1 ? t[s] = null : t[s.substring(0, o)] = s.substring(o + 1) | |
} | |
return t | |
} | |
var i = this.contentDocument.location; | |
if (t.host !== i.host) | |
return 0; | |
if (t.pathname === i.pathname && t.search === i.search) | |
return 0; | |
if (t.toString().indexOf("#")!==-1) | |
return 0; | |
if (anchorLinksToAttachment(t) || anchorLinksToTagOrCategoryPage(t)) | |
return 0; | |
if (!isElementVisible(t)) | |
return 0; | |
var s = cachedElementBoundingRect(t), o = this._articleBoundingRect, u = Math.max(0, Math.max(o.top - (s.top + s.height), s.top - (o.top + o.height))); | |
if (s.top < o.top) | |
return 0; | |
if (u > LinkMaxVerticalDistanceFromArticle) | |
return 0; | |
var a = Math.max(0, Math.max(o.left - (s.left + s.width), s.left - (o.left + o.width))); | |
if (a > 0) | |
return 0; | |
var f = i.pathname, l = t.pathname; | |
if (this.prefixWithDateForNextPageURL) { | |
if (t.pathname.indexOf(this.prefixWithDateForNextPageURL)===-1) | |
return 0; | |
f = f.substring(this.prefixWithDateForNextPageURL.length), l = l.substring(this.prefixWithDateForNextPageURL.length) | |
} | |
var c = l.substring(1).split("/"); | |
c[c.length - 1] || c.pop(); | |
var h = c.length, p = f.substring(1).split("/"), d=!1; | |
p[p.length - 1] || (d=!0, p.pop()); | |
var v = p.length; | |
if (h < v) | |
return 0; | |
var m = 0, g = 0, y = t.textContent; | |
for (var b = 0; b < h; ++b) { | |
var w = c[b], E = b < v ? p[b]: ""; | |
if (E !== w) { | |
if (b < v - 2) | |
return 0; | |
if (w.length >= E.length) { | |
var S = 0; | |
while (w[w.length - 1 - S] === E[E.length - 1 - S]) | |
S++; | |
S && (w = w.substring(0, w.length - S), E = E.substring(0, E.length - S)); | |
var x = w.indexOf(E); | |
x!==-1 && (w = w.substring(x)) | |
} | |
n(E, w, y, this.pageNumber) ? g = Math.pow(LinkNextOrdinalValueBase, b - h + 1) : m++ | |
} | |
if (m > 1) | |
return 0 | |
} | |
var T=!1; | |
if (t.search) { | |
linkParameters = r(t.search), referenceParameters = r(i.search); | |
for (var N in linkParameters) { | |
var C = linkParameters[N], k = N in referenceParameters ? referenceParameters[N]: null; | |
if (k !== C) { | |
k === null && (k = ""), C === null && (C = ""); | |
if (C.length < k.length) | |
m++; | |
else if (n(k, C, y, this.pageNumber)) { | |
if (LinkURLSearchParameterKeyMatchRegex.test(N)) { | |
if (f.toLowerCase() !== l.toLowerCase()) | |
return 0; | |
if (this.isWordPressSite() && d) | |
return 0; | |
T=!0 | |
} | |
if (LinkURLBadSearchParameterKeyMatchRegex.test(N)) { | |
m++; | |
continue | |
} | |
g = Math.max(g, 1 / LinkNextOrdinalValueBase) | |
} else | |
m++ | |
} | |
} | |
} | |
if (!g) | |
return 0; | |
if (LinkURLPageSlashNumberMatchRegex.test(t.href) || LinkURLSlashDigitEndMatchRegex.test(t.href)) | |
T=!0; | |
if (!T && h === v && stringSimilarity(f, l) < LinkMinimumURLSimilarityRatio) | |
return 0; | |
if (LinkURLArchiveSlashDigitEndMatchRegex.test(t)) | |
return 0; | |
var L = LinkMatchWeight * (Math.pow(LinkMismatchValueBase, - m) + g) + LinkVerticalDistanceFromArticleWeight * u / LinkMaxVerticalDistanceFromArticle; | |
T && (L += LinkURLSemanticMatchBonus), t.parentNode.tagName === "LI" && (L += LinkListItemBonus); | |
var y = t.innerText; | |
return LinkNextMatchRegEx.test(y) && (L += LinkNextMatchBonus), LinkPageMatchRegEx.test(y) && (L += LinkPageMatchBonus), LinkContinueMatchRegEx.test(y) && (L += LinkContinueMatchBonus), L | |
}, | |
elementContainsEnoughTextOfSameStyle: function(t) { | |
function o(e, t) { | |
function u(e) { | |
var t = e.children[0]; | |
if (t) { | |
var n = t.children, r = n.length; | |
for (var i = 0; i < r; ++i) | |
if (getComputedStyle(n[i]).float !== "none") | |
return !1 | |
} | |
return !0 | |
} | |
function a(e, i) { | |
if (e.nodeType === Node.TEXT_NODE) { | |
/\S/.test(e.nodeValue) && r.push(e); | |
return | |
} | |
if (e.nodeType !== Node.ELEMENT_NODE) | |
return; | |
if (!isElementVisible(e)) | |
return; | |
if (t&&++n > t) | |
return; | |
if (e._evaluatedForTextContent) | |
return; | |
var f = e.tagName; | |
if (f === "IFRAME" || f === "FORM") | |
return; | |
o[f] ? i-- : (f === "UL" || f === "OL") && u(e) && i--; | |
var l = i + 1; | |
if (l < s) { | |
var c = e.childNodes, h = c.length; | |
for (var p = 0; p < h; ++p) | |
a(c[p], l) | |
} | |
} | |
var n = 0, r = [], o = { | |
P: 1, | |
STRONG: 1, | |
B: 1, | |
EM: 1, | |
I: 1, | |
SPAN: 1 | |
}; | |
return i && (o.CENTER = 1, o.FONT = 1), a(e, 0), r | |
} | |
const n = 110, r = 1800; | |
var i = t.tagName === "BODY", s = i ? 2: 3, u = o(t, n), a = r / scoreMultiplierForElementTagNameAndAttributes(t) / languageScoreMultiplierForTextNodes(u), f = {}, l = u.length; | |
for (var c = 0; c < l; ++c) { | |
var h = u[c], p = h.length, d = h.parentElement, v = window.getComputedStyle(d), m = v.fontFamily + "|" + v.fontSize, g = Math.pow(p, TextNodeLengthPower); | |
if (f[m]) { | |
if ((f[m] += g) > a) | |
break | |
} else | |
f[m] = g | |
} | |
for (var m in f) | |
if (f[m] > a) | |
return !0; | |
return !1 | |
}, | |
pointsToUseForHitTesting: function() { | |
const t = window.innerWidth, n = t / 4, r = t / 2, i = 128, s = 320; | |
return [[r, 800], [r, 600], [n, 800], [r, 400], [r - i, 1100], [s, 700], [3 * n, 800], [t - s, 700], [r - i, 1300]] | |
}, | |
clearVisualExaminationState: function() { | |
var t = this._elementsEvaluatedForTextContent.length; | |
for (var n = 0; n < t; ++n) | |
delete this._elementsEvaluatedForTextContent[n]._evaluatedForTextContent; | |
this._elementsEvaluatedForTextContent = [] | |
}, | |
findArticleByVisualExamination: function() { | |
this.clearVisualExaminationState(); | |
var t = this.pointsToUseForHitTesting(), n = t.length; | |
for (var r = 0; r < n; r++) { | |
var i = t[r][0], s = t[r][1], o = elementAtPoint(i, s); | |
for (var u = o; u; u = u.parentElement) { | |
if (u._evaluatedForTextContent) | |
break; | |
if (VeryPositiveClassNameRegEx.test(u.className)) | |
return new CandidateElement(u, this.contentDocument); | |
if (CandidateTagNamesToIgnore[u.tagName]) | |
continue; | |
var a = u.offsetWidth, f = u.offsetHeight; | |
if (!a&&!f) { | |
var l = cachedElementBoundingRect(u); | |
a = l.width, f = l.height | |
} | |
if (a < CandidateMinimumWidth || f < CandidateMinimumHeight || a * f < CandidateMinimumArea) | |
continue; | |
var c = this.elementContainsEnoughTextOfSameStyle(u); | |
u._evaluatedForTextContent=!0, this._elementsEvaluatedForTextContent.push(u); | |
if (!c) | |
continue; | |
if (CandidateElement.candidateElementAdjustedHeight(u) < CandidateMinimumHeight) | |
continue; | |
var h = new CandidateElement(u, this.contentDocument); | |
if (h.shouldDisqualifyDueToSimilarElements()) | |
return null; | |
if (h.shouldDisqualifyDueToHorizontalRuleDensity()) | |
return null; | |
if (h.shouldDisqualifyDueToHeaderDensity()) | |
return null; | |
if (h.shouldDisqualifyForDeepLinking()) | |
continue; | |
return h | |
} | |
} | |
return null | |
}, | |
articleTextContent: function() { | |
return this._articleTextContent | |
}, | |
pageDescription: function() { | |
var t = this.contentDocument.querySelectorAll("head meta[name]"), n = t.length; | |
for (var r = 0; r < n; ++r) { | |
var i = t[r]; | |
if (i.getAttribute("name").toLowerCase() === "description") { | |
var s = i.getAttribute("content"); | |
if (s) | |
return s.trim() | |
} | |
} | |
return null | |
}, | |
articleTitleAndSiteNameFromTitleString: function(e) { | |
const t = [" - ", " \u2013 ", " \u2014 ", ": ", " | ", " \u00bb "], n = t.length, r = .6; | |
var i = this.contentDocument.location.host, s = i.replace(/^(www|m)\./, ""), o = s.replace(/\.(com|info|net|org|edu)$/, "").toLowerCase(), u, a; | |
for (var f = 0; f < n; ++f) { | |
var l = e.split(t[f]); | |
if (l.length !== 2) | |
continue; | |
var c = l[0].trim(), h = l[1].trim(), p = c.toLowerCase(), d = h.toLowerCase(), v = Math.max(stringSimilarity(p, s), stringSimilarity(p, o)), m = Math.max(stringSimilarity(d, s), stringSimilarity(d, o)), g = Math.max(v, m); | |
if (!a || g > a) | |
a = g, v > m ? u = { | |
siteName: c, | |
articleTitle: h | |
} : u = { | |
siteName: h, | |
articleTitle: c | |
} | |
} | |
return u && a >= r ? u : null | |
}, | |
readingListItemInformation: function() { | |
const t = 220, n = 220; | |
var r, i = this.pageDescription(), s=!1; | |
this.adoptableArticle() ? (r = this.articleTitle(), i = i || this.articleTextContent(), s=!0) : (r = this.contentDocument.title, this.contentDocument.body && (i = i || this.contentDocument.body.innerText)); | |
var o = "", u = this.mainImageNode(); | |
return u && (o = u.src), r || (r = userVisibleURLString(this.contentDocument.location.href)), r = r.trim().substring(0, t), i || (i = ""), i = i.trim().substring(0, n).replace(/[\s]+/g, " "), { | |
title: r, | |
previewText: i, | |
mainImageURL: o, | |
isReaderAvailable: s | |
} | |
} | |
}; | |
var ReaderArticleFinderJS = new ReaderArticleFinder(document); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment