/**
* This file is documented using
* [jsduck-syntax](https://github.com/senchalabs/jsduck).
* The source code is available at
* [Wikimedia Commons](https://commons.wikimedia.org/wiki/MediaWiki:Gadget-libTagger.js)
* ([raw](https://commons.wikimedia.org/wiki?title=MediaWiki:Gadget-libTagger.js&action=raw&ctype=text/javascript))
*
* @class tagger
* @singleton
*
*
*
* Quick start: Simple usage:
*
@example
// Load the gadget
mw.loader.using('ext.gadget.libTagger', function () {
});
*
*
* @requires jQuery
* @requires mediaWiki
* @requires libAPI
* @requires wikiDOM
*
* @author Rainer Rillke <https://commons.wikimedia.org/wiki/User:Rillke>
**/
/*
* @license
* The MIT License (MIT) [full text see below]
* GNU General Public License, version 3 (GPL-3.0)
* Creative Commons Attribution 3.0 (CC-BY-3.0)
* Choose whichever license of these you like best.
*
* @jshint valid
* <http://jshint.com/>
*/
/*jshint curly:false, smarttabs:true*/
/*!
Copyright (c) 2013 Rainer Rillke <https://commons.wikimedia.org/wiki/User:Rillke>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
**/
(function($, mw, undefined) {
'use strict';
var tagger, defaultTagInfo;
function firstValue(o) { for (var i in o) { if (o.hasOwnProperty(i)) { return o[i]; } } }
/**
* @cfg defaultTagInfo
* A skeleton showing how the tagInfo object should look like.
* @cfg {string} defaultTagInfo.text
* Tag or text to add
* @cfg {string} defaultTagInfo.summary
* Edit summary
* @cfg {number|string} defaultTagInfo.page
* Page name or page ID
* @cfg {string} [defaultMessge.watchlist='watch']
* Whether to watch the edited page. One of the following values:
* watch, unwatch, preferences, nochange
* @cfg {string|Object} [defaultTagInfo.destination='prepend']
* Where to add the text. Possible strings: prepend, append
* or an object of the following pattern (to target to specific elements)
* {
* location: 'before|after',
* type: 'template|category',
* target: ['Peferred', 'Second choice', 'Third choice'],
* fallback: 'prepend|append'
* }
*/
/**
* @property {Object} defaultTagInfo
* Confer to ``defaultTagInfo`` configuration.
* @private
*/
defaultTagInfo = {
text: "",
summary: "",
page: '',
watchlist: 'watch',
destination: 'prepend'
};
tagger = mw.libs.tagger = {
/**
* Inserts a tag or text into the page specified.
*
* @param {Object} tagInfo
* An object specifying the tag, summary and where to
* insert that tag. Confer to ``defaultTagInfo`` config.
*
* @return {$.Promise}
* A jQuery Promise that is resolved after the tag was
* inserted into the page.
*
@example
// Load the gadget
mw.loader.using('ext.gadget.libTagger', function () {
mw.libs.tagger.tag({
text: "{{Sand}} to be inserted into the sandbox.",
summary: "Inserting a test text",
page: 'Commons:Sandbox',
watchlist: 'nochange',
destination: 'append'
}).done(function() {
mw.libs.tagger.tag({
text: " and pebbles",
summary: "A bit inconvenient but also more funny.",
page: 'Commons:Sandbox',
watchlist: 'nochange',
destination: {location: 'after', type: 'template', target: ['Sand'], fallback: 'append' }
});
});
});
*
*/
tag: function(tagInfo) {
tagInfo = $.extend({}, defaultTagInfo, tagInfo);
if (tagInfo.destination.target) {
return mw.libs.commons.api.$changeText(tagInfo.page, function(text) {
var wikiDOM = mw.libs.wikiDOM,
dom = wikiDOM.parser.text2Obj(text),
destination = tagInfo.destination,
type = destination.type,
nodesOfType = dom.nodesByType[type],
// TODO: Outsource to wikiDOM?
clean = 'template' === type ? 'normalizeTemplateTransclusion' : 'normalizeLink',
ed, inserted;
if (nodesOfType) {
$.each(destination.target, function(i, target) {
target = wikiDOM[clean]( target );
$.each(nodesOfType, function(i, n) {
if (!n.parts) return;
if (target === wikiDOM[clean]( n.parts[0][0] )) {
// node['after']('tag to add');
n[destination.location](tagInfo.text);
inserted = true;
return false;
}
});
if (inserted) return false;
});
}
if (inserted) {
text = wikiDOM.parser.obj2Text(dom);
} else {
switch (destination.fallback) {
case 'append':
text += tagInfo.text;
break;
case 'prepend':
text = tagInfo.text + text;
break;
default:
throw new Error('Unable to insert text and no fallback provided.');
}
}
ed = $.extend({}, tagInfo, {
text: text
});
return ed;
});
} else {
var ed = $.extend({}, tagInfo, {
title: tagInfo.page,
editType: tagInfo.destination + 'text'
});
delete ed.page;
delete ed.destination;
return mw.libs.commons.api.$editPage( ed );
}
}
};
}(jQuery, mediaWiki));
//</nowiki>