பயனர்:Balajijagadesh/annotator.js
குறிப்பு - சேமித்த பின்னர், நீங்கள் செய்த மாற்றங்களைக் காண்பதற்கு உங்கள் உலவியின் இடைமாற்று அகற்றப்பட வேண்டும்.
- மொஸில்லா பயர்பாக்ஸ் / சபாரி: Shift+Reload, அல்லது Ctrl-F5 அல்லது Ctrl-R (⌘-R Mac ல்)
- கூகிள் குரோம் Ctrl-Shift-R அழுத்தவும். (⌘-Shift-R Mac ல்) ;
- இண்டர்நெட் எக்ஸ்ப்ளோரர்: Ctrl-Refresh அல்லது Ctrl-F5 ஐ அழுத்தவும்.
- ஒபேரா: Tools → Preferences இல் இடைமாற்றை அகற்றவும்;
/**
* Annotator
*
* This gadget provides an annotation tool for Wikisource, linking text selections to Wikidata items.
*
* @author Mahir256. Copied from https://bn.wikisource.org/wiki/User:Mahir256/annotator.js
*
*/
mw.loader.using( 'oojs-ui' ).done( function () {
$( function () {
importStylesheet('User:Balajijagadesh/annotator.css');
function getCurrentlySelectedText() {
var text = "";
if (window.getSelection) {
text = window.getSelection().toString();
} else if (document.selection && document.selection.type != "Control") {
text = document.selection.createRange().text;
}
return text;
}
function getSelectionRange() {
var range, sel, container, outputElem;
if (document.selection) {
range = document.selection.createRange();
range.collapse(isStart);
} else {
sel = window.getSelection();
if (sel.getRangeAt) {
if (sel.rangeCount > 0) {
range = sel.getRangeAt(0);
}
} else {
// Old WebKit
range = document.createRange();
range.setStart(sel.anchorNode, sel.anchorOffset);
range.setEnd(sel.focusNode, sel.focusOffset);
// Handle the case when the selection was selected backwards (from the end to the start in the document)
if (range.collapsed !== sel.isCollapsed) {
range.setStart(sel.focusNode, sel.focusOffset);
range.setEnd(sel.anchorNode, sel.anchorOffset);
}
}
}
return range;
}
function getPreviousPageSpanFromRange(range){
return getPreviousPageSpan(range.startContainer);
}
function getPreviousPageSpan(startContainer){
var stuff = $(startContainer), parent = stuff.parent(), foundpage = 0, currentlySelectedText = getCurrentlySelectedText();
// for each sibling prior to this one
while(parent[0] != $(document)[0]) {
stuff.prevAll().each(function() {
var current_elems = $(".ws-pagenum", this);
var current_length = current_elems.length;
if (current_length > 0) {
foundpage = current_elems[current_length - 1];
return false;
}
});
if(foundpage != 0){
break;
}
stuff = parent; parent = stuff.parent();
}
return foundpage;
}
function getPageNameFromWsPagenum(item) {
if(!item)
return '';
return $(item).attr('title');
}
function MyProcessDialog( config ) {
MyProcessDialog.super.call( this, config );
}
OO.inheritClass( MyProcessDialog, OO.ui.ProcessDialog );
MyProcessDialog.static.name = 'myProcessDialog';
MyProcessDialog.static.title = 'Annotator';
MyProcessDialog.static.actions = [
{ label: 'Annotate', action: 'save', flags: 'primary' },
{ label: 'Annotate in bulk', action: 'masssave' },
{ label: 'Cancel', flags: 'safe' }
];
var myWikidataApi = new mw.Api({'ajax':{'url': 'https://www.wikidata.org/w/api.php', 'timeout': 30000, 'dataType': 'json'}});
var myWikisourceApi = new mw.Api();
MyProcessDialog.prototype.initialize = function () {
MyProcessDialog.super.prototype.initialize.apply( this, arguments );
var currentDialog = this;
this.content = new OO.ui.PanelLayout( { padded: true, expanded: false } );
this.currentlySelectedText = getCurrentlySelectedText();
this.textInput = new OO.ui.SearchWidget( {
value: this.currentlySelectedText
} );
this.textInput.results.selectedQid = '';
$(this.textInput.$element).css('height', '240px');
$(this.textInput.$element).addClass('annotator-results');
this.target_range = getSelectionRange();
if(mw.config.get('wgNamespaceNumber') == 250) {
this.targetPage = mw.config.get('wgPageName');
}
else{
this.targetPage = decodeURI(
getPageNameFromWsPagenum(
getPreviousPageSpanFromRange(
this.target_range
)
)
);
}
console.log('target page', this.targetPage);
this.content.$element.append(
new OO.ui.LabelWidget( {
label: 'Find a Wikidata item:'
} ),
this.textInput.$element
);
this.$body.append( this.content.$element );
this.textInput.onQueryChange = function (value) {
var currentTextInput = this;
this.results.clearItems();
var items = [];
myWikidataApi.get({
'action': 'wbsearchentities',
'search': value,
'errorformat': 'plaintext',
'language': 'ta',
'type': 'item',
'origin': '*',
'limit': '5',
'uselang': 'ta'
}).done( function ( data3 ) {
myWikidataApi.get({
'action': 'wbgetentities',
'ids': data3['search'].map((entry) => entry['id']).join('|'),
'props': 'claims',
'origin': '*'
}).done(function(data2){
for ( i = 0; i < 5; ++i ) {
(function(i, data3, data2){
console.log('Hello!', Object.keys(data2['entities']).length);
if(i < Object.keys(data2['entities']).length) {
(function(data3_search_i, data2_entities_i){
var newOptionWidget = new OO.ui.OptionWidget( {
data: data3_search_i['id'],
label: $( '<span><b>' + data3_search_i['display']['label']['value'] + '</b><br/></span>' )
} );
if('P18' in data2_entities_i['claims']){
image_element = $('<img src="' +
'https://commons.wikimedia.org/w/index.php?title=Special:Redirect/file/' + data2_entities_i['claims']['P18'][0]['mainsnak']['datavalue']['value']
+ '&width=128px" style="height: 2.8em;display: block;float: right;"/>');
$(newOptionWidget.$label).css('display', 'inline-block');
newOptionWidget.$element.append(image_element);
currentTextInput.results.addItems( [ newOptionWidget ] );
}
else{
image_element = $('<img src="' +
"https://commons.wikimedia.org/w/index.php?title=Special:Redirect/file/White_box_28x52.png"
+ '&width=128px" style="height: 2.8em;display: block;float: right;"/>');
$(newOptionWidget.$label).css('display', 'inline-block');
newOptionWidget.$element.append(image_element);
currentTextInput.results.addItems( [ newOptionWidget ] );
}
myWikidataApi.get({
'action': 'wbgetentities',
'ids': data2_entities_i['claims']['P31'].map((claim) => claim['mainsnak']['datavalue']['value']['id']).join('|'),
'props': 'labels',
'origin': '*'
}).done(function(data4){
if('description' in data3_search_i['display']){
newOptionWidget.$label.html(newOptionWidget.$label.html() + data3_search_i['display']['description']['value'] + '</span>');
}
else{
newOptionWidget.$label.html(newOptionWidget.$label.html() + Object.values(data4['entities']).map((entity) =>
'ta' in entity['labels'] ? entity['labels']['ta']['value'] : ('en' in entity['labels'] ? entity['labels']['en']['value'] : undefined)
).filter(label => label !== undefined).join(', '));
}
});
})(data3['search'][i], data2['entities'][data3['search'][i]['id']]);
}
})(i, data3, data2);
}
});
});
};
this.textInput.results.on('choose', function(item, selected){
if(item !== null){
console.log(item.getData());
currentDialog.textInput.results.selectedQid = item.getData();
}
});
this.textInput.onQueryChange(this.currentlySelectedText);
};
function replaceRevisionText(target_range, revisionText, selectedQid, currentlySelectedText){
var startContainerDataReplaced = target_range.startContainer.data.replace(/\s+$/, '');
console.log('Original:', target_range.startContainer.data);
console.log('Replaced:', startContainerDataReplaced);
return revisionText.replace(
startContainerDataReplaced,
startContainerDataReplaced.slice(0, target_range.startOffset)
+ '{{wdl|' + selectedQid + '|' + currentlySelectedText + '}}' +
startContainerDataReplaced.slice(target_range.endOffset)
)
}
function replaceInRevisionText(revisionText, selectedQid, currentlySelectedText){
var test_regex = new RegExp("(?:(?<!\\|Q\\d+\\|[^}]*)(" + currentlySelectedText + "[^ ,।;?!–—<}-]*)[^}]*}}"
+ ")\|(?:"
+ "\\|Q\\d+\\|[^}]*(" + currentlySelectedText + "[^ ,।;?!–—<}-]*)(?![^}]*}})"
+ ")\|(?:"
+ "(?<!\\|Q\\d+\\|[^}]*)(" + currentlySelectedText + "[^ ,।;?!–—<}-]*)(?![^}]*}}))"
);
console.log('Original:', revisionText);
function replacer(match, p1, p2, p3, offset, string, groups) {
var cST = p1 || p2 || p3;
return match.replace(cST, '{{wdl|' + selectedQid + '|' + cST + '}}');
}
var replacedRevisionText = revisionText.replace(test_regex, replacer);
console.log("Replaced:", replacedRevisionText);
return replacedRevisionText;
}
function replaceAllOccurrences(currentlySelectedText, selectedQid, dialog){
var pagesToEdit = {};
$('.prp-pages-output').each(function(index){
$((index == 0) ? '.wikisource-header-template ~ *' : '*', this).contents().filter(function() {
return ((this.nodeType == 3) && ($(this).text().search(currentlySelectedText) != -1));
}).each(function(){
var currentPage = decodeURI(getPageNameFromWsPagenum(getPreviousPageSpan(this)));
if(currentPage in pagesToEdit){
pagesToEdit[currentPage].push($(this).text());
}
else{
pagesToEdit[currentPage] = [$(this).text()];
}
});
});
console.log(pagesToEdit);
function makeEditFunc(pageToEdit, editsToMake, currentlySelectedText, selectedQid) {
return function () {
return $.Deferred(function (deferred) {
myWikisourceApi.get({
'action': 'query',
'prop': 'revisions',
'titles': pageToEdit,
'rvslots': 'main',
'rvprop': 'content',
}).done(function(data){
// save same page
var revisionText = Object.values(data.query.pages)[0].revisions[0].slots.main['*'],
headerText = revisionText.slice(0, revisionText.indexOf('</noinclude>')+'</noinclude>'.length),
replacedText = revisionText.slice(revisionText.indexOf('</noinclude>')+'</noinclude>'.length, revisionText.lastIndexOf('<noinclude>')),
footerText = revisionText.slice(revisionText.lastIndexOf('<noinclude>'));
replacedText = replaceInRevisionText(replacedText, selectedQid, currentlySelectedText);
var promise = myWikisourceApi.postWithToken('csrf', {
'action': 'edit',
'title': pageToEdit,
// perform find/replace
'text': headerText + replacedText + footerText,
'summary': 'গণহারে টীকা দেওয়া হয়েছে'
});
promise.done(function () {
console.log(pageToEdit, 'All done!')
});
promise.fail(function (code, obj) {
console.log(pageToEdit, 'কি যেন সমস্যা তৈরি হল!')
});
promise.always(function () {
deferred.resolve();
});
});
});
};
}
// Make a chain of deferred objects. We chain them rather than execute them in
// parallel so that we don't make 1000 simultaneous delete requests and bring the
// site down. We use deferred objects rather than the promise objects returned
// from the API request so that the chain continues even if some articles gave
// errors.
var deferred;
for (let key in pagesToEdit) {
if(typeof(deferred) == 'undefined'){
deferred = makeEditFunc(key, pagesToEdit[key], currentlySelectedText, selectedQid)();
}
else {
deferred = deferred.then(makeEditFunc(key, pagesToEdit[key], currentlySelectedText, selectedQid));
}
}
$.when(deferred).then(function () {
var status = new OO.ui.MessageWidget( {
type: 'success',
label: 'টীকা ঠিক মতো দেওয়া হয়েছে!'
});
dialog.$body.prepend(status.$element);
dialog.executeAction('');
});
}
MyProcessDialog.prototype.getActionProcess = function ( action ) {
var dialog = this;
if ( action == 'masssave') {
console.log(action);
replaceAllOccurrences(dialog.currentlySelectedText, dialog.textInput.results.selectedQid, dialog);
}
else if ( action == 'save' ) {
var selectedQid = dialog.textInput.results.selectedQid;
if(selectedQid != '') {
console.log('The selected Qid is', selectedQid);
// get source of target page
myWikisourceApi.get({
'action': 'query',
'prop': 'revisions',
'titles': dialog.targetPage,
'rvslots': 'main',
'rvprop': 'content',
}).done(function(data){
// save same page
var revisionText = Object.values(data.query.pages)[0].revisions[0].slots.main['*'];
var replacedText = replaceRevisionText(dialog.target_range, revisionText, selectedQid, dialog.currentlySelectedText);
console.log(dialog.target_range);
console.log(revisionText);
console.log(replacedText);
var promise = myWikisourceApi.postWithToken('csrf', {
'action': 'edit',
'title': dialog.targetPage,
// perform find/replace
'text': replacedText,
'summary': 'টীকা দেওয়া হয়েছে'
}).done(function () {
var status = new OO.ui.MessageWidget( {
type: 'success',
label: 'The annotation is correct!'
});
dialog.$body.prepend(status.$element);
dialog.executeAction('');
}).fail(function (code, obj) {
var status = new OO.ui.MessageWidget( {
type: 'error',
label: 'কী ত্রুটি যেন হলো:' + obj.error.info
});
dialog.$body.prepend(status.$element);
});
});
}
}
return MyProcessDialog.super.prototype.getActionProcess.call( this, action );
};
MyProcessDialog.prototype.getBodyHeight = function () {
return 300;
};
var node2 = new OO.ui.ButtonWidget( {
icon: 'edit',
label: 'Edit',
invisibleLabel: true,
classes: ['annotator-cornerlink']
} );
node2.on( 'click', function ( e ) {
var windowManager = new OO.ui.WindowManager();
$( document.body ).append( windowManager.$element );
var dialog = new MyProcessDialog();
windowManager.addWindows( [ dialog ] );
windowManager.openWindow( dialog );
} );
$( 'body' ).append( node2.$element );
} );
} );