MediaWiki:Common.js: Difference between revisions
No edit summary |
No edit summary |
||
| Line 256: | Line 256: | ||
})(); | })(); | ||
/* ================================================ */ | /* ================================================ */ | ||
/* ADMIN CONTROL PANEL | /* ADMIN CONTROL PANEL - AlphaX Wiki */ | ||
/* ================================================ */ | /* ================================================ */ | ||
(function() { | (function() { | ||
| Line 287: | Line 288: | ||
'table.axcp-t thead th{background:#111;color:#555;text-transform:uppercase;letter-spacing:.07em;font-size:10px;font-weight:600;padding:10px 12px;border-bottom:1px solid #2E2E2E;cursor:pointer;white-space:nowrap;user-select:none}', | 'table.axcp-t thead th{background:#111;color:#555;text-transform:uppercase;letter-spacing:.07em;font-size:10px;font-weight:600;padding:10px 12px;border-bottom:1px solid #2E2E2E;cursor:pointer;white-space:nowrap;user-select:none}', | ||
'table.axcp-t thead th:hover{color:#FF6600}', | 'table.axcp-t thead th:hover{color:#FF6600}', | ||
'table.axcp-t thead th.sa::after{content:" | 'table.axcp-t thead th.sa::after{content:" u2191";color:#FF6600}', | ||
'table.axcp-t thead th.sd::after{content:" | 'table.axcp-t thead th.sd::after{content:" u2193";color:#FF6600}', | ||
'table.axcp-t td{padding:8px 12px;border-bottom:1px solid rgba(255,255,255,.03);vertical-align:middle}', | 'table.axcp-t td{padding:8px 12px;border-bottom:1px solid rgba(255,255,255,.03);vertical-align:middle}', | ||
'table.axcp-t tr:hover td{background:rgba(255,102,0,.04)}', | 'table.axcp-t tr:hover td{background:rgba(255,102,0,.04)}', | ||
| Line 315: | Line 316: | ||
var contentEl = document.querySelector('#mw-content-text .mw-parser-output') || document.getElementById('mw-content-text'); | var contentEl = document.querySelector('#mw-content-text .mw-parser-output') || document.getElementById('mw-content-text'); | ||
contentEl.innerHTML = '<div id="axcp-root"><div class="axcp-load"><div style="font-size:28px;margin-bottom:14px">⚙</div><div>Loading article database | contentEl.innerHTML = '<div id="axcp-root"><div class="axcp-load"><div style="font-size:28px;margin-bottom:14px">⚙</div><div>Loading article database...</div><div class="axcp-prog" id="axcp-prog">Fetching page list...</div></div></div>'; | ||
var root = document.getElementById('axcp-root'); | var root = document.getElementById('axcp-root'); | ||
| Line 355: | Line 356: | ||
return String(s||'').replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"'); | return String(s||'').replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"'); | ||
} | } | ||
function setP(msg) { var el = document.getElementById('axcp-prog'); if (el) el.textContent = msg; } | function setP(msg) { var el = document.getElementById('axcp-prog'); if (el) el.textContent = msg; } | ||
| Line 366: | Line 366: | ||
}); | }); | ||
fd.sort(function(a,b) { | fd.sort(function(a,b) { | ||
var av=a[sortCol], bv=b[sortCol]; | var av=a[sortCol]||0, bv=b[sortCol]||0; | ||
if (typeof av==='number'&&typeof bv==='number') return sortDir*(av-bv); | if (typeof av==='number'&&typeof bv==='number') return sortDir*(av-bv); | ||
return sortDir*String(av | return sortDir*String(av).localeCompare(String(bv)); | ||
}); | }); | ||
var mxW = Math.max.apply(null,[1].concat(fd.map(function(r){return r.words||0;}))); | var mxW = Math.max.apply(null,[1].concat(fd.map(function(r){return r.words||0;}))); | ||
| Line 391: | Line 391: | ||
h+='<div class="axcp-sc"><div class="axcp-sv" style="color:'+(nocat>0?'#ff7070':'#3ddc84')+'">'+nocat+'</div><div class="axcp-sl">Uncategorised</div></div>'; | h+='<div class="axcp-sc"><div class="axcp-sv" style="color:'+(nocat>0?'#ff7070':'#3ddc84')+'">'+nocat+'</div><div class="axcp-sl">Uncategorised</div></div>'; | ||
h+='</div></div>'; | h+='</div></div>'; | ||
h+='<div class="axcp-ctrl">'; | h+='<div class="axcp-ctrl">'; | ||
h+='<input class="axcp-inp" id="axcps" type="text" placeholder="Search articles or categories..." value="'+esc(filterText)+'">'; | h+='<input class="axcp-inp" id="axcps" type="text" placeholder="Search articles or categories..." value="'+esc(filterText)+'">'; | ||
| Line 405: | Line 404: | ||
h+='<button class="axcp-rbtn" id="axcpr">↻ Refresh Data</button>'; | h+='<button class="axcp-rbtn" id="axcpr">↻ Refresh Data</button>'; | ||
h+='</div>'; | h+='</div>'; | ||
h+='<div class="axcp-tw"><table class="axcp-t"><thead><tr>'; | h+='<div class="axcp-tw"><table class="axcp-t"><thead><tr>'; | ||
[{k:'title',l:'Article'},{k:'cat',l:'Category'},{k:'subcat',l:'Subcategory'}, | [{k:'title',l:'Article'},{k:'cat',l:'Category'},{k:'subcat',l:'Subcategory'}, | ||
{k:'words',l:'Words'},{k:'size',l:'Size'},{k:'status',l:'Status'}, | {k:'words',l:'Words'},{k:'size',l:'Size (KB)'},{k:'status',l:'Status'}, | ||
{k:'touched',l:'Last Edited'},{k:'revisions',l:'Revisions'}, | |||
{k:'watchers',l:'Watchers'},{k:'links',l:'Inbound Links'} | |||
].forEach(function(c){ | ].forEach(function(c){ | ||
var cl=sortCol===c.k?(sortDir===1?'sa':'sd'):''; | var cl=sortCol===c.k?(sortDir===1?'sa':'sd'):''; | ||
| Line 416: | Line 414: | ||
}); | }); | ||
h+='</tr></thead><tbody>'; | h+='</tr></thead><tbody>'; | ||
if (!fd.length) { | if (!fd.length) { | ||
h+='<tr><td colspan=" | h+='<tr><td colspan="10" style="text-align:center;padding:50px;color:#333">No articles match your filters.</td></tr>'; | ||
} | } | ||
fd.forEach(function(r){ | fd.forEach(function(r){ | ||
| Line 430: | Line 427: | ||
h+='<td class="axcp-n">'+fKb(r.size)+'</td>'; | h+='<td class="axcp-n">'+fKb(r.size)+'</td>'; | ||
h+='<td><span class="axcp-st s-'+st[0]+'">'+st[1]+'</span></td>'; | h+='<td><span class="axcp-st s-'+st[0]+'">'+st[1]+'</span></td>'; | ||
h+='<td style="color:#555;white-space:nowrap;font-size:12px">'+fDate(r.touched)+'</td>'; | h+='<td style="color:#555;white-space:nowrap;font-size:12px">'+fDate(r.touched)+'</td>'; | ||
h+='<td class="axcp-n '+(r.revisions>20?'axcp-hi':'')+'">'+(r.revisions||0)+'</td>'; | h+='<td class="axcp-n '+(r.revisions>20?'axcp-hi':'')+'">'+(r.revisions||0)+'</td>'; | ||
h+='<td class="axcp-n '+(r.watchers>0?'axcp-wt':'axcp-z')+'">'+(r.watchers>0?'👁 '+r.watchers:' | h+='<td class="axcp-n '+(r.watchers>0?'axcp-wt':'axcp-z')+'">'+(r.watchers>0?'👁 '+r.watchers:'-')+'</td>'; | ||
h+='<td class="axcp-n '+(r.links>5?'axcp-hi':'')+'">'+(r.links||0)+'</td>'; | h+='<td class="axcp-n '+(r.links>5?'axcp-hi':'')+'">'+(r.links||0)+'</td>'; | ||
h+='</tr>'; | h+='</tr>'; | ||
| Line 462: | Line 458: | ||
function loadData() { | function loadData() { | ||
root.innerHTML='<div class="axcp-load"><div style="font-size:28px;margin-bottom:14px">⚙</div><div>Loading article database | root.innerHTML='<div class="axcp-load"><div style="font-size:28px;margin-bottom:14px">⚙</div><div>Loading article database...</div><div class="axcp-prog" id="axcp-prog">Step 1/4 -- Fetching page list...</div></div>'; | ||
var pages=[], map={}, ids=[]; | var pages=[], map={}, ids=[]; | ||
| Line 470: | Line 465: | ||
if(apc) u+='&apcontinue='+encodeURIComponent(apc); | if(apc) u+='&apcontinue='+encodeURIComponent(apc); | ||
return apiFetch(u).then(function(d){ | return apiFetch(u).then(function(d){ | ||
pages=pages.concat(d.query.allpages); | if(!d||!d.query)return; | ||
pages=pages.concat(d.query.allpages||[]); | |||
var cont=d.continue&&d.continue.apcontinue; | |||
if(cont)return fetchPages(cont); | |||
}); | }); | ||
} | } | ||
// Step 2: info + categories (no revision params to avoid conflicts) | |||
function fetchInfoChunk(i) { | function fetchInfoChunk(i) { | ||
if(i>=ids.length) return Promise.resolve(); | if(i>=ids.length) return Promise.resolve(); | ||
var chunk=ids.slice(i,i+50).join('|'); | var chunk=ids.slice(i,i+50).join('|'); | ||
return apiFetch('/api.php?action=query&pageids='+chunk+'&prop=info|categories | return apiFetch('/api.php?action=query&pageids='+chunk+'&prop=info|categories&inprop=watchers&cllimit=15&format=json').then(function(d){ | ||
if(!d||!d.query||!d.query.pages){return fetchInfoChunk(i+50);} | |||
Object.keys(d.query.pages).forEach(function(pid){ | Object.keys(d.query.pages).forEach(function(pid){ | ||
var pg=d.query.pages[pid]; if(!map[pid])return; | var pg=d.query.pages[pid]; if(!map[pid])return; | ||
map[pid].size=pg.length||0; | map[pid].size=pg.length||0; | ||
map[pid].touched=pg.touched||''; | map[pid].touched=pg.touched||''; | ||
map[pid].watchers=pg.watchers!=null?pg.watchers:0 | map[pid].watchers=pg.watchers!=null?Number(pg.watchers):0; | ||
if(pg.categories){pg.categories.forEach(function(c){ | if(pg.categories){pg.categories.forEach(function(c){ | ||
var cn=c.title.replace('Category:',''); | var cn=c.title.replace('Category:',''); | ||
if(KCATS.indexOf(cn)>=0){if(!map[pid].cat)map[pid].cat=cn;} | if(KCATS.indexOf(cn)>=0){if(!map[pid].cat)map[pid].cat=cn;} | ||
else if(cn.length<60&&cn.indexOf('stub')<0){if(!map[pid].subcat)map[pid].subcat=cn;} | else if(cn.length<60&&cn.toLowerCase().indexOf('stub')<0){if(!map[pid].subcat)map[pid].subcat=cn;} | ||
});} | });} | ||
}); | }); | ||
| Line 495: | Line 493: | ||
} | } | ||
// Step 3: revision counts | |||
function fetchRevChunk(i) { | function fetchRevChunk(i) { | ||
if(i>=ids.length) return Promise.resolve(); | if(i>=ids.length) return Promise.resolve(); | ||
var chunk=ids.slice(i,i+20).join('|'); | var chunk=ids.slice(i,i+20).join('|'); | ||
return apiFetch('/api.php?action=query&pageids='+chunk+'&prop=revisions&rvprop=ids&rvlimit=max&format=json').then(function(d){ | return apiFetch('/api.php?action=query&pageids='+chunk+'&prop=revisions&rvprop=ids&rvlimit=max&format=json').then(function(d){ | ||
if(!d||!d.query||!d.query.pages){return fetchRevChunk(i+20);} | |||
Object.keys(d.query.pages).forEach(function(pid){ | Object.keys(d.query.pages).forEach(function(pid){ | ||
var pg=d.query.pages[pid]; if(!map[pid])return; | var pg=d.query.pages[pid]; if(!map[pid])return; | ||
| Line 507: | Line 507: | ||
} | } | ||
// Step 4: word counts + inbound links | |||
function fetchContentChunk(i) { | function fetchContentChunk(i) { | ||
if(i>=ids.length) return Promise.resolve(); | if(i>=ids.length) return Promise.resolve(); | ||
var chunk=ids.slice(i,i+8).join('|'); | var chunk=ids.slice(i,i+8).join('|'); | ||
return apiFetch('/api.php?action=query&pageids='+chunk+'&prop=revisions|linkshere&rvprop=content&rvslots=main&lhnamespace=0&lhlimit=max&format=json').then(function(d){ | return apiFetch('/api.php?action=query&pageids='+chunk+'&prop=revisions|linkshere&rvprop=content&rvslots=main&lhnamespace=0&lhlimit=max&format=json').then(function(d){ | ||
if(!d||!d.query||!d.query.pages){return fetchContentChunk(i+8);} | |||
Object.keys(d.query.pages).forEach(function(pid){ | Object.keys(d.query.pages).forEach(function(pid){ | ||
var pg=d.query.pages[pid]; if(!map[pid])return; | var pg=d.query.pages[pid]; if(!map[pid])return; | ||
| Line 516: | Line 518: | ||
if(!pg.revisions||!pg.revisions[0])return; | if(!pg.revisions||!pg.revisions[0])return; | ||
var slot=pg.revisions[0].slots?pg.revisions[0].slots.main:pg.revisions[0]; | var slot=pg.revisions[0].slots?pg.revisions[0].slots.main:pg.revisions[0]; | ||
var | var c=slot['*']||slot.content||''; | ||
c=c.replace(/\{\{[\s\S]*?\}\}/g,' ') | |||
.replace(/\[\[File:[^\]]+\]\]/gi,' ') | .replace(/\[\[File:[^\]]+\]\]/gi,' ') | ||
.replace(/\[\[(?:[^\]|]+\|)?([^\]]+)\]\]/g,'$1') | .replace(/\[\[(?:[^\]|]+\|)?([^\]]+)\]\]/g,'$1') | ||
| Line 524: | Line 525: | ||
.replace(/<\!--[\s\S]*?-->/g,' ') | .replace(/<\!--[\s\S]*?-->/g,' ') | ||
.replace(/={2,}[^=]+=={2,}/g,' ') | .replace(/={2,}[^=]+=={2,}/g,' ') | ||
.replace(/[|!*#;: | .replace(/[|!*#;:]/g,' ') | ||
.replace(/https?:\/\/\S+/g,' ') | .replace(/https?:\/\/\S+/g,' ') | ||
.replace(/\s+/g,' ').trim(); | .replace(/\s+/g,' ').trim(); | ||
map[pid].words= | map[pid].words=c?c.split(/\s+/).filter(function(w){return w.length>1;}).length:0; | ||
}); | }); | ||
return fetchContentChunk(i+8); | return fetchContentChunk(i+8); | ||
| Line 534: | Line 535: | ||
fetchPages(null).then(function(){ | fetchPages(null).then(function(){ | ||
setP('Step 2/4 -- Fetching info & categories for '+pages.length+' articles...'); | setP('Step 2/4 -- Fetching page info & categories for '+pages.length+' articles...'); | ||
pages.forEach(function(p){map[p.pageid]={title:p.title,cat:'',subcat:'',words:0,size:0 | pages.forEach(function(p){map[p.pageid]={title:p.title,cat:'',subcat:'',words:0,size:0,touched:'',revisions:0,watchers:0,links:0};}); | ||
ids=pages.map(function(p){return p.pageid;}); | ids=pages.map(function(p){return p.pageid;}); | ||
return fetchInfoChunk(0); | return fetchInfoChunk(0); | ||