User:SunAfterRain/js/InPageDiff.js

注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google ChromeFirefoxMicrosoft EdgeSafari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。
// 基於 InPageEdit 的同頁面顯示差異所誕生的項目
$.when(
	$.ready,
	mw.loader.using(['ext.gadget.HanAssist'])
).then((_, require) => {
	const HanAssist = require('ext.gadget.HanAssist');
	const madeKey = 'InPageDiff.modified';
	const madeMap = new WeakMap();
	const windowManager = new OO.ui.WindowManager();
	windowManager.$element.appendTo(document.body);
	function openDiffDialog(diffElemnetRef) {
		return function (ev) {
			ev.preventDefault();
			const diffElemnet = diffElemnetRef.deref();
			if (!diffElemnet) {
				return;
			}
			let diffUrl;
			try {
				diffUrl = new URL(diffElemnet.href);
			} catch {
				// ignore
			}

			const diffLink = diffUrl.href;
			
			diffUrl.searchParams.set('action', 'render');
			const renderDiffLink = diffUrl.href;

			class DiffViewer extends OO.ui.ProcessDialog {
				constructor() {
					super({
						size: 'larger'
					});

					this.$realContent = $('<div>');
				}
	
				initialize() {
					super.initialize();
	
					this.content = new OO.ui.PanelLayout({
						padded: true,
						expanded: false
					});
					this.$realContent.appendTo(this.content.$element);
	
					this.$body.append(this.content.$element);
	
					return this;
				}
	
				fetch() {
					return fetch(renderDiffLink)
						.then(response => response.text())
						.then(renderHtml => {
							const $element = $($.parseHTML(renderHtml)).not('.mw-revslider-container, .mw-diff-revision-history-links, .mw-diff-table-prefix');
							const $diffTable = $element.filter('table.diff');
							const $parserOutput = $element.filter('.mw-parser-output');
							$diffTable.find('#differences-prevlink, #differences-nextlink').remove();
							this.$realContent.get(0).replaceChildren(...$element.get());
							mw.hook('wikipage.diff').fire($diffTable);
							if ($parserOutput.length) {
								mw.hook('wikipage.content').fire($parserOutput);
							}
							this.updateSize();
						})
						.catch(error => {
							console.error(error);
							throw new OO.ui.Error(String(error), { recoverable: false });
						});
				}
				
				fetchWrap() {
					if (!this.fetchPromise) {
						this.fetchPromise = this.fetch();
						delete this.lastError;
	
						const deferred = $.Deferred();
						this.fetchPromise
							.then(deferred.resolve)
							.catch(error => {
								if (error instanceof OO.ui.Error) {
									this.lastError = error;
								} else {
									deferred.reject(error);
								}
							})
							.then(() => {
								delete this.fetchPromise;
							});
						return deferred;
					} else {
						const deferred = $.Deferred();
						this.fetchPromise
							.then(deferred.resolve)
							.catch(error => {
								if (!(error instanceof OO.ui.Error)) {
									deferred.reject(error);
								} else {
									deferred.resolve();
								}
							})
							.then(() => {
								delete this.fetchPromise;
							});
						return deferred;
					}
				}

				getSetupProcess(data) {
					return super.getSetupProcess(data).next(() => {
						this.fetchWrap();
						this.executeAction('main');
					});
				}
	
				getActionProcess(action) {
					return new OO.ui.Process()
						.next(() => {
							if (action === 'main') {
								return this.fetchWrap();
							} else if (action === 'original') {
								window.location.replace(diffLink);
							}
						})
						.next(() => {
							if (action === 'main' && this.lastError) {
								return this.lastError;
							}
	
							return super.getActionProcess(action).execute();
						});
				}
			}
	
			DiffViewer.static = Object.create(OO.ui.ProcessDialog.static);
			DiffViewer.static.name = 'DiffViewer';
			DiffViewer.static.title = HanAssist.conv({ hans: '比較差異', hant: '比較差異' });
			DiffViewer.static.actions = [
				{
					label: mw.msg('ooui-dialog-process-dismiss'),
					flags: ['primary']
				},
				{
					action: 'original',
					label: HanAssist.conv({ hans: '检视原始差异', hant: '檢視原始差異' })
				}
			];
			
			const viewer = new DiffViewer();
			windowManager.addWindows([viewer]);
			viewer.open();
		};
	}
	function initial($content) {
		for (const diffLink of $content.find('a.mw-changeslist-groupdiff, a.mw-changeslist-diff')) {
			if (madeMap.has(diffLink)) {
				return;
			}
			madeMap.set(diffLink, true);
			$(diffLink).on('click', openDiffDialog(new WeakRef(diffLink)));
		}  
	}
	mw.hook('wikipage.content').add(initial);
});