Jump to content

User:Nardog/AutoSectionLink.js

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Nardog (talk | contribs) at 14:18, 17 January 2022 (wasn't used). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
['edit', 'submit'].includes(mw.config.get('wgAction')) &&
mw.config.get('wgArticleId') &&
mw.config.get('wgPageContentModel') === 'wikitext' &&
$(function autoSectionLink() {
	let section = $('input[name="wpSection"]').val();
	if (section === 'new') return;
	let $widget = $('#wpSummaryWidget');
	if (!$widget.length) return;
	let isOld = !section && (
		$('input[name="altBaseRevId"]').val() > 0 ||
		$('input[name="baseRevId"]').val() !== $('input[name="editRevId"]').val()
	);
	mw.loader.using([
		'jquery.textSelection', 'mediawiki.util', 'oojs-ui-core',
		'oojs-ui.styles.icons-editing-core'
	], () => {
		let input = OO.ui.infuse($widget);
		let button = new OO.ui.ButtonWidget({
			framed: false,
			icon: 'undo',
			title: 'Restore previous section link'
		}).toggle().on('click', () => {
			let cache = button.getData();
			input.setValue(input.getValue().replace(
				/^(\/\*.*?\*\/)?\s*/,
				cache[0] ? '/* ' + cache[0] + ' */ ' : ''
			));
			updatePreview(cache[0]);
			cache.reverse();
		}).on('toggle', () => {
			input.$element.css('width', `calc(100% - ${button.$element.width()}px)`);
		});
		button.$element.css({ position: 'absolute', top: 0, right: 0, margin: 0 })
			.insertAfter($widget).parent().css('position', 'relative');
		let origLines;
		let update = $diff => {
			let $textarea = $('#wpTextbox1');
			if (!origLines) origLines = $textarea.data('origtext').replace(/\s+$/, '').split('\n');
			let lines = $textarea.textSelection('getContents').replace(/\s+$/, '').split('\n');
			let firstLineNum;
			if (isOld) {
				let i, lastLineNum;
				$diff.find('td:last-child').each(function () {
					if (this.classList.contains('diff-lineno')) {
						i = this.textContent.replace(/\D+/g, '') - 1;
					} else if (this.classList.contains('diff-context')) {
						i++;
					} else if (this.classList.contains('diff-addedline')) {
						i++;
						if (!firstLineNum) firstLineNum = i;
						lastLineNum = i;
					} else if (this.classList.contains('diff-empty')) {
						if (!firstLineNum) firstLineNum = i === 0 ? 1 : i;
						lastLineNum = i;
					}
				});
				lines.length = lastLineNum || 0;
			} else {
				firstLineNum = lines.findIndex((line, i) => line !== origLines[i]) + 1;
				if (!firstLineNum) {
					firstLineNum = lines.length < origLines.length
						? lines.length
						: 1;
				}
				for (let i = 1, x = lines.length, y = origLines.length;
					(section ? i < x : i <= x) && lines[x - i] === origLines[y - i];
					i++
				) {
					lines.pop();
				}
			}
			let re = /^(={1,6})\s*(.+?)\s*\1\s*(?:<!--.+-->\s*)?$/, lowest = 6;
			lines.slice(firstLineNum).forEach(line => {
				let match = line.match(re);
				if (match && match[1].length < lowest) lowest = match[1].length;
			});
			let head;
			lines.slice(0, firstLineNum).reverse().some(line => {
				let match = line.match(re);
				if (match && match[1].length < lowest) {
					head = match[2];
					return true;
				}
			});
			head = head ? head
				.replace(/'''(.+?)'''|\[\[:?(?:[^\|\]]+\|)?([^\]]+)\]\]|<\/?(?:abbr|b|bdi|bdo|big|cite|code|data|del|dfn|em|font|i|ins|kbd|mark|nowiki|q|rb|ref|rp|rt|rtc|ruby|s|samp|small|span|strike|strong|sub|sup|templatestyles|time|tt|u|var)(?:\s[^[^>]*)?>|<!--.*?-->|\[(?:https?:)?\/\/[^\s\[\]]+\s([^\]]+)\]/gi, '$1$2$3')
				.replace(/''(.+?)''/g, '$1')
				.trim() : '';
			let match = input.getValue().match(/^(?:\/\*\s*(.*?)\s*\*\/)?\s*(.*?)$/);
			if (!match[1]) match[1] = '';
			if (match[1] === head) return;
			if (section < 1 && lowest === 6 && !head && match[1] === 'top') return;
			input.setValue((head ? '/* ' + head + ' */ ' : '') + match[2]);
			button.setData([match[1], head]).toggle(true);
			updatePreview(head);
		};
		let updatePreview = head => {
			setTimeout(() => {
				let $preview = $('.mw-summary-preview > .comment > span[dir="auto"]');
				if (!$preview.length) return;
				let url = head && mw.util.getUrl() + '#' + head.replace(/ /g, '_');
				let text = head && (document.dir === 'rtl' ? '←\u200F' : '→\u200E') + head;
				let $ac = $preview.children('.autocomment');
				if ($ac.length && !$ac[0].previousSibling) {
					if (head) {
						$ac.children('a').attr('href', url).text(text);
					} else {
						let node = $ac[0].nextSibling;
						if (node && node.nodeType === Node.TEXT_NODE) {
							node.textContent = node.textContent.replace(/^\s+/, '');
						}
						$ac.remove();
					}
				} else if (head) {
					$('<span>').addClass('autocomment').append(
						$('<a>').attr({
							href: url,
							title: mw.config.get('wgPageName').replace(/_/g, ' ')
						}).text(text),
						mw.messages.exists('colon-separator') ? mw.msg('colon-separator') : ': '
					).prependTo($preview);
				}
			}, 100);
		};
		if (isOld) {
			mw.hook('wikipage.diff').add(update);
		} else {
			$('#wpTextbox1').change(update);
			mw.hook('ext.CodeMirror.switch').add((on, $codeMirror) => {
				if (on) $codeMirror[0].CodeMirror.on('change', mw.util.debounce(500, update));
			});
		}
	});
});