// <nowiki>
(function() {
console.log('Running text-reactions.');
var $textarea, api;
/**
* List of reactions. Each reaction object contains:
* - name
* - trigger
* 'keypress' (triggered by keyup in the textarea)
* 'word' (triggered by entry of a word)
* 'interval' (triggered at regular interval)
* 'paste' (triggered by text insertion via copy-paste or drag-drop)
* 'ref' (triggered when reference is inserted via RefToolbar
* - key: (for keypress trigger) key that was pressed
* - word: (for word trigger) word that was written
* - interval: (for interval trigger) in milliseconds
* - react: function that shows the notice/warning if needed.
*
*/
var textReactions = [
{
name: 'keypress-test',
trigger: 'keypress',
key: 'e',
react: function (text, caretPosition) {
console.log('Hit key "e"');
}
},
{
name: 'word-test',
trigger: 'word',
word: 'test',
react: function (text, caretPosition) {
console.log('Hit word "test"');
}
},
{
name: 'paste-test',
trigger: 'paste',
react: function (pasteContent, wikitext) {
console.log('You pasted: ' + pasteContent);
}
},
{
name: 'ref-test',
trigger: 'ref',
react: function (citeTemplate) {
var url = citeTemplate.getParam('url');
// check if url is blacklisted/deprecated/predatory journal, etc
console.log('You inserted ref: ' + citeTemplate.wikitext);
}
},
{
name: 'interval-test',
trigger: 'interval',
interval: 5000,
react: function (wikitext) {
console.log('This is triggered every 5 secs');
}
},
{
test: 'dabNotification',
trigger: 'keypress',
key: ']',
react: function (wikitext, cursorPosition) {
// Adapted from https://gerrit.wikimedia.org/r/c/mediawiki/extensions/Disambiguator/+/716439
var matches = /.*(\[\[([^[\]|]+)(?:\|.*]]|]]))$/.exec(wikitext.slice(0, cursorPosition));
if (matches) {
var pageTitle = matches[matches.length - 1].trim();
var linkWikitext = matches[matches.length - 2];
return api.get({
action: 'query',
titles: pageTitle,
prop: 'pageprops',
ppprop: 'disambiguation',
}).then(function (json) {
if (json.query.pages && json.query.pages[0].pageprops &&
Object.prototype.hasOwnProperty.call(json.query.pages[0].pageprops, 'disambiguation')
) {
console.log('You linked the disambiguation page ' + pageTitle);
}
});
}
},
}
];
$.when(
$.ready,
mw.loader.using([
'mediawiki.util', 'mediawiki.api', 'mediawiki.user',
'jquery.textSelection', 'ext.gadget.libExtraUtil'
])
).then(function () {
if (!['edit', 'submit'].includes(mw.util.getParamValue('action'))) return;
$textarea = $('#wpTextbox1');
if (!$textarea.length) return; // probably VE
api = new mw.Api({
parameters: {
formatversion: 2
}
});
var keyReactionsMap = {};
var wordReactionsMap = {};
var pasteReactions = [];
textReactions.forEach(function (tr) {
if (tr.trigger === 'keypress') {
keyReactionsMap[tr.key] = (keyReactionsMap[tr.key] || []).concat(tr);
} else if (tr.trigger === 'word') {
wordReactionsMap[tr.word] = (wordReactionsMap[tr.word] || []).concat(tr);
} else if (tr.trigger === 'paste') {
pasteReactions.push(tr);
}
});
var WORD_DELIMITERS = [' ', '.', ',', ';'];
var WORD_MATCH_REGEX = /\s(\S+)[ .,;]$/;
var keyupHandler = function (e) {
(keyReactionsMap[e.key] || []).forEach(function (tr) {
tr.react($textarea.textSelection('getContents'), $textarea.textSelection('getCaretPosition'));
});
if (WORD_DELIMITERS.includes(e.key)) {
var content = $textarea.textSelection('getContents');
var caretPosition = $textarea.textSelection('getCaretPosition');
var word = WORD_MATCH_REGEX.exec(content.slice(0, caretPosition))[1];
if (word) {
(wordReactionsMap[word] || []).forEach(function (tr) {
tr.react(content, caretPosition);
});
}
}
};
var pasteHandler = function (e) {
var wikitext = $textarea.textSelection('getContents');
var pasteData = e.originalEvent.clipboardData || // for paste
e.originalEvent.dataTransfer; // for drag-drop
var pasteContent = pasteData.getData('text');
pasteReactions.forEach(function (tr) {
tr.react(pasteContent, wikitext);
});
};
// HACK: Hijack WikiEditor method used by RefToolbar to insert ref into the textbox
var origFunc = $.wikiEditor.modules.toolbar.fn.doAction;
$.wikiEditor.modules.toolbar.fn.doAction = function() {
// Call the original function
var args = Array.prototype.slice.call(arguments);
origFunc.apply($.wikiEditor.modules.toolbar.fn, args);
// Now do our thing
var ref = args[1] && args[1].options && args[1].options.post;
var refContent;
try {
refContent = $($.parseXML(ref)).find('ref').text();
} catch (e) {}
if (refContent) {
var citeTemplate = extraJs.parseTemplates(refContent)[0];
textReactions.filter(function (tr) {
return tr.trigger === 'ref';
}).forEach(function (tr) {
tr.react(citeTemplate);
});
}
};
// Bind textarea event handlers, with CodeMirror integration
$textarea.on('keyup', keyupHandler).on('paste drop', pasteHandler);
mw.hook('ext.CodeMirror.switch').add(function (_enabled, $editor) {
$textarea = $editor;
$textarea.off('keyup', keyupHandler).on('keyup', keyupHandler)
.off('paste drop', pasteHandler).on('paste drop', pasteHandler);
});
var intervalReactions = textReactions.filter(function (tr) {
return tr.trigger === 'interval';
});
intervalReactions.forEach(function (tr) {
setInterval(function () {
tr.react($textarea.textSelection('getContents'));
}, tr.interval);
});
});
})();
// </nowiki>