//<source lang=javascript>
/* TODO: test, convert [[Wikipedia:AutoEd/wikilinks.js]],
* [[User:GregU/dashes.js]], and [[User:Ash/tidyCitations.js]],
* take a crack at [[User:Cameltrader/Advisor.js/Description#Further_development]]
* make some suggestions only apply in article namespace
*/
var aekNumberToMonthArray = ['January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December'];
/* General purpose function to convert regexp to suggestions */
function aekSuggestionsFromRe(regex, repl, str, skel) {
var match, sug;
var suggestions = [];
while (match = regex.exec(str)) {
var substr = str.substring(match.index, match.index + match[0].length);
var r = substr.replace(regex, repl);
sug = skel;
sug.start = match.index;
sug.end = match.index + match[0].length;
sug.replacement = r;
suggestions.push(sug);
// HACK: regex.exec should get subsequent matches automatically, but it doesn't (?)
str = str.substring(match.index + match[0].length, str.length);
}
return suggestions;
}
/* ported from [[Wikipedia:AutoEd/extrabreaks.js]] */
function aekAdvisorExtraBreaks(s) {
var skel = {
name: "extra-br",
description: "Remove unneeded br tags"
};
var res = [{
re: /[\t ]*<[\s\/\.]*br[\s\/\.]*>[\t ]*([\t\n ]*?)(\]\]|}}|\|)/gim,
rep: '$1$2'
},
{
re: /[\t ]*<[\s\/\.]*br[\s\/\.]*>[\t ]*([\s]*?[\n]\*)/gim,
rep: '$1'
},
{
re: /[\t ]*<[\s\/\.]*br[\s\/\.]*>[\t ]*([\n])[\t ]*([\n])/gim,
rep: '$1$2'
}];
var suggestions = res.map(function(p) {
return aekSuggestionsFromRe(p.re, p.rep, s, skel);
}).reduce(function (x, y) {
return x.concat(y);
});
return suggestions;
}
ct.rules.push(aekAdvisorExtraBreaks);
/* ported from [[Wikipedia:AutoEd/htmltowikitext.js]] */
function aekAdvisorHTMLToWiki(s) {
var skel = {
name: "wikify",
description: "Convert HTML to wikicode"
};
var res = [
{ re: /<(B|STRONG)[ ]*>((?:[^<>]|<[a-z][^<>]*\/>|<([a-z]+)(?:| [^<>]*)>[^<>]*<\/\3>)*?)<\/\1[ ]*>/gi,
rep: "'''$2'''" },
{ re: /<(I|EM)[ ]*>((?:[^<>]|<[a-z][^<>]*\/>|<([a-z]+)(?:| [^<>]*)>[^<>]*<\/\3>)*?)<\/\1[ ]*>/gi,
rep: "''$2''" },
// </br>, <\br>, <br\>, <BR />, ...
{ re: /<<?[\\\/\s\.]*BR[\\\s\.]*>>?/gim, rep: '<br />' },
{ re: /<BR\/>/gim, rep: '<br />' },
// <hr>
{ re: /([\r\n])[\t ]*<[\\\/\. ]*HR[\\\/\. ]*>/gi, rep: '$1----' },
{ re: /(.)<[\\\/\. ]*HR[\\\/\. ]*>/gi, rep: '$1\n----' },
// Not really an HTML-to-wikitext fix, but close enough
{ re: /<[\\\/\s]*REFERENCES[\\\/\s]*>/gim, rep: '<references />' },
// Repeated references tag
{ re: /(<references \/>)[\s]*\1/gim, rep: '$1' },
// Make sure <H1>, ..., <H6> is after a newline
{ re: /([^\r\n ])[\t ]*(<H[1-6][^<>]*>)/gim, rep: '$1\n$2' },
// Make sure </H1>, ..., </H6> is before a newline
{ re: /(<\/H[1-6][^<>]*>)[\t ]*([^\r\n ])/gim, rep: '$1\n$2' },
// Remove newlines from inside <H1>, ..., <H6>
// Replace <H1>, ..., <H6> with wikified section headings
{ re: /(^|[\r\n])[\t ]*<H1[^<>]*>([^\r\n]*?)<\/H1[\r\n\t ]*>[\t ]*([\r\n]|$)/gim, rep: '$1=$2=$3' },
{ re: /(^|[\r\n])[\t ]*<H2[^<>]*>([^\r\n]*?)<\/H2[\r\n\t ]*>[\t ]*([\r\n]|$)/gim, rep: '$1==$2==$3' },
{ re: /(^|[\r\n])[\t ]*<H3[^<>]*>([^\r\n]*?)<\/H3[\r\n\t ]*>[\t ]*([\r\n]|$)/gim, rep: '$1===$2===$3' },
{ re: /(^|[\r\n])[\t ]*<H4[^<>]*>([^\r\n]*?)<\/H4[\r\n\t ]*>[\t ]*([\r\n]|$)/gim, rep: '$1====$2====$3' },
{ re: /(^|[\r\n])[\t ]*<H5[^<>]*>([^\r\n]*?)<\/H5[\r\n\t ]*>[\t ]*([\r\n]|$)/gim, rep: '$1=====$2=====$3' },
{ re: /(^|[\r\n])[\t ]*<H6[^<>]*>([^\r\n]*?)<\/H6[\r\n\t ]*>[\t ]*([\r\n]|$)/gim, rep: '$1======$2======$3' },
];
var suggestions = res.map(function(p) {
return aekSuggestionsFromRe(p.re, p.rep, s, skel);
}).reduce(function(x, y) {
return x.concat(y);
});
return suggestions;
}
ct.rules.push(aekAdvisorHTMLToWiki);
function aekAdvisorLinks(s) {
var skel = {
name: "links",
description: "Fix external links"
};
var res = [{
re: /\]\[/g,
rep: "] ["
}];
var suggestions = res.map(function(p) {
return aekSuggestionsFromRe(p.re, p.rep, s, skel);
}).reduce(function (x, y) {
return x.concat(y);
});
return suggestions;
}
ct.rules.push(aekAdvisorLinks);
function aekAdvisorTemplates(s) {
var skel = {
name: "templates",
description: "Fix template syntax"
};
var res = [
//Remove unneeded Template: text from transclusions
{
re: /{{[_ ]*Template:[_ ]*/gi,
rep: '{{'
},
//Replace redirects to Reflist with Reflist
{
re: /{{[_ ]*(?:Reference[_ ]+List|References-Small|Reflink)[_ ]*(\||}})/gi,
rep: '{{Reflist$1'
},
{
re: /{{[_ ]*(?:Refs|Reference|Ref-list|Listaref|FootnotesSmall)[_ ]*(\||}})/gi,
rep: '{{Reflist$1'
},
//Replace a long version of Reflist with Reflist
{
re: /]*[ ]+class=['"]*references-small['"]*[^<>]*>[\r\n]*[\r\n]*<\/div>/gim,
rep: '{{Reflist}}'
},
//Replace redirects to about with about
{
re: /{{[_ ]*(?:Otheruses4|Four[_ ]+other[_ ]+uses|Otherusesabout|This2)[_ ]*(\||}})/gi,
rep: '{{about$1'
}
];
var suggestions = res.map(function(p) {
return aekSuggestionsFromRe(p.re, p.rep, s, skel);
}).reduce(function(x, y) {
return x.concat(y);
});
return suggestions;
}
ct.rules.push(aekAdvisorTemplates);
function aekAddArticleTags(s) {
var match;
var suggestions = [];
/* TODO: add length heuristic?; rewrite in terms of templates array */
var stub_regex = new RegExp("stub}" + "}");
var is_stub = stub_regex.test(s);
var templates_re = new RegExp("{" + "{[^|}]+", "g");
var templates = s.match(templates_re) || [];
templates = templates.map(function(str) {
str = str.replace("subst:", "");
str = str.replace("{" + "{", "");
str = str.toLowerCase();
return str;
});
var now = new Date();
var template_date = "|date = " + aekNumberToMonthArray[now.getMonth()] + " " + now.getFullYear();
/* Trivia sections */
if ((match = /== ?(Trivia|Miscellany|Miscellaneous) ?==/i.exec(s))) {
if (!templates.some(function(str) {
return str == "trivia"
})) {
suggestions.push({
name: "trivia",
description: "Tag trivia sections",
start: match.index,
end: match.index + match[0].length,
replacement: match[0] + "\n{" + "{trivia" + template_date + "}}"
});
}
}
/* Excessive links */
/* Most external links begin with http (?) */
var s_without_refs = s.replace(/<ref>.*?<\/ref>/, "");
var ext_links = s_without_refs.match(/[^\[]\[\s*http.*?\]/g) || [];
if (ext_links.length > 3 && !templates.some(function(str) {
return str == "excessivelinks" || str == "too many links";
})) {
/* for testing, make 20-ish for release */
suggestions.push({
name: "too-many-links",
description: "Tag for profusion of external links",
start: 0,
end: 0,
replacement: "{" + "{Excessivelinks" + template_date + "}}\n"
});
}
/* some things only make sense for full articles */
if (!is_stub) {
/* No sections */
if (!/== ?.+ ?==/.test(s) && !templates.some(function(str) {
return str == "sections"
})) {
suggestions.push({
name: "no-sections",
description: "Tag for lack of sections",
start: 0,
end: 0,
replacement: "{" + "{Sections" + template_date + "}}\n"
});
}
/* No references */
if (!/<ref>/.test(s) && !templates.some(function(str) {
return str == "unreferenced"
})) {
suggestions.push({
name: "no-references",
description: "Tag for lack of references",
start: 0,
end: 0,
/* TODO: unreferencedBLP */
replacement: "{" + "{unreferenced" + template_date + "}}\n"
});
}
} /* is_stub */
return suggestions;
}
ct.rules.push(aekAddArticleTags);
//</source>