/* var _addText="{{User:Addonian1123/qes}}" */
(function () {
'use strict';
const isMultiEdit = localStorage.getItem('qe_multi_edit') === 'true';
const isEditNoticeEnabled = localStorage.getItem('qe_edit_notice') !== 'false';
const isConfirmCancel = localStorage.getItem('qe_confirm_cancel') === 'true';
const isWarnUnsaved = localStorage.getItem('qe_warn_unsaved') === 'true';
const isDebugEnabled = localStorage.getItem('qeDebug') === 'true' || localStorage.getItem('qeDebug') === '1';
const titleRegexp = new RegExp(
mw.config
.get('wgArticlePath')
.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
.replace(/\\\$1/, '([^?]+)') + '|[?&]title=([^&#]*)'
);
const summaryPresetsCache = {};
let apiSingleton;
let activeCleanupFn = null;
function getApi() {
if (!apiSingleton) {
apiSingleton = new mw.Api();
}
return apiSingleton;
}
function api(func, params, silentError) {
const client = getApi();
$.extend(params, {
errorformat: 'html',
errorlang: mw.config.get('wgUserLanguage'),
errorsuselocal: true
});
return client[func](params).fail(function (_, data) {
if (!silentError) {
mw.notify(client.getErrorMessage(data), {
type: 'error',
tag: 'qe'
});
}
});
}
function qeLog() {
if (!isDebugEnabled) return;
try {
console.log.apply(console, ['[QuickEditSandbox]'].concat([].slice.call(arguments)));
} catch (_e) {}
}
function tryThreeWayMerge(baseText, theirText, myText) {
if (baseText === theirText) return { success: true, text: myText };
if (baseText === myText) return { success: true, text: theirText };
if (theirText === myText) return { success: true, text: myText };
const baseLines = baseText.split('\n');
const theirLines = theirText.split('\n');
const myLines = myText.split('\n');
if (theirLines.length >= baseLines.length && myLines.length >= baseLines.length) {
const theirPrefixMatch = baseLines.every((l, idx) => l === theirLines[idx]);
const myPrefixMatch = baseLines.every((l, idx) => l === myLines[idx]);
if (theirPrefixMatch && myPrefixMatch) {
const merged = baseLines.concat(theirLines.slice(baseLines.length)).concat(myLines.slice(baseLines.length));
return { success: true, text: merged.join('\n') };
}
}
return { success: false };
}
function getPageInfo(title, sectionID, customRevId) {
qeLog('getPageInfo:request', { title, sectionID, customRevId });
const viewedRevId = customRevId || (
(title === mw.config.get('wgPageName') && mw.config.get('wgRevisionId') !== mw.config.get('wgCurRevisionId') && mw.config.get('wgRevisionId') > 0)
? mw.config.get('wgRevisionId')
: null
);
const params = {
action: 'query',
curtimestamp: 1,
prop: 'revisions|info',
indexpageids: 1,
rvprop: ['timestamp', 'content', 'ids'],
rvslots: 'main'
};
if (viewedRevId) {
params.revids = viewedRevId;
} else {
params.titles = title;
}
if (sectionID !== null && sectionID !== undefined && sectionID !== '') {
params.rvsection = sectionID;
}
return api('get', params).then(function (res) {
const pageId = res && res.query && res.query.pageids && res.query.pageids[0];
const page = pageId && res.query.pages && res.query.pages[pageId];
const rev = page && page.revisions && page.revisions[0];
const exists = !!(page && !page.missing && page.revisions && page.revisions.length);
const full = rev && rev.slots && rev.slots.main ? rev.slots.main['*'] : '';
const base = (rev && rev.timestamp) || res.curtimestamp;
const contentModel = (page && page.contentmodel) || 'wikitext';
const isOldRev = !!(viewedRevId && rev && rev.revid && rev.revid !== mw.config.get('wgCurRevisionId'));
return {
start: res.curtimestamp,
base: base,
full: full,
exists: exists,
contentModel: contentModel,
isOldRev: isOldRev,
revId: rev ? rev.revid : null,
serverLatestRevId: page ? (page.lastrevid || (rev ? rev.revid : null)) : null
};
});
}
function formatLocalSummary(summaryText) {
if (!summaryText.trim()) return '';
let rest = summaryText;
let prefixHtml = '';
const secMatch = rest.match(/^\/\*\s*(.*?)\s*\*\/\s*/);
if (secMatch) {
const secTitle = secMatch[1];
const anchor = encodeURIComponent(secTitle.replace(/ /g, '_')).replace(/%/g, '.');
prefixHtml = '<span class="autocomment">→<a href="#' + mw.html.escape(anchor) + '"><bdi dir="ltr">' + mw.html.escape(secTitle) + '</bdi></a>:</span> ';
rest = rest.slice(secMatch[0].length);
}
const linkRegex = /\[\[([^|\]\n]+)(?:\|([^\]\n]+))?\]\]/g;
let result = '';
let lastIndex = 0;
let match;
while ((match = linkRegex.exec(rest)) !== null) {
result += mw.html.escape(rest.slice(lastIndex, match.index));
const target = match[1].trim();
const label = (match[2] || target).trim();
result += '<a href="' + mw.html.escape(mw.util.getUrl(target)) + '">' + mw.html.escape(label) + '</a>';
lastIndex = linkRegex.lastIndex;
}
result += mw.html.escape(rest.slice(lastIndex));
return prefixHtml + result;
}
function showCompareDiff(targetContainer, title, from, to) {
mw.loader.load('mediawiki.diff.styles');
const isNarrow = $(window).width() <= 768;
const compareParams = {
action: 'compare',
fromslots: 'main',
'fromtext-main': from,
fromtitle: title,
frompst: 'true',
toslots: 'main',
'totext-main': to,
totitle: title,
topst: 'true'
};
if (isNarrow) {
compareParams.difftype = 'inline';
}
return api('post', compareParams).then(function (r) {
if (r && r.compare && r.compare['*']) {
const $table = $('<table>')
.addClass('diff')
.append(
$('<colgroup>').append(
$('<col>').addClass('diff-marker'),
$('<col>').addClass('diff-content'),
$('<col>').addClass('diff-marker'),
$('<col>').addClass('diff-content')
)
)
.append(r.compare['*']);
targetContainer.empty().append($table);
} else {
targetContainer.empty().append($('<div>').addClass('qe-diff-empty-notice').text(mw.msg('qe-diff-empty')));
}
});
}
function extractSectionHeader(text) {
const match = text.match(/^(=+)(.+)\1\s*(?:\n|$)/);
return match ? match[2].trim() : '';
}
function resolveLanguageMode(req, contentModel) {
const isWikitext = (contentModel === 'wikitext');
if (isWikitext) {
const { mediawiki } = req('ext.CodeMirror.mode.mediawiki');
return { modeName: 'mediawiki', langSupport: mediawiki() };
}
const modes = req('ext.CodeMirror.modes');
let fn = null;
let mName = 'javascript';
if (contentModel === 'javascript' || contentModel === 'js') {
fn = modes.javascript;
mName = 'javascript';
} else if (contentModel === 'css' || contentModel === 'sanitized-css') {
fn = modes.css;
mName = 'css';
} else if (contentModel === 'json' || contentModel === 'jsonc') {
fn = modes.json || modes.jsonc;
mName = 'json';
} else if (contentModel === 'Scribunto' || contentModel === 'lua') {
fn = modes.lua;
mName = 'lua';
} else if (modes.html && contentModel === 'html') {
fn = modes.html;
mName = 'html';
} else if (typeof modes.javascript === 'function') {
fn = modes.javascript;
mName = 'javascript';
}
return { modeName: mName, langSupport: typeof fn === 'function' ? fn() : null };
}
function getRequiredModules(isMobile, isWikitext) {
if (!isMobile) {
return isWikitext
? ['ext.wikiEditor', 'ext.CodeMirror.WikiEditor', 'ext.CodeMirror.mode.mediawiki']
: ['ext.wikiEditor', 'ext.CodeMirror.WikiEditor', 'ext.CodeMirror.modes'];
}
return isWikitext
? ['ext.CodeMirror', 'ext.CodeMirror.mode.mediawiki']
: ['ext.CodeMirror', 'ext.CodeMirror.modes'];
}
function getSummaryPresetsHtml() {
const lang = mw.config.get('wgUserLanguage') || 'default';
if (!summaryPresetsCache[lang]) {
summaryPresetsCache[lang] = api('get', {
action: 'parse',
text: '{{int:summary}}',
prop: 'text',
disablelimitreport: true
}, true).then(function (parseRes) {
if (parseRes && parseRes.parse && parseRes.parse.text && parseRes.parse.text['*']) {
return parseRes.parse.text['*'];
}
return Promise.reject();
}).catch(function (err) {
delete summaryPresetsCache[lang];
return Promise.reject(err);
});
}
return summaryPresetsCache[lang];
}
function buildErrorBox(htmlSnippet) {
const errorNotice = new OO.ui.MessageWidget({
type: 'error',
inline: false,
label: new OO.ui.HtmlSnippet(htmlSnippet)
});
return $('<div>').addClass('qe-server-error-container').append(errorNotice.$element);
}
function buildServerErrorNotice(code, data) {
let rawHtml = '';
let isAlreadyHtml = false;
const client = getApi();
if (data && data.errors && data.errors.length) {
const allHaveHtml = data.errors.every(function (e) {
return !!(e.html || e['*']);
});
if (allHaveHtml) {
isAlreadyHtml = true;
rawHtml = data.errors.map(function (e) {
return e.html || e['*'];
}).join('<hr>');
} else {
rawHtml = data.errors.map(function (e) {
return e.html || e['*'] || e.message || (e.code && mw.message(e.code).exists() ? mw.message(e.code).text() : e.code) || '';
}).filter(Boolean).join('\n');
}
} else if (data && data.error) {
if (data.error.html || data.error['*']) {
isAlreadyHtml = true;
rawHtml = data.error.html || data.error['*'];
} else {
rawHtml = data.error.info || (data.error.code && mw.message(data.error.code).exists() ? mw.message(data.error.code).text() : data.error.code) || '';
}
}
if (!rawHtml && data && typeof client.getErrorMessage === 'function') {
try {
const $apiMsg = client.getErrorMessage(data);
if ($apiMsg && $apiMsg.length) {
rawHtml = $('<div>').append($apiMsg.clone()).html();
isAlreadyHtml = true;
}
} catch (_e) {}
}
if (!rawHtml && typeof code === 'string' && mw.message(code).exists()) {
rawHtml = mw.message(code).text();
}
if (!rawHtml) {
rawHtml = (typeof code === 'string') ? code : mw.msg('unknown-error');
}
const containsWikitext = !isAlreadyHtml && /\[\[|\{\{|'''/.test(rawHtml);
const renderPromise = containsWikitext
? api('get', {
action: 'parse',
text: rawHtml,
prop: 'text',
disablelimitreport: true
}, true).then(function (pRes) {
return (pRes && pRes.parse && pRes.parse.text && pRes.parse.text['*']) || mw.html.escape(rawHtml).replace(/\n/g, '<br>');
}).catch(function () {
return mw.html.escape(rawHtml).replace(/\n/g, '<br>');
})
: Promise.resolve(isAlreadyHtml ? rawHtml : mw.html.escape(rawHtml).replace(/\n/g, '<br>'));
return renderPromise.then(buildErrorBox);
}
function updatePageContentDom(contentText, contentModel, parsedHtml) {
if (contentModel === 'wikitext') {
let $directParserOutput = contentText.children('.mw-parser-output.mw-content-ltr, .mw-parser-output.mw-content-rtl');
if (!$directParserOutput.length) {
$directParserOutput = contentText.children('.mw-parser-output');
}
if ($directParserOutput.length) {
$directParserOutput.first().replaceWith(parsedHtml);
$directParserOutput.slice(1).remove();
} else {
contentText.html(parsedHtml);
}
return;
}
const $directCode = contentText.children('.mw-highlight, pre.mw-code, pre.mw-css, pre.mw-js, table.mw-json, pre');
if ($directCode.length) {
$directCode.first().replaceWith(parsedHtml);
$directCode.slice(1).remove();
return;
}
if (/json/i.test(contentModel)) {
const $jsonOut = contentText.children('.mw-parser-output').filter(function () {
return $(this).find('.mw-json, pre, .mw-highlight').length > 0;
});
if ($jsonOut.length) {
$jsonOut.first().replaceWith(parsedHtml);
$jsonOut.slice(1).remove();
return;
}
}
const $nestedCode = contentText.find('.mw-highlight, pre.mw-code, pre.mw-css, pre.mw-js, table.mw-json').filter(function () {
return $(this).closest('#mw-clearyourcache, .mw-warning-with-logexcerpt, .mw-editsection, .mw-parser-output').length === 0;
});
if ($nestedCode.length) {
const $firstWrapper = $nestedCode.first().parentsUntil(contentText).last();
const $target = $firstWrapper.length ? $firstWrapper : $nestedCode.first();
$target.replaceWith(parsedHtml);
$nestedCode.slice(1).each(function () {
const $w = $(this).parentsUntil(contentText).last();
($w.length ? $w : $(this)).remove();
});
return;
}
const $directOut = contentText.children('.mw-parser-output');
if ($directOut.length && /json/i.test(contentModel)) {
$directOut.first().replaceWith(parsedHtml);
$directOut.slice(1).remove();
return;
}
const $clearCache = contentText.children('#mw-clearyourcache');
if ($clearCache.length) {
$clearCache.last().after(parsedHtml);
} else {
contentText.html(parsedHtml);
}
}
function reloadPageCleanly() {
try {
const reloadUrl = new URL(location.href);
if (reloadUrl.searchParams.has('redlink') || reloadUrl.searchParams.get('action') === 'edit') {
reloadUrl.searchParams.delete('redlink');
reloadUrl.searchParams.delete('action');
location.href = reloadUrl.toString();
return;
}
} catch (_e) {}
location.reload();
}
async function showEditor($element, customTitle, customSectionID) {
const isMobile = mw.config.get('skin') === 'minerva' || window.innerWidth <= 768;
let title = customTitle;
let sectionID = customSectionID;
const isTriggerLink = !!($element && $element.length && !$element.is('#mw-content-text'));
const heading = isTriggerLink ? $element.parents(':header, .mw-heading').last() : $();
let matcher;
let inserter;
if (heading.length) {
matcher = heading.nextUntil.bind(heading);
inserter = heading.after.bind(heading);
const targetEl = $element.siblings('.qe-target').last();
const href = (targetEl && targetEl.attr && targetEl.attr('href')) || '';
const titleMatch = (href && href.match && href.match(titleRegexp)) || [];
const fallbackTitle = mw.config.get('wgPageName');
if (!title) title = decodeURIComponent(titleMatch[1] || titleMatch[2] || fallbackTitle);
if (sectionID === undefined) {
const sectionMatch = /[?&]v?e?section=(T?-?\d+)/.exec(href);
sectionID = sectionMatch ? sectionMatch[1] : null;
}
} else {
const $articleContent = ($element && $element.length && $element.is('#mw-content-text')) ? $element : $('#mw-content-text');
if (!title) title = mw.config.get('wgPageName');
if (sectionID === undefined) sectionID = null;
matcher = function (selector) { return $articleContent.find(selector); };
inserter = function ($el) { $articleContent.prepend($el); };
}
if (!isMultiEdit) {
if (typeof activeCleanupFn === 'function') {
activeCleanupFn(true);
activeCleanupFn = null;
}
$('.qe-hide').removeClass('qe-hide');
$('.qe-heading').removeClass('qe-heading');
$('#qe-editor').remove();
}
let editor;
let isAborted = false;
const progress = new OO.ui.ProgressBarWidget();
progress.$element.addClass('qe-progress-bar');
if (isTriggerLink) $element.addClass('qe-loading');
const abortLoading = function () {
if (isAborted) return;
isAborted = true;
if (isTriggerLink) $element.removeClass('qe-loading');
progress.$element.remove();
if (editor) editor.remove();
if (isMobile && !$('#qe-editor.qe-mobile-fullscreen').length) {
$('html, body').removeClass('qe-mobile-lock');
}
if (activeCleanupFn === abortLoading) {
activeCleanupFn = null;
}
};
if (!isMultiEdit) {
activeCleanupFn = abortLoading;
}
if (isMobile) {
$('html, body').addClass('qe-mobile-lock');
const $loadingBox = $('<div>').addClass('qe-mobile-loading-box').append(
progress.$element,
new OO.ui.ButtonWidget({ label: mw.msg('cancel'), flags: ['destructive'], framed: false })
.on('click', abortLoading).$element
);
editor = $('<div id="qe-editor" class="qe-mobile-fullscreen qe-loading">').append($loadingBox);
$(document.body).append(editor);
} else {
inserter(progress.$element);
}
const pageInfoPromise = getPageInfo(title, sectionID);
const messagesPromise = getApi().loadMessagesIfMissing([
'showpreview', 'showdiff', 'cancel', 'minoredit', 'summary-preview', 'unknown-error'
]);
let guessedIsWikitext;
if (title === mw.config.get('wgPageName') && mw.config.get('wgPageContentModel')) {
guessedIsWikitext = (mw.config.get('wgPageContentModel') === 'wikitext');
} else {
guessedIsWikitext = !/\.(js|css|json)$/i.test(title) && !/^(Module|模組|模块):/i.test(title);
}
const modulesToPreload = getRequiredModules(isMobile, guessedIsWikitext);
const editorModulesPromise = mw.loader.using(modulesToPreload).catch(function (e) {
qeLog(mw.msg('qe-error-load-modules'), e);
return null;
});
Promise.all([pageInfoPromise, messagesPromise, editorModulesPromise]).then(async function ([r, , preloadedReq]) {
if (isAborted) return;
let start = r.start;
let base = r.base;
let initialServerLatestRevId = r.serverLatestRevId;
const full = r.full;
const contentModel = r.contentModel;
const isNewPage = !r.exists;
let saving = false;
let isDestroyed = false;
let expanded = (sectionID === null);
let previewRequestSeq = 0;
let scrollRafId = 0;
let scrollTimer1 = 0;
let scrollTimer2 = 0;
let cmInputAttached = false;
const remainderStart = (sectionID !== null && sectionID !== undefined && sectionID !== '') ? full.match(/\n=+.+=+(?:\n|$)/) : null;
const part = isNewPage ? '' : remainderStart ? full.substring(0, remainderStart.index) : full;
const remainder = isNewPage ? '' : remainderStart ? full.substring(remainderStart.index) : '';
let level = 0;
let cmInstance = null;
const actualIsWikitext = (contentModel === 'wikitext');
let modulesRequire = preloadedReq;
if (actualIsWikitext !== guessedIsWikitext || !modulesRequire) {
const actualModules = getRequiredModules(isMobile, actualIsWikitext);
modulesRequire = await mw.loader.using(actualModules).catch(function (e) {
qeLog(mw.msg('qe-error-load-modules'), e);
return null;
});
}
if (isAborted) return;
full.replace(/^(=+).+?(=+)(?:\n|$)/, function (m, a, b) {
level = Math.min(a.length, b.length);
return m;
});
let levelMatch = 'h1:has(*), .mw-heading1';
for (let i = 2; i <= level; i++) levelMatch += ', h' + i + ':has(*), .mw-heading' + i;
const partSection = heading.length ? matcher(':header:has(*), .mw-heading') : $();
const fullSection = heading.length ? matcher(levelMatch) : $();
const textarea = new OO.ui.MultilineTextInputWidget({
rows: isMobile ? 12 : 8,
maxRows: isMobile ? 25 : 35,
autosize: false,
value: part
});
textarea.$element.css({ 'width': '100%', 'max-width': '100%' });
function getEditorText() {
if (typeof $(textarea.$input).textSelection === 'function') {
const val = $(textarea.$input).textSelection('getContents');
if (val !== undefined && val !== null) return val;
}
if (cmInstance && cmInstance.view && cmInstance.view.state && cmInstance.view.state.doc) {
return cmInstance.view.state.doc.toString();
}
return textarea.getValue();
}
function getFirstLine() {
if (cmInstance && cmInstance.view && cmInstance.view.state && cmInstance.view.state.doc) {
return cmInstance.view.state.doc.line(1).text;
}
const val = getEditorText();
const nl = val.indexOf('\n');
return nl === -1 ? val : val.slice(0, nl);
}
function setEditorText(val) {
if (typeof $(textarea.$input).textSelection === 'function') {
$(textarea.$input).textSelection('setContents', val);
} else {
textarea.setValue(val);
}
}
function isDirty() {
return getEditorText() !== (expanded ? full : part);
}
let currentSectionHeader = extractSectionHeader(part);
const summary = new OO.ui.TextInputWidget({
value: (isNewPage || sectionID === null || !currentSectionHeader) ? '' : '/* ' + currentSectionHeader + ' */ '
});
const mobileTopSummary = new OO.ui.TextInputWidget({
placeholder: mw.msg('qe-summary-placeholder'),
value: summary.getValue()
});
let presetItems = [];
function updatePresetSelectionStates() {
const curSummary = summary.getValue();
for (let i = 0; i < presetItems.length; i++) {
presetItems[i].$el.toggleClass('qe-summary-selected', presetItems[i].regex.test(curSummary));
}
}
summary.on('change', function (val) {
if (mobileTopSummary.getValue() !== val) mobileTopSummary.setValue(val);
updatePresetSelectionStates();
});
mobileTopSummary.on('change', function (val) {
if (summary.getValue() !== val) summary.setValue(val);
});
function checkAndUpdateSectionHeader() {
if (isDestroyed || sectionID === null) return;
const newHeader = extractSectionHeader(getFirstLine());
if (newHeader && newHeader !== currentSectionHeader) {
const curSummary = summary.getValue();
if (/^\/\*\s*.*?\s*\*\//.test(curSummary)) {
summary.setValue(curSummary.replace(/^\/\*\s*.*?\s*\*\//, '/* ' + newHeader + ' */'));
} else {
summary.setValue('/* ' + newHeader + ' */ ' + curSummary.trim());
}
currentSectionHeader = newHeader;
}
}
if (sectionID !== null) {
textarea.$input.on('input', checkAndUpdateSectionHeader);
textarea.on('change', checkAndUpdateSectionHeader);
}
function beforeUnloadHandler(e) {
if (!isDestroyed && isWarnUnsaved && isDirty()) {
e.preventDefault();
e.returnValue = '';
return '';
}
}
if (isWarnUnsaved) {
window.addEventListener('beforeunload', beforeUnloadHandler);
}
const isDefaultMinor = localStorage.getItem('qe_default_minor') === 'true';
const isUserMinor = mw.user.options.get('minoredit') === 1 || mw.user.options.get('minoredit') === '1';
const minor = new OO.ui.CheckboxInputWidget({
accessKey: 'i',
selected: isDefaultMinor || isUserMinor
});
const save = new OO.ui.ButtonInputWidget({
label: mw.msg('qe-save'),
flags: ['primary', 'progressive'],
accessKey: 's'
});
const preview = new OO.ui.ButtonInputWidget({
label: mw.msg('showpreview')
});
const compare = new OO.ui.ButtonInputWidget({
label: mw.msg('showdiff')
});
const cancel = new OO.ui.ButtonInputWidget({
label: mw.msg('cancel'),
title: mw.msg('qe-btn-cancel-title'),
flags: ['destructive']
});
const more = new OO.ui.ButtonInputWidget({
label: '+',
title: mw.msg('qe-btn-edit-all-section')
});
const buttons = new OO.ui.HorizontalLayout({
items: [save, preview, compare, cancel]
});
if (!isNewPage && part !== full && sectionID !== null) {
buttons.addItems([more], 3);
}
if (partSection.length) partSection.addClass('qe-hide');
if (heading.length) heading.addClass('qe-heading');
if (isTriggerLink) $element.removeClass('qe-loading');
progress.$element.remove();
textarea.$input.addClass('qe-textarea');
function blurAll() {
if (document.activeElement && typeof document.activeElement.blur === 'function') {
document.activeElement.blur();
}
if (textarea && textarea.$input) {
textarea.$input.blur();
}
if (cmInstance && cmInstance.view && cmInstance.view.contentDOM) {
cmInstance.view.contentDOM.blur();
}
}
function closeEditor(isSuccess, silent) {
if (isDestroyed) return;
isDestroyed = true;
previewRequestSeq++;
if (scrollRafId) cancelAnimationFrame(scrollRafId);
if (scrollTimer1) clearTimeout(scrollTimer1);
if (scrollTimer2) clearTimeout(scrollTimer2);
blurAll();
if (isWarnUnsaved) {
window.removeEventListener('beforeunload', beforeUnloadHandler);
}
if (cmInputAttached && cmInstance && cmInstance.view && cmInstance.view.dom) {
try {
cmInstance.view.dom.removeEventListener('input', checkAndUpdateSectionHeader);
} catch (_e) {}
cmInputAttached = false;
}
if (cmInstance) {
if (typeof cmInstance.destroy === 'function') {
try { cmInstance.destroy(); } catch (_e) {}
}
cmInstance = null;
}
if (typeof textarea.$input.wikiEditor === 'function') {
try { textarea.$input.wikiEditor('destroy'); } catch (_e) {}
}
if (editor) {
editor.remove();
editor = null;
}
if (isMobile && !$('#qe-editor.qe-mobile-fullscreen').length) {
$('html, body').removeClass('qe-mobile-lock');
}
if (isTriggerLink) $element.removeClass('qe-loading');
if (heading.length) heading.removeClass('qe-heading');
if (partSection.length) partSection.removeClass('qe-hide');
if (fullSection.length) fullSection.removeClass('qe-hide');
if (activeCleanupFn === cleanupRef) {
activeCleanupFn = null;
}
if (window.qeIntegrations && typeof window.qeIntegrations.onEditorClose === 'function') {
try { window.qeIntegrations.onEditorClose(); } catch (_e) {}
}
if (!silent && isEditNoticeEnabled) {
mw.notify(isSuccess ? mw.msg('qe-save-notice') : mw.msg('qe-cancel-notice'), {
type: isSuccess ? 'success' : 'warn',
tag: 'qe-status'
});
}
}
const cleanupRef = function (silent) {
closeEditor(false, silent);
};
if (!isMultiEdit) {
activeCleanupFn = cleanupRef;
}
summary.on('enter', function () {
if (!saving) save.emit('click');
});
mobileTopSummary.on('enter', function () {
if (saving) return;
if (isMobile) switchMobileView('edit');
save.emit('click');
});
function checkLatestServerRevision() {
return api('get', {
action: 'query',
curtimestamp: 1,
prop: 'info',
indexpageids: 1,
titles: title
}, true).then(function (res) {
const pageId = res && res.query && res.query.pageids && res.query.pageids[0];
const page = pageId && res.query.pages && res.query.pages[pageId];
const currentLatest = page ? page.lastrevid : null;
if (initialServerLatestRevId && currentLatest && currentLatest > initialServerLatestRevId) {
return { hasConflict: true, currentLatest: currentLatest };
}
return { hasConflict: false };
}).catch(function () {
return { hasConflict: false };
});
}
function handleEditConflict(myFullText) {
previewRequestSeq++;
return getPageInfo(title, sectionID).then(function (rLive) {
if (isDestroyed) return;
const theirText = rLive.full;
const autoMerge = tryThreeWayMerge(full, theirText, myFullText);
if (autoMerge.success) {
mw.notify(mw.msg('qe-conflict-automerged'), { type: 'warn' });
setEditorText(autoMerge.text);
base = rLive.base;
start = rLive.start;
initialServerLatestRevId = rLive.serverLatestRevId;
expanded = true;
if (fullSection.length) fullSection.addClass('qe-hide');
more.setDisabled(true);
return;
}
const conflictNotice = new OO.ui.MessageWidget({
type: 'error',
label: $('<div>')
.append($('<strong>').text(mw.msg('qe-conflict-title')))
.append($('<p>').text(mw.msg('qe-conflict-explain')))
});
const btnMergeInEditor = new OO.ui.ButtonWidget({
label: mw.msg('qe-conflict-btn-mark-editor'),
flags: ['primary', 'progressive']
});
const btnOverwrite = new OO.ui.ButtonWidget({
label: mw.msg('qe-conflict-btn-overwrite'),
flags: ['destructive']
});
const btnReload = new OO.ui.ButtonWidget({
label: mw.msg('qe-conflict-btn-reload')
});
const conflictToolbar = new OO.ui.HorizontalLayout({
items: [btnMergeInEditor, btnOverwrite, btnReload]
});
const $diffBox = $('<div>').css({ 'margin': '10px 0', 'max-height': '260px', 'overflow-y': 'auto' });
showCompareDiff($diffBox, title, theirText, myFullText);
const $conflictBlock = $('<div>')
.addClass('qe-conflict-box')
.append(conflictNotice.$element, conflictToolbar.$element.css({ 'margin': '8px 0' }), $diffBox);
btnMergeInEditor.on('click', function () {
const conflictMarked =
'<<<<<<< ' + mw.msg('qe-conflict-tab-your') + '\n' +
myFullText + '\n' +
'=======\n' +
theirText + '\n' +
'>>>>>>> ' + mw.msg('qe-conflict-tab-their');
setEditorText(conflictMarked);
base = rLive.base;
start = rLive.start;
initialServerLatestRevId = rLive.serverLatestRevId;
expanded = true;
if (fullSection.length) fullSection.addClass('qe-hide');
more.setDisabled(true);
$conflictBlock.remove();
if (isMobile) switchMobileView('edit');
});
btnOverwrite.on('click', function () {
base = rLive.base;
start = rLive.start;
initialServerLatestRevId = rLive.serverLatestRevId;
expanded = true;
if (fullSection.length) fullSection.addClass('qe-hide');
more.setDisabled(true);
$conflictBlock.remove();
if (isMobile) switchMobileView('edit');
save.emit('click');
});
btnReload.on('click', function () {
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(myFullText);
mw.notify(mw.msg('qe-conflict-copied-backup'), { type: 'success' });
}
setEditorText(theirText);
base = rLive.base;
start = rLive.start;
initialServerLatestRevId = rLive.serverLatestRevId;
expanded = true;
if (fullSection.length) fullSection.addClass('qe-hide');
more.setDisabled(true);
$conflictBlock.remove();
if (isMobile) switchMobileView('edit');
});
if (isMobile) {
switchMobileView('conflict', $conflictBlock);
} else if (editor) {
editor.children('.qe-editor-block').prepend($conflictBlock);
}
});
}
let $mobileViewPanel = null;
let $mobileViewContent = null;
let $mobileEditorMain = null;
let $mobileTopSaveBtn = null;
function switchMobileView(viewMode, $customContent) {
if (!isMobile || !$mobileViewPanel || !$mobileViewContent || isDestroyed) return;
if (viewMode === 'edit') {
$mobileViewPanel.addClass('qe-hide');
$mobileViewContent.empty();
$mobileEditorMain.removeClass('qe-hide');
editOptions.removeClass('qe-hide');
if (cmInstance && cmInstance.view && typeof cmInstance.view.requestMeasure === 'function') {
cmInstance.view.requestMeasure();
}
} else {
const hideTopSave = (viewMode === 'conflict');
mobileTopSummary.$element.toggleClass('qe-hide', hideTopSave);
if ($mobileTopSaveBtn) $mobileTopSaveBtn.toggleClass('qe-hide', hideTopSave);
$mobileEditorMain.addClass('qe-hide');
editOptions.addClass('qe-hide');
$mobileViewContent.empty().append($customContent);
$mobileViewPanel.removeClass('qe-hide');
}
}
function showServerErrorDialog(code, data) {
previewRequestSeq++;
buildServerErrorNotice(code, data).then(function ($errorContainer) {
if (isDestroyed || !editor || !editor[0] || !editor[0].isConnected) return;
if (isMobile) {
switchMobileView('error', $errorContainer);
mw.hook('wikipage.content').fire($errorContainer);
} else {
editor.children('.preview').remove();
const $preview = $('<div>')
.addClass('qe-border-color-base qe-preview-block preview')
.append(
$('<div>').css('margin-bottom', '8px').append(
$('<strong>').css('color', '#d33').text(mw.msg('qe-error-publish-title'))
),
$errorContainer
);
$preview.appendTo(editor);
mw.hook('wikipage.content').fire($preview);
if ($preview[0] && typeof $preview[0].scrollIntoView === 'function') {
$preview[0].scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
}
});
}
save.on('click', function () {
blurAll();
if (saving || isDestroyed) return;
previewRequestSeq++;
const currentContent = getEditorText();
const fullText = currentContent + (expanded ? '' : remainder);
saving = true;
save.setLabel(mw.msg('qe-saving'));
[compare, preview, cancel, more, save].forEach(b => b.setDisabled(true));
checkLatestServerRevision().then(function (checkResult) {
if (isDestroyed) return;
if (checkResult.hasConflict) {
saving = false;
save.setLabel(mw.msg('qe-save'));
[compare, preview, cancel, save].forEach(b => b.setDisabled(false));
more.setDisabled(expanded);
handleEditConflict(fullText);
return;
}
const userSummary = summary.getValue().trim();
const editParams = {
action: 'edit',
title: title,
summary: userSummary ? userSummary + ' // ' + mw.msg('qe-summary-tag') : mw.msg('qe-summary-tag'),
text: fullText,
basetimestamp: base,
starttimestamp: start
};
if (minor.isSelected()) {
editParams.minor = true;
} else {
editParams.notminor = true;
}
if (sectionID !== null && sectionID !== undefined && sectionID !== '') {
editParams.section = sectionID;
}
api('postWithEditToken', editParams, true).then(
function (editRes) {
if (isNewPage) {
closeEditor(true);
reloadPageCleanly();
return;
}
const editInfo = editRes && editRes.edit;
if (title === mw.config.get('wgPageName')) {
if (editInfo && editInfo.newrevid) {
mw.config.set({
wgCurRevisionId: editInfo.newrevid,
wgRevisionId: editInfo.newrevid
});
}
if (editInfo && editInfo.nochange !== undefined) {
closeEditor(true);
return;
}
const catLinks = $('#catlinks');
const parseParams = {
action: 'parse',
prop: catLinks.length ? ['text', 'categorieshtml'] : 'text'
};
if (editInfo && editInfo.newrevid) {
parseParams.oldid = editInfo.newrevid;
} else {
parseParams.page = mw.config.get('wgPageName');
}
api('get', parseParams).then(function (parseRes) {
const contentText = $('#mw-content-text');
const parsedHtml = parseRes && parseRes.parse && parseRes.parse.text && parseRes.parse.text['*'];
closeEditor(true);
if (parsedHtml !== undefined) {
updatePageContentDom(contentText, contentModel, parsedHtml);
mw.hook('wikipage.content').fire(contentText);
}
if (catLinks.length && parseRes && parseRes.parse && parseRes.parse.categorieshtml) {
catLinks.replaceWith(parseRes.parse.categorieshtml['*']);
mw.hook('wikipage.categories').fire($('#catlinks'));
}
}, function () {
closeEditor(true);
});
} else {
closeEditor(true);
}
},
function (code, data) {
if (isDestroyed) return;
saving = false;
save.setLabel(mw.msg('qe-save'));
[compare, preview, cancel, save].forEach(b => b.setDisabled(false));
more.setDisabled(expanded);
if (code === 'editconflict') {
handleEditConflict(fullText);
} else {
showServerErrorDialog(code, data);
}
}
);
});
});
preview.on('click', function () {
if (isDestroyed) return;
blurAll();
const reqSeq = ++previewRequestSeq;
const currentContent = getEditorText();
const summaryValue = summary.getValue().trim();
const loader = new OO.ui.ProgressBarWidget();
loader.$element.addClass('qe-progress-bar');
let $previewTarget;
if (isMobile) {
$previewTarget = $('<div>').append(loader.$element);
switchMobileView('preview', $previewTarget);
} else {
editor.children('.preview').remove();
editor.children('.qe-progress-bar').remove();
loader.$element.appendTo(editor);
}
let localJsonInvalid = false;
if (contentModel === 'json') {
try {
JSON.parse(currentContent);
} catch (_e) {
localJsonInvalid = true;
}
}
const jsonMsgPromise = localJsonInvalid
? getApi().loadMessagesIfMissing(['invalid-json-data', 'json-error-syntax']).catch(function () { return null; })
: Promise.resolve(null);
const canServerValidate = !localJsonInvalid && (contentModel === 'javascript' || contentModel === 'sanitized-css' || contentModel === 'Scribunto');
const validatePromise = canServerValidate
? api('post', {
action: 'codemirror-validate',
content: currentContent,
contentmodel: contentModel,
title: title
}, true).catch(function () {
return null;
})
: Promise.resolve(null);
let parsePromise;
if (localJsonInvalid && !summaryValue) {
parsePromise = Promise.resolve(null);
} else {
const parseParams = {
action: 'parse',
title: title,
contentmodel: localJsonInvalid ? 'wikitext' : contentModel,
summary: summaryValue,
prop: localJsonInvalid ? 'summary' : 'text|summary|parsewarningshtml',
pst: 'true',
preview: 'true',
disablelimitreport: 'true',
disableeditsection: 'true',
disabletoc: 'true',
text: localJsonInvalid ? '' : currentContent
};
if (sectionID !== null && sectionID !== undefined && sectionID !== '') {
parseParams.sectionpreview = 'true';
}
parsePromise = api('post', parseParams, true);
}
Promise.all([parsePromise, validatePromise, jsonMsgPromise]).then(async function ([mainRes, valRes]) {
if (isDestroyed || reqSeq !== previewRequestSeq) return;
loader.$element.remove();
if (!editor || !editor[0] || !editor[0].isConnected) return;
let summaryBlock = '';
if (summaryValue) {
let parsedSummaryHtml = '';
if (mainRes && mainRes.parse && mainRes.parse.parsedsummary) {
parsedSummaryHtml = typeof mainRes.parse.parsedsummary === 'string'
? mainRes.parse.parsedsummary
: (mainRes.parse.parsedsummary['*'] || '');
}
if (!parsedSummaryHtml) {
parsedSummaryHtml = formatLocalSummary(summaryValue);
}
summaryBlock =
'<div class="qe-summary-preview qe-border-color-base">' +
'<b>' + mw.msg('summary-preview') + '</b><br>' +
'<span class="comment">' + parsedSummaryHtml + '</span>' +
'</div>';
}
const mainHtml = (mainRes && mainRes.parse && mainRes.parse.text && mainRes.parse.text['*']) || '';
const $container = $('<div>');
if (summaryBlock) {
$container.append(summaryBlock);
}
const hasUnfilledJsonError = !localJsonInvalid && /json/i.test(contentModel) && /\$1/.test(mainHtml);
if (localJsonInvalid || hasUnfilledJsonError) {
if (hasUnfilledJsonError) {
await getApi().loadMessagesIfMissing(['invalid-json-data', 'json-error-syntax']).catch(function () {});
if (isDestroyed || reqSeq !== previewRequestSeq || !editor || !editor[0] || !editor[0].isConnected) return;
}
const jsonErrText = mw.message('invalid-json-data').exists()
? mw.message('invalid-json-data', mw.message('json-error-syntax').exists() ? mw.msg('json-error-syntax') : 'Syntax error').escaped()
: mw.html.escape(mainHtml.replace(/<[^>]+>/g, '').trim());
$container.append(buildErrorBox(jsonErrText));
} else {
if (valRes && valRes['codemirror-validate'] && valRes['codemirror-validate'].valid === false) {
const errs = valRes['codemirror-validate'].errors || [];
if (errs.length) {
const errHtml = errs.map(function (err) {
const msg = err.html || mw.html.escape(err.message || err.code || '');
const loc = (err.line !== undefined)
? ' (' + err.line + (err.column !== undefined ? ':' + err.column : '') + ')'
: '';
return msg + mw.html.escape(loc);
}).join('<br>');
$container.append(buildErrorBox(errHtml));
}
}
const parseWarnings = (mainRes && mainRes.parse && mainRes.parse.parsewarningshtml) || [];
if (parseWarnings.length) {
const warnNotice = new OO.ui.MessageWidget({
type: 'warning',
inline: false,
label: new OO.ui.HtmlSnippet(parseWarnings.join('<br>'))
});
$container.append(warnNotice.$element.css('margin-bottom', '0.5em'));
}
$container.append(mainHtml, '<div style="clear:both;"></div>');
}
if (isMobile) {
if (!$previewTarget[0].isConnected) return;
$previewTarget.empty().append($container);
} else {
editor.children('.preview').remove();
$container.addClass('qe-border-color-base qe-preview-block preview').appendTo(editor);
}
mw.hook('wikipage.content').fire($container);
}, function (code, data) {
if (isDestroyed || reqSeq !== previewRequestSeq) return;
buildServerErrorNotice(code, data).then(function ($errorContainer) {
if (isDestroyed || reqSeq !== previewRequestSeq) return;
loader.$element.remove();
if (!editor || !editor[0] || !editor[0].isConnected) return;
if (isMobile) {
if (!$previewTarget[0].isConnected) return;
$previewTarget.empty().append($errorContainer);
mw.hook('wikipage.content').fire($errorContainer);
} else {
editor.children('.preview').remove();
const $preview = $('<div>')
.addClass('qe-border-color-base qe-preview-block preview')
.append($errorContainer)
.appendTo(editor);
mw.hook('wikipage.content').fire($preview);
}
});
});
});
compare.on('click', function () {
if (isDestroyed) return;
blurAll();
const reqSeq = ++previewRequestSeq;
const currentContent = getEditorText();
const baseCompareText = part + (expanded ? remainder : '');
const loader = new OO.ui.ProgressBarWidget();
loader.$element.addClass('qe-progress-bar');
const removeLoader = function () {
loader.$element.remove();
};
if (isMobile) {
const $diffBox = $('<div>').append(loader.$element);
switchMobileView('diff', $diffBox);
showCompareDiff($diffBox, title, baseCompareText, currentContent).then(removeLoader, removeLoader);
} else {
editor.children('.preview').remove();
editor.children('.qe-progress-bar').remove();
loader.$element.appendTo(editor);
const $preview = $('<div>').addClass('qe-border-color-base qe-preview-block preview');
showCompareDiff($preview, title, baseCompareText, currentContent).then(function () {
removeLoader();
if (isDestroyed || reqSeq !== previewRequestSeq) return;
if (editor && editor[0] && editor[0].isConnected) {
$preview.appendTo(editor);
}
}, removeLoader);
}
});
cancel.on('click', function () {
if (isDestroyed) return;
blurAll();
if (isConfirmCancel && isDirty()) {
OO.ui.confirm(mw.msg('qe-confirm-cancel-prompt')).then(function (confirmed) {
if (confirmed) {
closeEditor(false);
}
});
} else {
closeEditor(false);
}
});
more.on('click', function () {
if (isDestroyed) return;
expanded = true;
setEditorText(getEditorText() + remainder);
if (!cmInstance && typeof textarea.adjustSize === 'function') {
textarea.adjustSize(true);
}
if (fullSection.length) fullSection.addClass('qe-hide');
more.setDisabled(true);
});
const $summaryLabel = $('<div>').addClass('qe-summary-presets');
function bindSummaryPresets(rawHtml) {
if (isDestroyed) return;
const $temp = $('<div>').html(rawHtml);
const $span = $temp.find('span[style*="text-align"]').first();
const $target = $span.length ? $span : $temp;
$summaryLabel.empty().append($target.contents());
presetItems = [];
$summaryLabel.find('a').each(function () {
const $a = $(this);
const href = $a.attr('href') || '';
if (href.indexOf('Help:') !== -1 || href.indexOf('%E7%BC%96%E8%BE%91%E6%91%98%E8%A6%81') !== -1) return;
const tag = $a.text().trim();
if (!tag) return;
const escaped = tag.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
presetItems.push({
$el: $a,
regex: new RegExp('(?:^|\\s)' + escaped + '(?=\\s|$)', 'i')
});
});
updatePresetSelectionStates();
}
getSummaryPresetsHtml().then(bindSummaryPresets).catch(function () {
if (isDestroyed) return;
$summaryLabel.text(mw.msg('qe-summary-placeholder'));
presetItems = [];
});
$summaryLabel.on('click', 'a', function (e) {
const href = $(this).attr('href') || '';
if (href.indexOf('Help:') !== -1 || href.indexOf('%E7%BC%96%E8%BE%91%E6%91%98%E8%A6%81') !== -1) {
return;
}
e.preventDefault();
const tag = $(this).text().trim();
if (!tag) return;
let cur = summary.getValue();
const escaped = tag.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
const regex = new RegExp('(\\s|^)' + escaped + '(?=\\s|$)', 'g');
if (regex.test(cur)) {
cur = cur.replace(regex, ' ').replace(/\s{2,}/g, ' ').trim();
cur = cur.replace(/(\/\*.*?\*\/)\s*/, '$1 ');
} else {
cur = cur.trim() ? (cur.trim() + ' ' + tag) : tag;
}
summary.setValue(cur);
});
const editOptions = $('<div>')
.addClass('qe-edit-options')
.append(
$('<div id="wpSummaryWidget">')
.addClass('qe-border-color-base')
.append(
$summaryLabel,
summary.$element.addClass('qe-summary-input')
),
new OO.ui.FieldLayout(minor, {
label: new OO.ui.HtmlSnippet(mw.message('minoredit').parse()),
align: 'inline'
}).$element.addClass('qe-minoredit-block'),
buttons.$element.addClass('qe-buttons qe-border-color-base'),
r.isOldRev
? new OO.ui.MessageWidget({
type: 'warning',
inline: true,
label: mw.msg('qe-editing-old-revision', r.revId)
}).$element.css({ 'margin-top': '0.5em' })
: undefined,
title !== mw.config.get('wgPageName')
? $('<div>')
.addClass('qe-not-current-page qe-border-color-base')
.append(
mw.msg('qe-page-edit-notice'),
$('<a>')
.attr('href', mw.util.getUrl(title))
.addClass('qe-not-current-page-link')
.text(title.replace(/_/g, ' '))
)
: undefined
);
if (isMobile) {
const toggleBtn = new OO.ui.ButtonWidget({
label: mw.msg('qe-toggle-options'),
icon: 'expand',
framed: false
});
toggleBtn.on('click', function () {
editOptions.toggleClass('qe-mobile-collapsed');
});
editOptions.addClass('qe-mobile-collapsed').prepend(toggleBtn.$element);
}
const $editorBlock = $('<div>').addClass('qe-editor-block qe-background-color-interactive qe-color-base qe-border-color-base');
if (isMobile) {
$mobileEditorMain = $('<div>').addClass('qe-editor-main-container').append(textarea.$element);
$mobileViewContent = $('<div>').addClass('qe-mobile-view-content');
const saveBtnWidget = new OO.ui.ButtonWidget({
label: mw.msg('qe-save'),
flags: ['primary', 'progressive']
}).on('click', () => {
if (saving) return;
switchMobileView('edit');
save.emit('click');
});
$mobileTopSaveBtn = saveBtnWidget.$element;
const $mobileTopBar = $('<div>').addClass('qe-mobile-topbar').append(
new OO.ui.ButtonWidget({
label: mw.msg('qe-btn-back-to-edit'),
icon: 'previous',
flags: ['safe']
}).on('click', () => switchMobileView('edit')).$element,
mobileTopSummary.$element.addClass('qe-mobile-topbar-summary'),
$mobileTopSaveBtn
);
$mobileViewPanel = $('<div>').addClass('qe-view-panel qe-hide').append($mobileTopBar, $mobileViewContent);
$editorBlock.append($mobileEditorMain, $mobileViewPanel, editOptions);
editor.empty().removeClass('qe-loading').append($editorBlock);
if (!editor.parent().is(document.body)) {
$(document.body).append(editor);
}
} else {
$editorBlock.append(textarea.$element, editOptions);
editor = $('<div id="qe-editor">').append($editorBlock);
inserter(editor);
}
if (modulesRequire) {
try {
if (textarea.$input && textarea.$input[0]) {
textarea.$input[0].setSelectionRange(0, 0);
textarea.$input[0].scrollTop = 0;
}
if (!isMobile) {
if (typeof mw.addWikiEditor === 'function') {
mw.addWikiEditor(textarea.$input);
textarea.$input.wikiEditor({
toolbar: { format: {}, insert: {}, advanced: {} }
});
}
const CodeMirrorWikiEditor = modulesRequire('ext.CodeMirror.WikiEditor');
const { modeName, langSupport } = resolveLanguageMode(modulesRequire, contentModel);
if (typeof CodeMirrorWikiEditor === 'function' && langSupport) {
const cm = new CodeMirrorWikiEditor(textarea.$input[0], langSupport);
cm.mode = modeName;
cm.initialize();
cmInstance = cm;
}
} else {
const CodeMirror = modulesRequire('ext.CodeMirror');
const { modeName, langSupport } = resolveLanguageMode(modulesRequire, contentModel);
if (typeof CodeMirror === 'function' && langSupport) {
const cm = new CodeMirror(textarea.$input[0], langSupport);
cm.mode = modeName;
cm.initialize();
cmInstance = cm;
}
}
const resetScrollToTop = function () {
if (isDestroyed) return;
if (cmInstance && cmInstance.view) {
const sel = cmInstance.view.state.selection.main;
if (sel.from !== 0 || sel.to !== 0) {
cmInstance.view.dispatch({
selection: { anchor: 0, head: 0 },
scrollIntoView: false
});
}
if (cmInstance.view.scrollDOM) {
if (cmInstance.view.scrollDOM.scrollTop !== 0) {
cmInstance.view.scrollDOM.scrollTop = 0;
}
if (cmInstance.view.scrollDOM.scrollLeft !== 0) {
cmInstance.view.scrollDOM.scrollLeft = 0;
}
}
}
if (textarea.$input && textarea.$input[0]) {
if (textarea.$input[0].scrollTop !== 0) {
textarea.$input[0].scrollTop = 0;
}
if (textarea.$input[0].selectionStart !== 0 || textarea.$input[0].selectionEnd !== 0) {
textarea.$input[0].setSelectionRange(0, 0);
}
}
if (isMobile && $mobileEditorMain && $mobileEditorMain[0] && $mobileEditorMain[0].scrollTop !== 0) {
$mobileEditorMain[0].scrollTop = 0;
}
};
resetScrollToTop();
scrollRafId = requestAnimationFrame(resetScrollToTop);
scrollTimer1 = setTimeout(resetScrollToTop, 100);
scrollTimer2 = setTimeout(resetScrollToTop, 300);
if (sectionID !== null && cmInstance && cmInstance.view && cmInstance.view.dom) {
cmInstance.view.dom.addEventListener('input', checkAndUpdateSectionHeader);
cmInputAttached = true;
}
} catch (e) {
qeLog(mw.msg('qe-error-init-cm'), e);
}
}
if (!cmInstance && !isMobile && typeof textarea.setAutosize === 'function') {
textarea.setAutosize(true);
textarea.adjustSize(true);
}
}, function () {
abortLoading();
});
}
function clickHandler(event) {
const $element = $(event.target).closest('.qe-editlink');
if (!$element.length || $element.hasClass('qe-loading')) return;
event.preventDefault();
showEditor($element);
}
window.qeEditSection = function (title, sectionID, $mountTarget) {
showEditor($mountTarget || $('#mw-content-text'), title, sectionID);
};
window.qeCoreReady = $.when(
mw.loader.using([
'oojs-ui-core',
'oojs-ui-widgets',
'oojs-ui-windows',
'oojs-ui.styles.icons-interactions',
'oojs-ui.styles.icons-editing-core',
'oojs-ui.styles.icons-moderation'
]),
$.ready
).then(function () {
$(document.body).on('click', clickHandler);
return true;
});
})();