User:Example/sagittarius.js: Difference between revisions
Jump to navigation
Jump to search
(++) |
(No difference)
|
Revision as of 01:03, 29 October 2013
mw.loader.using(['mediawiki.api', 'mediawiki.Title'], function () {
if (wgNamespaceNumber < 0)
return;
if (wgAction !== 'view')
return;
importStylesheet('User:Kephir/gadgets/sagittarius.css');
function el(tag, child, attr, events) {
var node = document.createElement(tag);
if (child) {
if ((typeof child === 'string') || (typeof child.length !== 'number'))
child = [child];
for (var i = 0; i < child.length; ++i) {
var ch = child[i];
if ((ch === void(null)) || (ch === null))
continue;
else if (typeof ch !== 'object')
ch = document.createTextNode(String(ch));
node.appendChild(ch);
}
}
if (attr) for (var key in attr) {
if ((attr[key] === void(0)) || (attr[key] === null))
continue;
node.setAttribute(key, String(attr[key]));
}
if (events) for (var key in events) {
node.addEventListener(key, events[key], false);
}
return node;
}
function link(child, href, attr, ev) {
attr = attr || {};
ev = ev || {};
if (typeof attr === 'string') {
attr = { "title": attr };
}
if (typeof href === 'string')
attr.href = href;
else {
attr.href = 'javascript:void(null);';
ev.click = href;
}
return el('a', child, attr, ev);
}
var templateGroups = {
"from": "Source",
"to" : "Target",
"misc": "Miscellaneous"
};
var templateAliases = {
"R to anchor" : "R to section",
"R to subtopic": "R to related topic"
};
var redirectTemplates = {
"R from initialism": {
"group": "from",
"label": "Initialism",
"auto": "capitals"
},
"R from alternative spelling": {
"group": "from",
"label": "Alternative spelling with same pronunciation"
},
"R from other capitalisation": {
"group": "from",
"label": "Other capitalisation"
},
"R from misspelling": {
"group": "from",
"label": "Misspelling",
"implies": "R unprintworthy"
},
"R from modification": {
"group": "from",
"label": "Modification (punctuation or word order)"
},
"R from plural": {
"group": "from",
"label": "Plural"
},
"R to plural": {
"group": "to",
"label": "Plural"
},
"R from name and country": {
"group": "from",
"label": "Name, Country/State/Province"
},
"R from long name": {
"group": "from",
"label": "Long name"
},
"R from former name": {
"group": "from",
"label": "Former name with no historical significance"
},
"R from historic name": {
"group": "from",
"label": "Historic name",
"implies": ["R printworthy"]
},
"R from scientific name": {
"group": "from",
"label": "Scientific name",
"implies": ["R printworthy"]
},
"R to scientific name": {
"group": "to",
"label": "Scientific name"
},
"R from alternative scientific name": {
"group": "from",
"label": "Alternative scientific name"
},
"R from molecular formula": {
"group": "from",
"label": "Molecular formula"
},
"R from alternative language": {
"group": "from",
"label": "Alternative language"
},
"R from ASCII": {
"group": "from",
"label": "ASCII-only title",
"auto": "from-ascii-to-unicode"
},
"R from Unicode": {
"group": "from",
"label": "Unicode title",
"auto": "from-unicode-to-ascii"
},
"R from diacritics": {
"group": "from",
"label": "Title with diacritics",
"conflict": "R from title without diacritics"
},
"R from title without diacritics": {
"group": "from",
"label": "Title without diacritics",
"conflict": "R from diacritics"
},
"R from surname": {
"group": "from",
"label": "Surname",
},
"R from CamelCase": {
"group": "from",
"label": "Old-style CamelCase name"
},
"R from unnecessary disambiguation": {
"group": "from",
"label": "Redundant disambiguation"
},
"R to decade": {
"group": "to",
"label": "Decade article"
},
"R to disambiguation page": {
"group": "to",
"label": "Disambiguation page"
},
"R from ambiguous page": {
"group": "from",
"label": "Ambiguous title"
},
"R from EXIF": {
"group": "from",
"label": "Title derived from EXIF data"
},
"R to list entry": {
"group": "to",
"label": "List entry"
},
"R from member": {
"group": "from",
"label": "Member of the target organisation"
},
"R with possibilities": {
"group": "misc",
"label": "Might be worthy of own article",
"conflict": "R without possibilities"
},
"R without possibilities": {
"group": "misc",
"label": "Not worthy of own article",
"conflict": "R with possibilities"
},
"R unprintworthy": {
"group": "misc",
"label": "Unprintworthy",
"conflict": "R printworthy"
},
"R printworthy": {
"group": "misc",
"label": "Printworthy",
"conflict": "R unprintworthy"
},
"R to related topic": {
"group": "to",
"label": "Related topic"
},
"R from related word": {
"group": "from",
"label": "Related word"
},
"R from school": {
"group": "from",
"label": "School"
},
"R to section": {
"group": "to",
"label": "Section",
"auto": "anchor"
},
"R from shortcut": {
"group": "from",
"label": "Shortcut",
"conflict": "R from template shortcut"
},
"R from template shortcut": {
"group": "from",
"label": "Template shortcut",
"conflict": "R from shortcut"
},
"R from song": {
"group": "from",
"label": "Song (to artist article)"
},
"R from duplicated article": {
"group": "from",
"label": "Duplicated article"
},
"R from merge": {
"group": "from",
"label": "Merged article"
},
"R from move": {
"group": "from",
"label": "Moved title"
},
"R to category": {
"group": "to",
"label": "Category namespace (from other namespaces)",
"target-namespace": wgNamespaceIds["category"],
"xnr-only": true
},
"R to help": {
"group": "to",
"label": "Help namespace",
"target-namespace": wgNamespaceIds["help"],
},
"R to main": {
"group": "to",
"label": "Main namespace (from other namespaces)",
"target-namespace": 0,
"xnr-only": true
},
"R to portal": {
"group": "to",
"label": "Portal namespace",
"target-namespace": wgNamespaceIds["portal"]
},
"R to talk": {
"group": "to",
"label": "Talk namespace",
"target-talk": true
},
"R to template": {
"group": "to",
"label": "Template namespace (from other namespaces)",
"target-namespace": wgNamespaceIds["template"],
"xnr-only": true
},
"R to user": {
"group": "to",
"label": "User namespace",
"target-namespace": wgNamespaceIds["user"]
},
"R to project": {
"group": "to",
"label": "Wikipedia namespace",
"target-namespace": wgNamespaceIds["project"]
}
};
var api = new mw.Api();
var contentText = document.getElementById('mw-content-text');
var firstHeading = document.getElementById('firstHeading');
var redirMsg = contentText.getElementsByClassName('redirectMsg')[0];
var ui = el('div');
var edittoken = null;
function MarkupBlob(markup) {
var rdrx = /^#REDIRECT\s*\[\[\s*([^\|{}[\]]+?)\s*]]\s*/i;
var tprx = /^\s*{{(R [A-Za-z ]+)}}\s*/i;
var m;
if (!markup) {
this.target = '';
this.rcatt = {};
this.tail = '';
return this;
}
if (!(m = rdrx.exec(markup)))
throw new Error('Not a redirect');
markup = markup.substr(m[0].length);
this.target = m[1];
this.rcatt = {}
while (m = tprx.exec(markup)) {
var alias = m[1];
markup = markup.substr(m[0].length);
while (templateAliases[alias])
alias = templateAliases[alias]; // hopefully there are no loops.
this.rcatt[alias] = true;
}
this.tail = markup;
}
MarkupBlob.prototype.toString = function () {
var markup = '#REDIRECT [[' + this.target + ']]\n\n';
for (var key in this.rcatt) {
if (this.rcatt[key])
markup += '{{' + key + '}}\n';
}
markup += '\n';
markup += this.tail;
return markup;
}
function buildTagList(rcatt) {
function makeCheckBox(key) {
return el('label', [
el('input', null, {
"type": "checkbox",
"checked": (key in rcatt) ? "checked" : null,
}, {
change: function (ev) {
rcatt[key] = this.value;
}
}),
' ',
redirectTemplates[key].label
])
}
var list = el('dl', null, { "class": "tag-list" });
var group = {};
for (var key in templateGroups) {
list.appendChild(el('dt', templateGroups[key]));
list.appendChild(el('dd', group[key] = el('ul')));
}
for (var key in redirectTemplates) {
var label = makeCheckBox(key);
group[redirectTemplates[key].group].appendChild(el('li', label));
}
return list;
}
function buildEditingUI(mblob, stamp) {
var statusbar;
var needsCheck = true;
var doSave;
mblob = mblob || new MarkupBlob();
return el('form', [
el('div', [
el('img', null, {
'src': '//bits.wikimedia.org/static-1.22wmf18/skins/common/images/redirectltr.png', // XXX: make this site- and directionality-agnostic
'alt': '#REDIRECT'
}),
el('input', null, {
'type': 'text',
'class': 'redirectText',
'value': mblob.target
}, {
'change': function (ev) {
mblob.target = this.value;
statusbar.data = '';
needsCheck = true;
}
})
], {
'class': 'redirectMsg'
}),
buildTagList(mblob.rcatt),
el('p', [
el('input', null, { 'type': 'submit', 'value': 'Save' }),
el('span', [statusbar = document.createTextNode('')], {
'class': 'status-line'
})
])
], {
'action': 'javascript:void(0)',
'class': 'kephir-sagittarius-editor'
}, {
'submit': doSave = function (ev) {
var that = this;
ev.preventDefault();
if (!/^\s*[^\|{}[\]]+\s*$/.test(mblob.target)) {
statusbar.data = 'Error: the target page name is invalid.'
return;
}
if (needsCheck) {
statusbar.data = 'Checking target validity...';
needsCheck = false;
api.get({
action: 'query',
titles: mblob.target,
redirects: '1'
}, {
success: function (result) {
if (result.query.redirects) {
statusbar.data = 'Error: The target page is already a redirect. Click "Save" again to proceed anyway.';
return;
}
if (result.query.pages["-1"]) {
statusbar.data = 'Error: The target page does not exist. Click "Save" again to proceed anyway.';
return;
}
doSave(ev);
}
})
return;
}
statusbar.data = 'Saving...';
api.post({
action: 'edit',
title: wgPageName,
basetimestamp: stamp,
token: mw.user.tokens.get('editToken'),
summary: 'Redirecting to [[' + mblob.target + ']] (using [[User:Kephir/gadgets/sagittarius|Sagittarius]])',
text: mblob.toString()
}, {
success: function (result) {
statusbar.data = 'Saved. Reloading page...'
if (/redirect=no/.test(location.href)) // XXX
location.reload();
else
location.search = location.search ? location.search + '&redirect=no' : '?redirect=no';
}
});
}
});
}
function buildCreationUI() {
var mblob = new MarkupBlob();
// ...
return el('div', [
buildTagList(mblob.rcatt)
], {
'class': 'kephir-sagittarius-editor'
});
}
if (wgArticleId === 0) { // nonexistent page.
ui.appendChild(el('div', [
link(['Create a redirect'], function () {
while (ui.hasChildNodes())
ui.removeChild(ui.firstChild);
ui.appendChild(buildEditingUI(null, null));
}), ' from this page with Sagittarius'
], {
"class": "kephir-sagittarius-invite"
}));
contentText.parentNode.insertBefore(ui, contentText);
} else if (wgIsRedirect && redirMsg) {
// start editor immediately
ui.appendChild(el('div', ['Loading page source…'], {
"class": "kephir-sagittarius-loading"
}));
contentText.appendChild(ui);
api.get({
action: 'query',
prop: 'info|revisions',
rvprop: 'timestamp|content',
pageids: wgArticleId,
rvstartid: wgCurRevisionId,
rvlimit: 1,
rvdir: 'older',
intoken: 'edit',
}, {
success: function (result) {
while (ui.hasChildNodes())
ui.removeChild(ui.firstChild);
var page = result.query.pages[wgArticleId];
var mblob;
token = page.edittoken;
try {
mblob = new MarkupBlob(page.revisions[0]['*']);
} catch(e) {
ui.appendChild(el('div', ['Error: unable to parse page. Edit the source manually.'], {
"class": "kephir-sagittarius-error"
}));
return;
}
redirMsg.parentNode.removeChild(redirMsg);
ui.appendChild(buildEditingUI(mblob, page.revisions[0].timestamp));
}
})
} else if (wgUserName === 'Kephir') { // testing for now
firstHeading.appendChild(document.createTextNode(' '));
firstHeading.appendChild(link(['←'], function () {
ui.appendChild(buildCreationUI());
}, {
"class": "kephir-sagittarius-createlink",
"title": "Create redirects to this page"
}));
}
});