User:Nardog/Consecudiff.js

(mw.config.get('wgNamespaceNumber') || mw.config.get('wgAction') !== 'view') &&(function consecudiff() {mw.loader.addStyleTag('.consecudiff::before{content:" ["} .consecudiff::after{content:"]"} .consecudiff-top::before{content:" ⟨"} .consecudiff-top::after{content:"⟩"}');let isHist = mw.config.get('wgAction') === 'history';class Consecudiff {constructor(lis, isContribs) {this.isContribs = isContribs;this.isEnhanced = !isHist && !isContribs &&lis[0].classList.contains('mw-enhanced-rc');this.threshold = isContribs ? window.consecudiffContribsThreshold || 120: isHist ? window.consecudiffHistThreshold || 720: window.consecudiffThreshold || 720;this.strictMode = !isContribs &&!!window.consecudiffDetectInterruptions;this.diffSelector = isHist? 'a.mw-history-histlinks-previous': '.mw-changeslist-diff';this.permaSelector = this.isEnhanced && '.mw-enhanced-rc-time > a' ||(isHist || isContribs) && 'a.mw-changeslist-date';this.hybridSelector = this.diffSelector;if (this.permaSelector) {this.hybridSelector += ', ' + this.permaSelector;}this.topClass = isContribs? 'mw-contributions-current': 'mw-changeslist-last';let dependencies = ['mediawiki.util'];if ((isHist || isContribs) && mw.config.get('wgUserLanguage') !== 'en') {dependencies.push('mediawiki.language.months');}mw.loader.using(dependencies, () => {let chunks;if (isHist) {chunks = this.chunkByUser(lis);} else {chunks = [];this.groupByTitle(lis).forEach(group => {chunks.push(...this.chunkByUser(group));});}let subchunks = [];chunks.forEach(chunk => {subchunks.push(...this.divideByDate(chunk));});let linkPairs = [];subchunks.forEach(subchunk => {linkPairs.push(...this.makeLinks(subchunk));});linkPairs.forEach(([$span, parent]) => {$span.appendTo(parent);});});}groupByTitle(lis) {let selector = this.isContribs? '.mw-contributions-title': '.mw-changeslist-title';let lisByTitle = {};lis.forEach(li => {let link = (this.isEnhanced ? li.closest('table') : li).querySelector(selector);if (!link) return;let title = link.textContent;if (!lisByTitle.hasOwnProperty(title)) lisByTitle[title] = [];lisByTitle[title].push(li);});return Object.values(lisByTitle).filter(group => group.length > 1);}chunkByUser(lis) {if (this.isSingleContribs) return [lis];let chunks = [], lastSplitAt = 0, prevUser;this.isSingleContribs = lis.some((li, i) => {let link = li.querySelector('.mw-userlink');if (!link) return this.isContribs;let user = link.textContent;if (i && user !== prevUser) {chunks.push(lis.slice(lastSplitAt, i));lastSplitAt = i;}prevUser = user;});if (this.isSingleContribs) return [lis];chunks.push(lis.slice(lastSplitAt));return chunks.filter(chunk => chunk.length > 1);}divideByDate(lis) {let chunks = [], lastSplitAt = 0, prevDate;lis.forEach((li, i) => {let date;if (isHist || this.isContribs) {date = this.parseDate(li.querySelector('.mw-changeslist-date').textContent);} else {date = Date.parse(li.dataset.mwTs.replace(/(....)(..)(..)(..)(..)(..)/, '$1-$2-$3T$4:$5:$6Z'));}if (date) date = date / 60000;if (i && prevDate - date > this.threshold) {chunks.push(lis.slice(lastSplitAt, i));lastSplitAt = i;}prevDate = date;if (!this.strictMode || lastSplitAt === i) return;let prevDiff = lis[i - 1].querySelector(this.diffSelector);if (prevDiff) {let prevNext = mw.util.getParamValue('oldid', prevDiff.search);if (prevNext !== li.dataset.mwRevid) {chunks.push(lis.slice(lastSplitAt, i));lastSplitAt = i;}}});chunks.push(lis.slice(lastSplitAt));return chunks.filter(chunk => chunk.length > 1);}makeLinks(lis) {let count = lis.length;let firstPerma;let start = lis.findIndex(li => (firstPerma = li.querySelector(this.hybridSelector)));if (start === -1 || count - start < 2) return [];let end, lastDiff;for (let i = count - 1; i > start; i--) {if (!isHist && !this.isContribs) {lastDiff = lis[i].querySelector(this.diffSelector);if (lastDiff ||lis[i].classList.contains('mw-changeslist-src-mw-new')) {end = i + 1;break;}}if (this.permaSelector && lis[i].querySelector(this.permaSelector)) {end = i + 1;break;}}if (!end) return [];count = end - start;let params = { diff: lis[start].dataset.mwRevid };if (lastDiff) {params.oldid = mw.util.getParamValue('oldid', lastDiff.search);} else {params.oldid = lis[end - 1].dataset.mwRevid;if (isHist && lis[end - 1].querySelector(this.diffSelector) ||this.isContribs && !lis[end - 1].querySelector('.newpage')) {params.direction = 'prev';}}let title = !isHist && mw.util.getParamValue('title', firstPerma.search);let url = mw.util.getUrl(title, params);let classes = 'consecudiff';if (!isHist && lis[start].classList.contains(this.topClass)) {classes += ' consecudiff-top';}return lis.slice(start, end).map((li, i) => [$('<span>').addClass(classes).append($('<a>').attr('href', url).text(this.convertNumber(count - i + '/' + count))),this.isEnhanced? li.tagName === 'TR'? li.lastElementChild: li.querySelector('.mw-changeslist-line-inner'): li]);}parseDate(s) {let date = Date.parse(s);if (date) return date;if (s.includes(',')) date = Date.parse(s.replace(',', ''));if (date) return date;if (mw.loader.getState('mediawiki.language.months') !== 'ready') return;s = s.replace(/\D/g, c => {let n = mw.language.convertNumber(c, true);return Number.isNaN(n) ? c : n;});let h, m;s = s.replace(/(\d\d?)[.:h](\d\d?)/, ($0, $1, $2) => {h = $1;m = $2;return ' ';});if (!h) return;let y, dateFirst;s = s.replace(/^(.*?)(\d{4})(?!\d)/, ($0, $1, $2) => {y = $2;dateFirst = /\d/.test($1);return $1 + ' ';});if (!y) return;let mo, d;if (dateFirst) {[d, s] = this.getDate(s);if (!d) return;[mo, s] = this.getMonth(s);if (mo === -1) return;} else {[mo, s] = this.getMonth(s);if (mo === -1) return;[d, s] = this.getDate(s);if (!d) return;}return new Date(y, mo, d, h, m).getTime();}getMonth(s) {if (!this.months) {this.months = mw.language.months.abbrev.concat(mw.language.months.names, mw.language.months.genitive).reverse();}let mo = this.months.findIndex(mn => {let temp = s.replace(mn, ' ');if (temp !== s) {s = temp;return true;}});if (mo === -1) {let [numeric, temp] = this.getDate(s);numeric = parseInt(numeric);if (numeric > 0 && numeric < 13) {mo = numeric - 1;s = temp;}} else {mo = 11 - mo % 12;}return [mo, s];}getDate(s) {let d;s = s.replace(/(^|\D)(\d\d?)(?!\d)/, ($0, $1, $2) => {d = $2;return $1 + ' ';});return [d, s];}convertNumber(num) {try {return mw.language.convertNumber(num);} catch (e) {return num;}}}mw.hook('wikipage.content').add($content => {$content.find('.mw-pager-body').each(function () {let lis = this.querySelectorAll(':scope > .mw-contributions-list > li');if (lis.length > 1) new Consecudiff([...lis], !isHist);});if (isHist) return;let $lists = $content.filter('.mw-changeslist');if (!$lists.length) $lists = $content.find('.mw-changeslist');$lists.each(function () {let lis = this.querySelectorAll('.mw-changeslist-edit:not(.mw-changeslist-src-mw-categorize)[data-mw-revid]');if (lis.length > 1) new Consecudiff([...lis]);});});}());