site-metadata-extractor
Version:
web(site) resource metadata extractor
724 lines • 93.9 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/* eslint-disable @typescript-eslint/no-explicit-any */
const isEqual_1 = __importDefault(require("lodash/isEqual"));
const uniq_1 = __importDefault(require("lodash/uniq"));
const url_1 = require("url");
const formatter_1 = __importStar(require("./formatter"));
const cleaner_1 = require("./cleaner");
const stopwords_1 = __importDefault(require("./stopwords"));
function addSiblings(doc, topNode, lang) {
const baselineScoreSiblingsPara = getSiblingsScore(doc, topNode, lang);
const sibs = topNode.prevAll();
sibs.each((_index, element) => {
const currentNode = doc(element);
const ps = getSiblingsContent(doc, lang, currentNode, baselineScoreSiblingsPara);
if (ps) {
ps.forEach((p) => {
topNode.prepend(`<p>${p}</p>`);
});
}
});
return topNode;
}
function biggestTitleChunk(title, splitter) {
let largeTextIndex = 0;
let largeTextLength = 0;
const titlePieces = title.split(splitter);
titlePieces.forEach((piece, index) => {
if (piece.length > largeTextLength) {
largeTextLength = piece.length;
largeTextIndex = index;
}
});
return titlePieces[largeTextIndex];
}
function cleanNull(text) {
if (text) {
return text.replace(/^null$/g, "");
}
return "";
}
function cleanText(text) {
if (text) {
return text
.replace(/[\r\n\t]/g, " ")
.replace(/\s\s+/g, " ")
.replace(/<!--.+?-->/g, "")
.replace(/�/g, "")
.trim();
}
return text;
}
function cleanTitle(title, delimiters) {
let titleText = title || "";
let usedDelimiter = false;
delimiters.forEach((char) => {
if (titleText.indexOf(char) >= 0 && !usedDelimiter) {
titleText = biggestTitleChunk(titleText, char);
usedDelimiter = true;
}
});
return cleanText(titleText);
}
function doesNodeListContainNode(list, node) {
let contains = false;
for (let i = 0; i < list.length; i++) {
const nodeToCompare = list[i];
if ((0, isEqual_1.default)(node, nodeToCompare)) {
contains = true;
}
}
return contains;
}
function getObjectTag(doc, node) {
const srcNode = node.find("param[name=movie]");
if (srcNode.length > 0) {
const src = srcNode.attr("value");
const video = getVideoAttrs(doc, node);
video.src = src;
return video;
}
return {};
}
function getSiblingsContent(doc, lang, currentSibling, baselineScoreSiblingsPara) {
if (currentSibling.get(0).tagName === "p" &&
currentSibling.text().length > 0) {
return [currentSibling];
}
else {
const potentialParagraphs = currentSibling.find("p");
if (potentialParagraphs === null) {
return null;
}
else {
const ps = [];
potentialParagraphs.each((_index, element) => {
const firstParagraph = doc(element);
const text = firstParagraph.text();
if (text.length > 0) {
const wordStats = (0, stopwords_1.default)(text, lang);
const paragraphScore = wordStats.stopWordCount;
const siblingBaselineScore = 0.3;
const highLinkDensity = isHighLinkDensity(doc, firstParagraph);
const score = baselineScoreSiblingsPara * siblingBaselineScore;
if (score < paragraphScore && !highLinkDensity) {
ps.push(text);
}
}
});
return ps;
}
}
}
function getSiblingsScore(doc, topNode, lang) {
const nodesToCheck = topNode.find("p");
let base = 100000;
let paragraphsNumber = 0;
let paragraphScore = 0;
nodesToCheck.each((_index, element) => {
const node = doc(element);
const textNode = node.text();
const wordStats = (0, stopwords_1.default)(textNode, lang);
const highLinkDensity = isHighLinkDensity(doc, node);
if (wordStats.stopWordCount > 2 && !highLinkDensity) {
paragraphsNumber++;
paragraphScore += wordStats.stopWordCount;
}
});
if (paragraphsNumber > 0) {
base = paragraphScore / paragraphsNumber;
}
return base;
}
function getScore(node) {
const gravityScoreString = node.attr("gravityScore");
if (!gravityScoreString) {
return 0;
}
else {
return parseInt(gravityScoreString, 10);
}
}
function getVideoAttrs(doc, node) {
const el = doc(node);
return {
height: el.attr("height"),
src: el.attr("src"),
width: el.attr("width"),
};
}
function isAbsoluteUrl(url) {
if (typeof url !== "string") {
throw new TypeError(`Expected a \`string\`, got \`${typeof url}\``);
}
// Don't match Windows paths `c:\`
if (/^[a-zA-Z]:\\/.test(url)) {
return false;
}
// Scheme: https://tools.ietf.org/html/rfc3986#section-3.1
// Absolute URL: https://tools.ietf.org/html/rfc3986#section-4.3
return /^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(url);
}
function isBoostable(doc, node, lang) {
const minimumStopWordCount = 5;
const maxStepsAwayFromNode = 3;
let stepsAway = 0;
const nodes = node.prevAll();
let boostable = false;
nodes.each((_index, element) => {
const currentNode = doc(element);
const currentNodeTag = currentNode.get(0).tagName;
if (currentNodeTag === "p") {
if (stepsAway >= maxStepsAwayFromNode) {
boostable = false;
return false;
}
const paraText = currentNode.text();
const wordStats = (0, stopwords_1.default)(paraText, lang);
if (wordStats.stopWordCount > minimumStopWordCount) {
boostable = true;
return false;
}
stepsAway++;
}
});
return boostable;
}
function isHighLinkDensity(doc, node) {
const links = node.find("a");
if (links.length > 0) {
const text = node.text();
const words = text.split(" ");
const numberOfWords = words.length;
const sb = [];
links.each((_index, element) => {
sb.push(doc(element).text());
});
const linkText = sb.join(" ");
const linkWords = linkText.split(" ");
const numberOfLinkWords = linkWords.length;
const numberofLinks = links.length;
const percentLinkWords = numberOfLinkWords / numberOfWords;
const score = percentLinkWords * numberofLinks;
if (score >= 1.0) {
return true;
}
}
return false;
}
function isNodeScoreThresholdMet(_doc, node, e) {
const topNodeScore = getScore(node);
const currentNodeScore = getScore(e);
const thresholdScore = topNodeScore * 0.08;
const elIsTdUlOlOrBlockQ = ["td", "ul", "ol", "blockquote"].includes(e.get(0).tagName);
if (currentNodeScore < thresholdScore && !elIsTdUlOlOrBlockQ) {
return false;
}
return true;
}
function isTableAndNoParaExist(doc, e) {
const subParagraphs = e.find("p");
subParagraphs.each((_index, element) => {
const p = doc(element);
const text = p.text();
if (text.length < 25) {
doc(p).remove();
}
});
const subParagraphsTwo = e.find("p");
const elIsTdUlOrOl = ["td", "ul", "ol"].includes(e.get(0).tagName);
if (subParagraphsTwo.length === 0 && !elIsTdUlOrOl) {
return true;
}
return false;
}
function isValidDate(d) {
const parsedDate = Date.parse(d);
return new Date(d).toString() !== "Invalid Date" && !isNaN(parsedDate);
}
function postCleanup(doc, targetNode, lang) {
const node = addSiblings(doc, targetNode, lang);
node.children().each((_index, element) => {
const el = doc(element);
const elTag = el.get(0).tagName;
if (!["p", "a"].includes(elTag)) {
if (isHighLinkDensity(doc, el) ||
isTableAndNoParaExist(doc, el) ||
!isNodeScoreThresholdMet(doc, node, el)) {
doc(el).remove();
}
}
});
return node;
}
function rawTitle(doc) {
let gotTitle = false;
let titleText = "";
[
doc('meta[property="og:title"]').first().attr("content"),
doc('h1[class*="title"]').first().text(),
doc("title").first().text(),
doc("h1").first().text(),
doc("h2").first().text(),
].forEach((candidate) => {
if (candidate && candidate.trim() && !gotTitle) {
titleText = candidate.trim();
gotTitle = true;
}
});
return titleText;
}
function updateNodeCount(node, addToCount) {
const countString = node.attr("gravityNodes");
let currentScore = 0;
if (countString) {
currentScore = parseInt(countString, 10);
}
const newScore = currentScore + addToCount;
node.attr("gravityNodes", `${newScore}`);
}
function updateScore(node, addToScore) {
const scoreString = node.attr("gravityScore");
let currentScore = 0;
if (scoreString) {
currentScore = parseInt(scoreString, 10);
}
const newScore = currentScore + addToScore;
node.attr("gravityScore", `${newScore}`);
}
const extractor = {
author: (doc) => {
const authorCandidates = doc("meta[property='article:author'], meta[property='og:article:author'], meta[name='author'], meta[name='dcterms.creator'], meta[name='DC.creator'], meta[name='DC.Creator'], meta[name='dc.creator'], meta[name='creator']");
const authorList = [];
authorCandidates.each((_index, element) => {
const author = cleanNull(doc(element).attr("content"));
if (author) {
authorList.push(author.trim());
}
});
// fallback to a named author div
if (authorList.length === 0) {
const fallbackAuthor = doc("span[class*='author']").first().text() ||
doc("p[class*='author']").first().text() ||
doc("div[class*='author']").first().text() ||
doc("span[class*='byline']").first().text() ||
doc("p[class*='byline']").first().text() ||
doc("div[class*='byline']").first().text();
if (fallbackAuthor) {
authorList.push(cleanText(fallbackAuthor));
}
}
return authorList;
},
calculateBestNode: (doc, lang) => {
let topNode = null;
const nodesToCheck = doc("p, pre, td");
const parentNodes = [];
const nodesWithText = [];
let startingBoost = 1.0;
let cnt = 0;
let i = 0;
nodesToCheck.each((_index, element) => {
const node = doc(element);
const textNode = node.text();
const wordStats = (0, stopwords_1.default)(textNode, lang);
const highLinkDensity = isHighLinkDensity(doc, node);
if (wordStats.stopWordCount > 2 && !highLinkDensity) {
nodesWithText.push(node);
}
});
const nodesNumber = nodesWithText.length;
const bottomNegativeScoreNodes = nodesNumber * 0.25;
const negativeScoring = 0;
nodesWithText.forEach((node) => {
let boostScore = 0.0;
if (isBoostable(doc, node, lang) === true) {
if (cnt >= 0) {
boostScore = (1.0 / startingBoost) * 50;
startingBoost += 1;
}
}
if (nodesNumber > 15) {
if (nodesNumber - i <= bottomNegativeScoreNodes) {
const booster = bottomNegativeScoreNodes - (nodesNumber - i);
boostScore = -1.0 * Math.pow(booster, 2);
const negScore = Math.abs(boostScore) + negativeScoring;
if (negScore > 40) {
boostScore = 5.0;
}
}
}
const textNode = node.text();
const wordStats = (0, stopwords_1.default)(textNode, lang);
const upScore = Math.floor(wordStats.stopWordCount + boostScore);
const parentNode = node.parent();
updateScore(parentNode, upScore);
updateNodeCount(parentNode, 1);
if (!doesNodeListContainNode(parentNodes, parentNode)) {
parentNodes.push(parentNode);
}
if (parentNodes.indexOf(parentNode) === -1) {
parentNodes.push(parentNode);
}
const parentParentNode = parentNode.parent();
if (parentParentNode) {
updateScore(parentParentNode, upScore / 2);
updateNodeCount(parentParentNode, 1);
if (!doesNodeListContainNode(parentNodes, parentParentNode)) {
parentNodes.push(parentParentNode);
}
if (parentNodes.indexOf(parentParentNode[0]) === -1) {
parentNodes.push(parentParentNode[0]);
}
}
cnt += 1;
i += 1;
});
let topNodeScore = 0;
parentNodes.forEach((el) => {
const score = getScore(doc(el));
if (score > topNodeScore) {
topNode = el;
topNodeScore = score;
}
if (topNode === null) {
topNode = el;
}
});
return doc(topNode);
},
// if it gets to the end without one of these links or meta tags, return the original url as canonical
canonicalLink: (doc, resourceUrl) => {
const canonicalLinkTag = doc("link[rel='canonical'], meta[property='og:url']");
if (canonicalLinkTag) {
const resourceUrlObj = new url_1.URL(resourceUrl);
// check if it is link or meta
if (canonicalLinkTag.get(0) &&
canonicalLinkTag.get(0).tagName === "link") {
const cleanedCanonicalLink = cleanNull(canonicalLinkTag.first().attr("href"));
// check if link is a relative url, if so, append origin
if (!isAbsoluteUrl(cleanedCanonicalLink)) {
return `${resourceUrlObj.origin}${cleanedCanonicalLink}`;
}
return cleanedCanonicalLink;
}
else if (canonicalLinkTag.get(0) &&
canonicalLinkTag.get(0).tagName === "meta") {
let cleanedCanonicalMeta = cleanNull(canonicalLinkTag.attr("content"));
// check if resourceUrl protocol is https? if so, use that
const urlProtocol = resourceUrlObj.protocol;
if (urlProtocol === "https:") {
cleanedCanonicalMeta = cleanedCanonicalMeta.replace(/^http:\/\//i, "https://");
return cleanedCanonicalMeta;
}
return cleanedCanonicalMeta;
}
}
// return original url
return resourceUrl;
},
copyright: (doc) => {
var _a;
const copyrightCandidates = doc("p[class*='copyright'], div[class*='copyright'], span[class*='copyright'], li[class*='copyright'], p[id*='copyright'], div[id*='copyright'], span[id*='copyright'], li[id*='copyright']");
let text = (_a = copyrightCandidates === null || copyrightCandidates === void 0 ? void 0 : copyrightCandidates.first()) === null || _a === void 0 ? void 0 : _a.text();
if (!text) {
// try to find copyright in text
text = doc("body")
.text()
.replace(/\s*[\r\n]+\s*/g, ". ");
}
if (text.indexOf("©") > -1) {
const copyright = text
.replace(/.*?©(\s*copyright)?([^,;:.|\r\n]+).*/gi, "$2")
.trim();
return cleanText(copyright);
}
return "";
},
date: (doc) => {
const dateCandidates = doc("meta[property='article:published_time'], \
meta[itemprop*='datePublished'], meta[name='dcterms.modified'], \
meta[name='dcterms.date'], \
meta[name='DC.date.issued'], meta[name='dc.date.issued'], \
meta[name='dc.date.modified'], meta[name='dc.date.created'], \
meta[name='DC.date'], \
meta[name='DC.Date'], \
meta[name='dc.date'], \
meta[name='date'], \
time[itemprop*='pubDate'], \
time[itemprop*='pubdate'], \
span[itemprop*='datePublished'], \
span[property*='datePublished'], \
p[itemprop*='datePublished'], \
p[property*='datePublished'], \
div[itemprop*='datePublished'], \
div[property*='datePublished'], \
li[itemprop*='datePublished'], \
li[property*='datePublished'], \
time, \
span[class*='date'], \
p[class*='date'], \
div[class*='date']");
let dateToReturn = "";
if (dateCandidates) {
const dateContentCandidate = cleanNull(dateCandidates.first().attr("content"));
const dateTimeCandidate = cleanNull(dateCandidates.first().attr("datetime"));
const dateTextCandidate = cleanText(dateCandidates.first().text());
if (dateContentCandidate) {
dateToReturn = dateContentCandidate.trim();
}
else if (dateTimeCandidate) {
dateToReturn = dateTimeCandidate.trim();
}
else if (dateTextCandidate) {
dateToReturn = dateTextCandidate.trim();
}
}
if (isValidDate(dateToReturn)) {
return dateToReturn;
}
// finally try jsonld date
const jsonldBlob = extractor.jsonld(doc);
if (jsonldBlob && jsonldBlob.datePublished) {
dateToReturn = jsonldBlob.datePublished;
}
return dateToReturn;
},
description: (doc) => {
const descriptionTag = doc("meta[name=description], meta[property='og:description']");
if (descriptionTag) {
const cleanedDescription = cleanNull(descriptionTag.first().attr("content"));
if (cleanedDescription) {
return (0, formatter_1.replaceCharacters)(cleanedDescription.trim(), false, true);
}
}
return "";
},
favicon: (doc, resourceUrlObj) => {
const tag = doc("link").filter((_index, el) => {
var _a, _b;
return ((_a = doc(el).attr("rel")) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === "shortcut icon" ||
((_b = doc(el).attr("rel")) === null || _b === void 0 ? void 0 : _b.toLowerCase()) === "icon";
});
const faviconLink = tag.attr("href") || "";
// ensure the url returned from favicon is absolute url
if (faviconLink && !isAbsoluteUrl(faviconLink)) {
// add the origin to the faviconLink
return `${resourceUrlObj.origin}${faviconLink}`;
}
return faviconLink;
},
image: (doc) => {
const images = doc("meta[property='og:image'], meta[property='og:image:url'], meta[itemprop=image], meta[name='twitter:image:src'], meta[name='twitter:image'], meta[name='twitter:image0']");
if (images.length > 0 && cleanNull(images.first().attr("content"))) {
const cleanedImages = cleanNull(images.first().attr("content")) || "";
return cleanedImages.trim();
}
return "";
},
jsonld: (doc) => {
const jsonldTag = doc('script[type="application/ld+json"]');
if (jsonldTag) {
let jsonldObj = jsonldTag.html() || "{}";
// Sanitize the jsonldObj string to remove extraneous HTML/XML tags
jsonldObj = (0, cleaner_1.sanitizeJsonLdString)(jsonldObj);
try {
const parsedJSON = JSON.parse(jsonldObj);
return parsedJSON;
}
catch (e) {
console.warn(`Error in jsonld parse - ${e}`);
}
}
return null;
},
keywords: (doc) => {
const keywordsTag = doc('meta[name="keywords"]');
if (keywordsTag) {
const cleansedKeywords = cleanNull(keywordsTag.attr("content"));
if (cleansedKeywords) {
return cleansedKeywords.trim();
}
}
return "";
},
lang: (doc) => {
let language = doc("html").attr("lang");
if (!language) {
const tag = doc("meta[name=lang]") || doc("meta[http-equiv=content-language]");
language = tag.attr("content");
}
if (language) {
const value = language[0] + language[1];
const regex = /^[A-Za-z]{2}$/;
if (regex.test(value)) {
return value.toLowerCase();
}
}
return "";
},
links: (doc, topNode, lang) => {
const links = [];
const gatherLinks = () => {
const nodes = topNode.find("a");
nodes.each((_index, element) => {
const href = doc(element).attr("href");
const text = doc(element).html();
if (href && text) {
links.push({
href,
text,
});
}
});
};
if (topNode) {
topNode = postCleanup(doc, topNode, lang);
gatherLinks();
}
return links;
},
locale: (doc) => {
const localeTag = doc("meta[property='og:locale']");
if (localeTag) {
const cleanedLocale = cleanNull(localeTag.first().attr("content"));
if (cleanedLocale) {
return cleanedLocale.trim();
}
}
return "";
},
publisher: (doc) => {
const publisherCandidates = doc("meta[property='og:site_name'], meta[itemprop=name], meta[name='dc.publisher'], meta[name='DC.publisher'], meta[name='DC.Publisher']");
if (publisherCandidates) {
const cleanedPublisher = cleanNull(publisherCandidates.first().attr("content"));
if (cleanedPublisher) {
return cleanedPublisher.trim();
}
}
return "";
},
siteName: (doc) => {
const siteNameTag = doc("meta[property='og:site_name'], meta[itemprop=name]");
if (siteNameTag) {
const cleanedSiteName = cleanNull(siteNameTag.first().attr("content"));
if (cleanedSiteName) {
return cleanedSiteName.trim();
}
}
return "";
},
// Grab the title with soft truncation
softTitle: (doc) => {
const titleText = rawTitle(doc);
return cleanTitle(titleText, ["|", " - ", "»"]);
},
tags: (doc) => {
let elements = doc("a[rel='tag']");
if (elements.length === 0) {
elements = doc("a[href*='/tag/'], a[href*='/tags/'], a[href*='/topic/'], a[href*='?keyword=']");
if (elements.length === 0) {
return [];
}
}
const tags = [];
elements.each((_index, element) => {
const tag = doc(element);
const tagText = tag.text().trim();
tagText.replace(/[\s\t\n]+/g, "");
if (tagText && tagText.length > 0) {
tags.push(tagText);
}
});
return (0, uniq_1.default)(tags);
},
text: (doc, topNode, lang) => {
if (topNode) {
topNode = postCleanup(doc, topNode, lang);
return (0, formatter_1.default)(doc, topNode, lang);
}
else {
return "";
}
},
// Grab the title of an html doc (excluding junk)
// Hard-truncates titles containing colon or spaced dash
title: (doc) => {
const titleText = rawTitle(doc);
const cleanedTitle = cleanTitle(titleText, ["|", " - ", "»", ":"]);
return (0, formatter_1.replaceCharacters)(cleanedTitle, false, true);
},
type: (doc) => {
const typeTag = doc("meta[property='og:type']");
if (typeTag) {
const cleanedType = cleanNull(typeTag.first().attr("content"));
if (cleanedType) {
return cleanedType.trim();
}
}
return "";
},
videos: (doc, topNode) => {
const videolist = [];
const videoCandidates = doc(topNode).find("iframe, embed, object, video");
videoCandidates.each((_index, element) => {
const candidate = doc(element);
const tag = candidate.get(0).tagName;
if (tag === "embed") {
if (candidate.parent() &&
candidate.parent().get(0).tagName === "object") {
videolist.push(getObjectTag(doc, candidate));
}
else {
videolist.push(getVideoAttrs(doc, candidate));
}
}
else if (tag === "object") {
videolist.push(getObjectTag(doc, candidate));
}
else if (tag === "iframe" || tag === "video") {
videolist.push(getVideoAttrs(doc, candidate));
}
});
const urls = [];
const results = [];
videolist.forEach((vid) => {
if (vid.src) {
if (vid && vid.height && vid.width && urls.indexOf(vid.src) === -1) {
results.push(vid);
urls.push(vid.src);
}
}
});
return results;
},
};
exports.default = extractor;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXh0cmFjdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2V4dHJhY3Rvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsdURBQXVEO0FBQ3ZELDZEQUFxQztBQUNyQyx1REFBK0I7QUFFL0IsNkJBQTBCO0FBQzFCLHlEQUEyRDtBQUMzRCx1Q0FBaUQ7QUFDakQsNERBQW9DO0FBeUNwQyxTQUFTLFdBQVcsQ0FDbEIsR0FBaUIsRUFDakIsT0FBd0IsRUFDeEIsSUFBWTtJQUVaLE1BQU0seUJBQXlCLEdBQUcsZ0JBQWdCLENBQUMsR0FBRyxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQztJQUN2RSxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7SUFFL0IsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQWMsRUFBRSxPQUF3QixFQUFFLEVBQUU7UUFDckQsTUFBTSxXQUFXLEdBQUcsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2pDLE1BQU0sRUFBRSxHQUFHLGtCQUFrQixDQUMzQixHQUFHLEVBQ0gsSUFBSSxFQUNKLFdBQVcsRUFDWCx5QkFBeUIsQ0FDMUIsQ0FBQztRQUVGLElBQUksRUFBRSxFQUFFO1lBQ04sRUFBRSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQTJCLEVBQUUsRUFBRTtnQkFDekMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDakMsQ0FBQyxDQUFDLENBQUM7U0FDSjtJQUNILENBQUMsQ0FBQyxDQUFDO0lBRUgsT0FBTyxPQUFPLENBQUM7QUFDakIsQ0FBQztBQUVELFNBQVMsaUJBQWlCLENBQUMsS0FBYSxFQUFFLFFBQWdCO0lBQ3hELElBQUksY0FBYyxHQUFHLENBQUMsQ0FBQztJQUN2QixJQUFJLGVBQWUsR0FBRyxDQUFDLENBQUM7SUFFeEIsTUFBTSxXQUFXLEdBQUcsS0FBSyxD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