Article Overview
<button id="download-csv-btn" style="background-color:#e07b00;color:#fff;padding:8px 18px;border:none;border-radius:4px;font-size:14px;font-weight:bold;cursor:pointer;">⬇ Download CSV</button>
</tbody>
| Category | Subcategory | Title | Words | Focus |
|---|---|---|---|---|
| Loading data… | ||||
<script> (function() {
var apiBase = '/api.php'; var allRows = [];
function fetchAllCategories(continueParam, accumulated, callback) {
var url = apiBase + '?action=query&list=allcategories&aclimit=500&format=json&origin=*';
if (continueParam) url += '&accontinue=' + encodeURIComponent(continueParam);
fetch(url)
.then(function(r){ return r.json(); })
.then(function(data) {
var cats = data.query && data.query.allcategories ? data.query.allcategories : [];
cats.forEach(function(c){ accumulated.push(c['*']); });
if (data.continue && data.continue.accontinue) {
fetchAllCategories(data.continue.accontinue, accumulated, callback);
} else {
callback(accumulated);
}
})
.catch(function(){ callback(accumulated); });
}
function getCategoryMembers(catName, type, continueParam, accumulated, callback) {
var cmtype = type || 'page|subcat';
var url = apiBase + '?action=query&list=categorymembers&cmtitle=Category:' + encodeURIComponent(catName) + '&cmlimit=500&cmtype=' + cmtype + '&format=json&origin=*';
if (continueParam) url += '&cmcontinue=' + encodeURIComponent(continueParam);
fetch(url)
.then(function(r){ return r.json(); })
.then(function(data) {
var members = data.query && data.query.categorymembers ? data.query.categorymembers : [];
members.forEach(function(m){ accumulated.push(m); });
if (data.continue && data.continue.cmcontinue) {
getCategoryMembers(catName, type, data.continue.cmcontinue, accumulated, callback);
} else {
callback(accumulated);
}
})
.catch(function(){ callback(accumulated); });
}
function getPageWordCount(pageTitle, callback) {
var url = apiBase + '?action=query&titles=' + encodeURIComponent(pageTitle) + '&prop=revisions&rvprop=content&rvslots=main&format=json&origin=*';
fetch(url)
.then(function(r){ return r.json(); })
.then(function(data) {
var pages = data.query && data.query.pages ? data.query.pages : {};
var pageData = Object.values(pages)[0];
var content = pageData && pageData.revisions && pageData.revisions[0] && pageData.revisions[0].slots && pageData.revisions[0].slots.main && pageData.revisions[0].slots.main['*'] ? pageData.revisions[0].slots.main['*'] : ;
var text = content.replace(/\[\[.*?\]\]/g,'$1').replace(/Template:.*?/gs,).replace(/<.*?>/g,).replace(/[^a-zA-ZäöüÄÖÜß\s]/g,' ');
var words = text.trim().split(/\s+/).filter(function(w){ return w.length > 0; }).length;
callback(words);
})
.catch(function(){ callback(0); });
}
function getPageCategories(pageTitle, callback) {
var url = apiBase + '?action=query&titles=' + encodeURIComponent(pageTitle) + '&prop=categories&cllimit=50&format=json&origin=*';
fetch(url)
.then(function(r){ return r.json(); })
.then(function(data) {
var pages = data.query && data.query.pages ? data.query.pages : {};
var pageData = Object.values(pages)[0];
var cats = pageData && pageData.categories ? pageData.categories.map(function(c){ return c.title.replace('Category:',); }) : [];
callback(cats);
})
.catch(function(){ callback([]); });
}
function buildTable() {
var status = document.getElementById('overview-status');
status.textContent = 'Fetching categories…';
fetch(apiBase + '?action=query&list=allcategories&aclimit=500&format=json&origin=*')
.then(function(r){ return r.json(); })
.then(function(data) {
var topCats = data.query && data.query.allcategories ? data.query.allcategories.map(function(c){ return c['*']; }) : [];
var rows = [];
var pending = 0;
var totalCats = topCats.length;
var processed = 0;
if (totalCats === 0) {
document.getElementById('article-overview-body').innerHTML = 'No categories found.';
status.textContent = ;
return;
}
function checkDone() {
processed++;
status.textContent = 'Loading… (' + processed + '/' + totalCats + ' categories)';
if (processed === totalCats) {
rows.sort(function(a,b){
if (a.category < b.category) return -1;
if (a.category > b.category) return 1;
if (a.sub < b.sub) return -1;
if (a.sub > b.sub) return 1;
return a.title.localeCompare(b.title);
});
allRows = rows;
renderTable(rows);
status.textContent = rows.length + ' articles loaded.';
}
}
topCats.forEach(function(catName) {
getCategoryMembers(catName, 'page|subcat', null, [], function(members) {
var pages = members.filter(function(m){ return m.ns === 0; });
var subcats = members.filter(function(m){ return m.ns === 14; });
if (pages.length === 0 && subcats.length === 0) {
checkDone();
return;
}
var subPending = 0;
function trySubDone() {
subPending--;
if (subPending <= 0) checkDone();
}
// Direct pages in this category (no subcat)
pages.forEach(function(page) {
subPending++;
var focus = catName;
rows.push({ category: catName, sub: '—', title: page.title, words: '…', focus: focus, _title: page.title });
});
// Pages in subcategories
subcats.forEach(function(subcat) {
subPending++;
var subName = subcat.title.replace('Category:',);
getCategoryMembers(subName, 'page', null, [], function(subPages) {
subPages.filter(function(m){ return m.ns === 0; }).forEach(function(page) {
subPending++;
rows.push({ category: catName, sub: subName, title: page.title, words: '…', focus: catName, _title: page.title });
});
trySubDone();
});
});
if (subPending === 0) checkDone();
});
});
})
.catch(function() {
document.getElementById('article-overview-body').innerHTML = 'Error loading data.';
}); }
function renderTable(rows) {
var tbody = document.getElementById('article-overview-body');
if (!rows || rows.length === 0) {
tbody.innerHTML = 'No articles found.';
return;
}
var html = ;
rows.forEach(function(row, i) {
var bg = i % 2 === 0 ? '#1a1a1a' : '#222';
html += ''; html += '' + escHtml(row.category) + ''; html += '' + escHtml(row.sub) + ''; html += '<a href="/wiki/' + encodeURIComponent(row.title.replace(/ /g,'_')) + '">' + escHtml(row.title) + '</a>'; html += '' + escHtml(String(row.words)) + ''; html += '' + escHtml(row.focus) + ''; html += ''; }); tbody.innerHTML = html; } function escHtml(str) { return String(str).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"'); } function downloadCSV() { var rows = allRows; if (!rows || rows.length === 0) { alert('No data to download yet. Please wait for the table to load.'); return; } var csv = 'Category,Subcategory,Title,Words,Focus\n'; rows.forEach(function(row) { csv += [row.category, row.sub, row.title, row.words, row.focus].map(function(v){ return '"' + String(v).replace(/"/g,'""') + '"'; }).join(',') + '\n'; }); var blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' }); var url = URL.createObjectURL(blob); var a = document.createElement('a'); a.href = url; a.download = 'article-overview.csv'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } document.addEventListener('DOMContentLoaded', function() { var btn = document.getElementById('download-csv-btn'); if (btn) btn.addEventListener('click', downloadCSV); buildTable(); }); if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', function() { var btn = document.getElementById('download-csv-btn'); if (btn) btn.addEventListener('click', downloadCSV); buildTable(); }); } else { var btn = document.getElementById('download-csv-btn'); if (btn) btn.addEventListener('click', downloadCSV); buildTable(); } })(); </script>