(function () {
// https://gitlab.wikimedia.org/diegodlh/w2c-gadget/-/blob/434e4b9954774d2e4c890f9043c1fe397f046a05/script.js
// Copyright (C) 2022 Diego de la Hera and contributors.
// This work is released under the terms of GPL-3.0 or any later version.
const EDIT_LABEL = "Web2Cit 🖉";
const TRACK_TOPIC = "stats.mediawiki_gadget_Web2Cit_total"
class Web2Cit {
static disabledItem = 'web2cit.disabled';
constructor() {
this.unpatched = {};
this.initialized = false;
// this.mode = undefined;
this.server = "https://web2cit.toolforge.org/";
if (window.web2citServer) {
try {
this.server = new URL(window.web2citServer).href;
} catch {
console.log("Ignoring invalid web2citServer setting");
}
}
this.search
}
get disabled() {
return localStorage.getItem(this.disabledItem) === "true";
// if (this.mode === "visual") {
// return localStorage.getItem(this.disabledItem) === "true";
// } else {
// return false;
// }
}
set disabled(disabled) {
localStorage.setItem(this.disabledItem, disabled === "true");
// if (this.mode === "visual") {
// localStorage.setItem(this.disabledItem, disabled === "true");
// } else {
// throw Error(`Cannot disable in ${this.mode} mode`);
// }
}
init() {
if (this.initialized) return;
console.log('Web2Cit: Initializing...');
this.patchInitialize();
if(!this.disabled) this.enable();
this.initialized = true;
// const surface = ve.init.target.getSurface();
// this.mode = surface.getMode();
// if (this.mode === "visual") {
// this.patchInitialize();
// }
// if (!this.disabled || this.mode === "source") {
// this.enable();
// }
}
enable() {
console.log("Web2Cit: Enabling...");
this.patchAjax();
this.patchPerformLookup();
// if (this.mode === "visual") {
// this.patchBuildTemplateResults();
// };
}
disable() {
console.log("Web2Cit: Disabling...");
this.unpatchAjax();
this.unpatchPerformLookup();
this.editButton.toggle(false);
// if (this.mode === "visual") {
// this.unpatchBuildTemplateResults();
// }
}
getSearch() {
return this.search;
}
setSearch(search) {
this.search = search;
}
patchInitialize () {
// console.log("Web2Cit: Patching CitoidInspector's \"initalize\"...")
const initialize = ve.ui.CitoidInspector.prototype.initialize;
// const toggle = new OO.ui.ToggleSwitchWidget({
// value: !this.disabled
// });
const toggle = new OO.ui.CheckboxInputWidget({
selected: !this.disabled,
});
const field = new OO.ui.FieldLayout( toggle, {
align: 'inline',
label: 'Web2Cit'
} );
const onToggleChange = (event) => {
if (event.target.checked) {
this.disabled = false;
this.enable();
// console.log('{ action: "enable" }');
mw.track(TRACK_TOPIC, 1, { action: "enable" });
} else {
this.disabled = true;
this.disable();
// console.log('{ action: "disable" }');
mw.track(TRACK_TOPIC, 1, { action: "disable" });
}
};
// a dedicated Web2Cit credit label
this.web2citCredit = new OO.ui.LabelWidget( {
classes: [ 've-ui-citoidInspector-credit' ]
} );
this.web2citCredit.setLabel($(`<div>${
ve.msg(
'citoid-citoiddialog-credit',
`<a href="" target="_blank">${EDIT_LABEL}</a>`
)
}</div>`))
this.web2citCredit.$element.on("click", (event) => {
if (event.target.tagName == "A") {
// console.log('{ action: "edit" }');
mw.track(TRACK_TOPIC, 1, { action: "edit" });
}
});
// a button widget to edit Web2Cit configuration from Citoid error message
const editButton = new OO.ui.ButtonWidget( {
label: EDIT_LABEL,
flags: [ 'progressive' ],
} );
const onEditButtonClick = () => {
window.open(this.server + this.search, "_blank");
// console.log('{ action: "edit_error" }');
mw.track(TRACK_TOPIC, 1, { action: "edit_error" });
};
editButton.toggle(false);
this.editButton = editButton;
ve.ui.CitoidInspector.prototype.initialize = function () {
initialize.bind(this)();
toggle.$element.on("change", onToggleChange);
const parentElement = this.autoProcessPanels.lookup.$element;
field.$element.insertAfter(parentElement.children().first());
editButton.$element.on("click", onEditButtonClick)
this.errorMessage.label.children().last().append( editButton.$element );
}
}
patchPerformLookup() {
if (this.unpatched.performLookup) return;
// console.log("Web2Cit: Patching CitoidInspector's \"performLookup\"...");
const performLookup = ve.ui.CitoidInspector.prototype.performLookup;
this.unpatched.performLookup = performLookup;
const server = this.server;
const getSearch = this.getSearch.bind(this);
const setSearch = this.setSearch.bind(this);
const web2citCredit = this.web2citCredit;
const editButton = this.editButton;
const onCitationInsert = (web2cit) => {
if (web2cit) {
// console.log("Web2Cit: Web2Cit citation inserted");
updateEditSummary();
// console.log('{ action: "insert" }');
mw.track(TRACK_TOPIC, 1, { action: "insert" });
} else {
// console.log('{ action: "insert_other" }');
mw.track(TRACK_TOPIC, 1, { action: "insert_other" });
}
};
ve.ui.CitoidInspector.prototype.performLookup = function () {
setSearch();
editButton.toggle(false)
return performLookup.bind(this)().then(() => {
const search = getSearch();
const results = this.results;
if (search) {
// update web2citCredit href
web2citCredit.label.children()[0].href = server + search;
if (results.length) {
// move Citoid credit into first reference widget
this.previewSelectWidget.items[0].$element.append(this.credit.$element)
if (!results.at(-1).source.includes("Web2Cit")) {
// if no Web2Cit citation, create and append an empty reference widget
const widget = new OO.ui.Widget()
widget.$element.addClass( 've-ui-citoidReferenceWidget' )
widget.destroy = () => {};
this.previewSelectWidget.insertItem(widget)
}
// get last reference widget
const refWidget = this.previewSelectWidget.items.at(-1);
// append Web2Cit credit
refWidget.$element.append(web2citCredit.$element);
// add Web2Cit reference widget class
const w2cRefWidgetClass = "web2citReferenceWidget";
refWidget.$element.addClass(w2cRefWidgetClass);
// register citation insert handler for all widgets
for (const refWidget of this.previewSelectWidget.items) {
if (refWidget.insertButton) { // may be undefined if we created it above
const web2cit = refWidget.$element.hasClass(w2cRefWidgetClass);
refWidget.insertButton.$button.on(
"click", () => { onCitationInsert(web2cit) }
);
}
}
} else {
// assume error
editButton.toggle(true)
}
}
})
}
}
patchAjax() {
if (this.unpatched.ajax) return;
// console.log("Web2Cit: Patching ajax...")
const ajax = $.ajax;
this.unpatched.ajax = ajax;
const server = this.server;
const setSearch = this.setSearch.bind(this);
$.ajax = function(url, options) {
// If url is an object, simulate pre-1.5 signature
if ( typeof url === "object" ) {
options = url;
url = undefined;
}
// Force options to be an object
options = options || {};
url = url || options.url;
const match = url.match(
/^\/api\/rest_v1\/data\/citation\/mediawiki\/(?<search>.+)/
);
if (match !== null) {
let { search } = match.groups;
// consider using ve.safeDecodeURIComponent()?
search = decodeURIComponent(search);
// mimick citoid's CitoidService.js
search = search.trim()//.toLowerCase();
// if the query does not begin with either http:// or https://
// only assume that the user meant a url if it follows the pattern
// www.something.somethingelse
// otherwise, we may miss DOIs, QIDs, PMCIDs, ISBNs or PMIDs
// which are handled by Citoid differently
// instruct the user to always add http:// or https:// at the beginning
// to explicitly mean a url
if (search.match(/^www\..+\..+/i)) {
search = "http://" + search;
};
if (
search.match(/^https?:\/\/.+/i) &&
// to prevent an endless loop, continue using web2cit through citoid
// if user explicitly asks to translate a web2cit url
!search.match(
new RegExp(`^https?://${server.replace(/^https?:\/\//i, "")}.+`, "i")
)
) {
setSearch(search);
console.log('Web2Cit: Search will be resolved using Web2Cit + Citoid...')
url = server + "translate";
options.data = {
"citoid": "true",
"format": "mediawiki",
"url": search
};
// only track web2cit generate actions
// console.log("{ action: 'generate' }");
mw.track(TRACK_TOPIC, 1, { action: "generate" });
}
}
return ajax.bind(this)(url, options);
}
}
unpatchAjax() {
if (!this.unpatched.ajax) return;
// console.log("Web2Cit: Unpatching ajax...");
$.ajax = this.unpatched.ajax;
delete this.unpatched.ajax;
}
unpatchPerformLookup() {
if (!this.unpatched.performLookup) return;
// console.log("Web2Cit: Unpatching CitoidInspector's \"performLookup\"...");
ve.ui.CitoidInspector.prototype.performLookup = this.unpatched.performLookup;
delete this.unpatched.performLookup;
}
}
function updateEditSummary() {
const hashtag = "#Web2Cit";
const saveDialog = ve.init.target.saveDialog;
const initialEditSummary = (
ve.init.target.editSummaryValue || ve.init.target.initialEditSummary
);
let editSummaryValue = (
saveDialog ?
saveDialog.editSummaryInput.getValue() :
initialEditSummary
) || "";
if (!editSummaryValue.includes(hashtag)) {
const prefix = ve.msg("citoid-citoiddialog-title"); // "Add a citation"
if (!editSummaryValue.trim()) { // empty edit summary
editSummaryValue = prefix;
} else if (editSummaryValue == initialEditSummary) {
editSummaryValue += prefix;
}
// we need a space before hashtag, otherwise Hashtags tool won't pick it (T262234)
editSummaryValue = (
editSummaryValue.trimEnd() + ` [[m:Web2Cit| ${hashtag}]]`
);
if (saveDialog) {
saveDialog.setEditSummary(editSummaryValue);
} else {
ve.init.target.editSummaryValue = editSummaryValue;
}
}
}
// a "gadget loader" - a small gadget that tells VE to load the real gadget
// once VE is activated by the user
// https://www.mediawiki.org/wiki/VisualEditor/Gadgets#Deployment
mw.loader.using( 'ext.visualEditor.desktopArticleTarget.init', function () {
// console.log("Web2Cit script will load...");
// return mw.loader.getScript('/w/index.php?title=User:Diegodlh/Web2Cit/script.js&action=raw&ctype=text/javascript');
window.web2cit = new Web2Cit();
mw.hook( 've.activationComplete' ).add( function () {
// console.log('Web2Cit: Running "ve.activationComplete" hook...')
window.web2cit.init();
});
// mw.hook( 've.wikitextInteractive' ).add( function () {
// console.log('Web2Cit: Running "ve.wikitextInteractive" hook...')
// window.web2cit.init();
// } );
});
}())