(function refRenamerCore() {
let messages = Object.assign({
loadingSource: 'Loading the source...',
loadingHtml: 'Loading HTML...',
parsing: 'Parsing wikitext...',
opening: 'Opening the diff...',
continue: 'Continue',
main: 'Main fallback stack:',
lastName: 'Last name',
firstName: 'First name',
author: 'Author',
periodical: 'Periodical/website',
publisher: 'Publisher',
article: 'Article',
book: 'Book',
domain: 'Domain',
firstPhrase: 'First phrase',
lowercase: 'Lowercase',
removeDia: 'Remove diacritics',
removePunct: 'Remove punctuation',
replaceSpace: 'Replace space with:',
year: 'Year',
yearFallback: 'Fall back on any 4-digit number',
yearConvert: 'Convert to ASCII',
latinIncrement: 'Append Latin letters on collision',
increment: 'Collision resolution:',
incrementExample: 'Example',
incrementExamples: '$1, $2...',
delimiter: 'Delimiter:',
delimitConditional: 'Insert delimiters only after numerals',
removeUnreused: 'Remove unreused names',
apply: 'Apply',
reset: 'Reset',
tableName: 'Name',
tableCaption: 'References to rename',
tableRef: 'Reference',
tableNewName: 'New name',
tableAddRemove: '±',
reapplyTooltip: 'Reapply current options',
propsTooltip: 'View/insert properties',
keepTooltip: 'Uncheck to remove',
tableRemove: '(Remove)',
removeTooltip: 'Remove from references to rename',
otherTableCaption: 'Other named references',
notReused: '(not reused)',
expand: 'Expand',
collapse: 'Collapse',
addTooltip: 'Add to references to rename',
addAll: 'Add all',
resetSelection: 'Reset selection',
noNamesAlert: 'The source does not contain ref names to rename.',
noChangesError: 'No names have been modified.',
numericError: 'The following names are invalid as they consist only of numerals:',
duplicatesError: 'The following names are already used or input more than once:',
templatesWarn: 'Ref names in the following templates will not be replaced:',
invalidWarn: 'The following names have been ignored because it could not be determined which references correspond to them:',
summary: 'Replaced VE ref names using RefRenamer',
genericSummary: 'Renamed references using RefRenamer'
}, window.refrenamerMessages);
let getMsg = (key, ...args) => (
messages.hasOwnProperty(key) ? mw.format(messages[key], ...args) : key
);
let notif;
let notify = key => {
mw.notify(getMsg(key), {
autoHideSeconds: 'long',
tag: 'refrenamer'
}).then(n => {
notif = n;
});
};
let dialog;
class Ref {
constructor(name, normalized) {
this.name = name;
this.names = new Set([name]);
this.normalized = normalized;
this.isVe = /^:\d+$/.test(name);
this.isAuto = this.isVe || /^auto(?:generated)?\d*$/.test(name);
}
initProps() {
this.props = {};
let coinsSpan = this.$ref[0].querySelector('.Z3988');
if (coinsSpan) {
new URLSearchParams(coinsSpan.title).forEach((v, k) => {
if (k.startsWith('rft.')) {
this.props[k.slice(4)] = v;
} else if (k === 'rft_id') {
if (/^https?:/.test(v)) {
if (this.props.domain) return;
try {
let url = new URL(v);
this.props.domain = url.hostname;
} catch (e) {}
} else {
let match = v.match(/^info:([^\/]+)\/(.+)$/);
if (match) {
this.props[match[1]] = match[2];
}
}
}
});
}
let text = this.$ref.text();
if (this.props.date) {
let numbers = this.props.date.match(/\p{Nd}+/gu);
if (numbers) {
let converted = numbers.map(n => toAscii(n));
let year = String(Math.max(...converted));
let original = numbers[converted.indexOf(year)];
this.props.year = original;
if (original !== year) {
this.props.yearAscii = year;
}
}
} else {
let match = text.match(/(?:^|\P{Nd})(\p{Nd}{4})(?!\p{Nd})/u);
if (match) {
this.props.textYear = match[1];
let ascii = toAscii(match[1]);
if (ascii !== match[1]) {
this.props.textYearAscii = ascii;
}
}
}
let link = this.$ref[0].querySelector('a.external');
if (link && link.hostname !== this.props.domain) {
this.props.linkDomain = link.hostname;
}
let match = text.match(/[^\s\p{P}].*?(?=\s*(?:\p{P}|$))/u);
if (match) {
this.props.phrase = match[0];
}
Object.freeze(this.props);
}
initRows() {
let rowClass = !this.reused && 'refrenamer-unreused';
this.$row = $('').addClass(rowClass).appendTo(dialog.$tbody);
this.$otherRow = $('').addClass(rowClass).appendTo(dialog.$otherTbody);
this.nameCell = $('').addClass('refrenamer-name')
.append($('').text(this.name))[0];
this.refCell = $('').addClass('refrenamer-ref mw-parser-output')
.append(this.$ref)[0];
this.moveButton = new OO.ui.ButtonWidget({
framed: false,
invisibleLabel: true
}).connect(dialog, { click: ['toggleActive', this] });
this.moveCell = $('').addClass('refrenamer-addremove')
.append(this.moveButton.$element)[0];
}
setActive(active) {
if (active === this.active) return;
this.active = active;
this[active ? '$otherRow' : '$row'].addClass('refrenamer-hidden');
let tooltip = getMsg(active ? 'removeTooltip' : 'addTooltip');
this.moveButton
.setFlags({ destructive: active, progressive: !active })
.setIcon(active ? 'subtract' : 'add')
.setLabel(tooltip).setTitle(tooltip);
this[active ? 'initInput' : 'initToggle']();
this[active ? '$row' : '$otherRow']
.prepend(this.nameCell, this.refCell)
.append(this.moveCell)
.removeClass('refrenamer-hidden');
}
initInput() {
if (this.input) return;
this.input = new OO.ui.MultilineTextInputWidget({
allowLinebreaks: false,
placeholder: this.name,
spellcheck: false
}).connect(dialog, { enter: ['executeAction', 'continue'] });
this.reapplyButton = new OO.ui.ButtonWidget({
classes: ['refrenamer-reapplybutton'],
framed: false,
icon: 'undo',
invisibleLabel: true,
label: getMsg('reapplyTooltip')
}).connect(dialog, {
click: ['applyConfig', [this], true]
}).connect(this.input, { click: 'focus' });
this.propsButton = new OO.ui.ButtonMenuSelectWidget({
classes: ['refrenamer-propsbutton'],
clearOnSelect: true,
framed: false,
icon: 'downTriangle',
invisibleLabel: true,
label: getMsg('propsTooltip'),
menu: {
$floatableContainer: this.input.$element,
horizontalPosition: 'end',
width: '16em'
}
});
this.propsButton.getMenu().addItems(
Object.entries(this.props).map(([k, v]) => {
let option = new OO.ui.MenuOptionWidget({
label: v,
title: v
});
option.$label.attr('data-refrenamer', k);
return option;
})
).connect(this, { choose: 'onPropChoose' });
if (!this.reused) {
this.keepCheck = new OO.ui.CheckboxInputWidget({
classes: ['refrenamer-keepcheck'],
invisibleLabel: true,
label: getMsg('keepTooltip')
}).connect(this, { change: 'onKeepChange' });
}
$('').addClass('refrenamer-newname').append(
this.keepCheck && this.keepCheck.$element,
this.input.$element,
this.reapplyButton.$element,
this.propsButton.$element
).appendTo(this.$row);
}
initToggle() {
if (this.$toggle) return;
this.$toggle = $('