<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://alphax.wiki/index.php?action=history&amp;feed=atom&amp;title=AlphaX%3AAdmin_Control_Panel</id>
	<title>AlphaX:Admin Control Panel - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://alphax.wiki/index.php?action=history&amp;feed=atom&amp;title=AlphaX%3AAdmin_Control_Panel"/>
	<link rel="alternate" type="text/html" href="https://alphax.wiki/index.php?title=AlphaX:Admin_Control_Panel&amp;action=history"/>
	<updated>2026-04-21T06:38:53Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.45.1</generator>
	<entry>
		<id>https://alphax.wiki/index.php?title=AlphaX:Admin_Control_Panel&amp;diff=9707&amp;oldid=prev</id>
		<title>Admin: Replaced content with &quot;&lt;!-- Admin Control Panel — content rendered by MediaWiki:Common.js --&gt; __NOTOC__ __NOEDITSECTION__&quot;</title>
		<link rel="alternate" type="text/html" href="https://alphax.wiki/index.php?title=AlphaX:Admin_Control_Panel&amp;diff=9707&amp;oldid=prev"/>
		<updated>2026-04-21T01:35:30Z</updated>

		<summary type="html">&lt;p&gt;Replaced content with &amp;quot;&amp;lt;!-- Admin Control Panel — content rendered by MediaWiki:Common.js --&amp;gt; __NOTOC__ __NOEDITSECTION__&amp;quot;&lt;/p&gt;
&lt;a href=&quot;https://alphax.wiki/index.php?title=AlphaX:Admin_Control_Panel&amp;amp;diff=9707&amp;amp;oldid=9705&quot;&gt;Show changes&lt;/a&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://alphax.wiki/index.php?title=AlphaX:Admin_Control_Panel&amp;diff=9705&amp;oldid=prev</id>
		<title>Admin: Create Admin Control Panel with live API-powered article table (words, category, size, revisions, watchers, dates, status)</title>
		<link rel="alternate" type="text/html" href="https://alphax.wiki/index.php?title=AlphaX:Admin_Control_Panel&amp;diff=9705&amp;oldid=prev"/>
		<updated>2026-04-21T01:30:44Z</updated>

		<summary type="html">&lt;p&gt;Create Admin Control Panel with live API-powered article table (words, category, size, revisions, watchers, dates, status)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;lt;div id=&amp;quot;axcp-root&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;style&amp;gt;&lt;br /&gt;
#axcp-root{font-family:system-ui,-apple-system,sans-serif;background:#0D0D0D;color:#fff;padding:0;margin:0 -10px;}&lt;br /&gt;
.axcp-header{background:#1A1A1A;border-bottom:1px solid #2E2E2E;padding:22px 28px 18px;}&lt;br /&gt;
.axcp-title{font-size:22px;font-weight:700;color:#fff;margin-bottom:4px;}&lt;br /&gt;
.axcp-subtitle{font-size:12px;color:#666;text-transform:uppercase;letter-spacing:.1em;}&lt;br /&gt;
.axcp-stats-row{display:flex;gap:12px;margin:16px 0 0;}&lt;br /&gt;
.axcp-stat{background:#0D0D0D;border:1px solid #2E2E2E;border-radius:12px;padding:12px 18px;flex:1;}&lt;br /&gt;
.axcp-stat-val{font-size:24px;font-weight:700;color:#FF6600;}&lt;br /&gt;
.axcp-stat-label{font-size:11px;color:#666;text-transform:uppercase;letter-spacing:.08em;margin-top:2px;}&lt;br /&gt;
.axcp-controls{display:flex;gap:10px;padding:16px 28px;background:#0D0D0D;border-bottom:1px solid #2E2E2E;flex-wrap:wrap;align-items:center;}&lt;br /&gt;
.axcp-search{flex:1;min-width:200px;background:#1A1A1A;border:1px solid #2E2E2E;border-radius:8px;padding:9px 14px;color:#fff;font-size:14px;outline:none;}&lt;br /&gt;
.axcp-search:focus{border-color:rgba(255,102,0,.5);}&lt;br /&gt;
.axcp-select{background:#1A1A1A;border:1px solid #2E2E2E;border-radius:8px;padding:9px 14px;color:#fff;font-size:13px;outline:none;cursor:pointer;}&lt;br /&gt;
.axcp-select:focus{border-color:rgba(255,102,0,.5);}&lt;br /&gt;
.axcp-badge-count{background:rgba(255,102,0,.12);border:1px solid rgba(255,102,0,.3);color:#FF6600;border-radius:6px;padding:3px 10px;font-size:12px;font-weight:600;}&lt;br /&gt;
.axcp-table-wrap{overflow-x:auto;padding:0 28px 28px;}&lt;br /&gt;
table.axcp-table{width:100%;border-collapse:collapse;margin-top:16px;font-size:13px;}&lt;br /&gt;
table.axcp-table th{background:#111;color:#666;text-transform:uppercase;letter-spacing:.08em;font-size:11px;font-weight:600;padding:10px 12px;border-bottom:1px solid #2E2E2E;cursor:pointer;white-space:nowrap;user-select:none;}&lt;br /&gt;
table.axcp-table th:hover{color:#FF6600;}&lt;br /&gt;
table.axcp-table th.sorted-asc::after{content:&amp;quot; ↑&amp;quot;;color:#FF6600;}&lt;br /&gt;
table.axcp-table th.sorted-desc::after{content:&amp;quot; ↓&amp;quot;;color:#FF6600;}&lt;br /&gt;
table.axcp-table td{padding:9px 12px;border-bottom:1px solid rgba(255,255,255,.04);vertical-align:middle;color:#ccc;}&lt;br /&gt;
table.axcp-table tr:hover td{background:rgba(255,102,0,.04);}&lt;br /&gt;
table.axcp-table tr:last-child td{border-bottom:none;}&lt;br /&gt;
.axcp-title-link{color:#fff;text-decoration:none;font-weight:500;}&lt;br /&gt;
.axcp-title-link:hover{color:#FF6600;}&lt;br /&gt;
.axcp-cat-badge{display:inline-block;padding:2px 8px;border-radius:6px;font-size:11px;font-weight:600;white-space:nowrap;}&lt;br /&gt;
.axcp-status{display:inline-block;padding:2px 8px;border-radius:6px;font-size:11px;font-weight:600;}&lt;br /&gt;
.status-stub{background:rgba(255,60,60,.15);color:#ff6b6b;border:1px solid rgba(255,60,60,.3);}&lt;br /&gt;
.status-short{background:rgba(255,166,0,.15);color:#ffa600;border:1px solid rgba(255,166,0,.3);}&lt;br /&gt;
.status-medium{background:rgba(61,220,132,.15);color:#3ddc84;border:1px solid rgba(61,220,132,.3);}&lt;br /&gt;
.status-long{background:rgba(100,160,255,.15);color:#64a0ff;border:1px solid rgba(100,160,255,.3);}&lt;br /&gt;
.axcp-bar-wrap{background:#1A1A1A;border-radius:4px;height:6px;width:80px;overflow:hidden;display:inline-block;vertical-align:middle;margin-left:6px;}&lt;br /&gt;
.axcp-bar{height:6px;border-radius:4px;background:linear-gradient(to right,#FF6600,#FF8533);}&lt;br /&gt;
.axcp-loading{text-align:center;padding:60px;color:#666;font-size:15px;}&lt;br /&gt;
.axcp-error{text-align:center;padding:40px;color:#ff6b6b;}&lt;br /&gt;
.axcp-num{text-align:right;font-variant-numeric:tabular-nums;color:#999;}&lt;br /&gt;
.axcp-refresh{background:linear-gradient(135deg,#FF6600,#FF8533);border:none;border-radius:8px;color:#fff;padding:9px 18px;font-size:13px;font-weight:600;cursor:pointer;white-space:nowrap;}&lt;br /&gt;
.axcp-refresh:hover{opacity:.85;}&lt;br /&gt;
&amp;lt;/style&amp;gt;&lt;br /&gt;
&amp;lt;script&amp;gt;&lt;br /&gt;
(function(){&lt;br /&gt;
  var root=document.getElementById(&amp;#039;axcp-root&amp;#039;);&lt;br /&gt;
&lt;br /&gt;
  // Category color map&lt;br /&gt;
  var CAT_COLORS={&lt;br /&gt;
    &amp;#039;Sexual Health&amp;#039;:&amp;#039;rgba(255,100,100,.15)|#ff7a7a&amp;#039;,&lt;br /&gt;
    &amp;#039;Dating, Sex &amp;amp; Relationships&amp;#039;:&amp;#039;rgba(255,182,100,.15)|#FFB664&amp;#039;,&lt;br /&gt;
    &amp;#039;Kink &amp;amp; BDSM&amp;#039;:&amp;#039;rgba(180,100,255,.15)|#c47aff&amp;#039;,&lt;br /&gt;
    &amp;#039;Culture, History &amp;amp; Politics&amp;#039;:&amp;#039;rgba(100,160,255,.15)|#64a0ff&amp;#039;,&lt;br /&gt;
    &amp;#039;Fashion &amp;amp; Visual Signaling&amp;#039;:&amp;#039;rgba(255,220,100,.15)|#ffd664&amp;#039;,&lt;br /&gt;
    &amp;#039;Community &amp;amp; Identity&amp;#039;:&amp;#039;rgba(61,220,132,.15)|#3ddc84&amp;#039;,&lt;br /&gt;
    &amp;#039;Drugs, Party Culture &amp;amp; Harm Reduction&amp;#039;:&amp;#039;rgba(255,120,50,.15)|#ff7832&amp;#039;,&lt;br /&gt;
    &amp;#039;Life Planning&amp;#039;:&amp;#039;rgba(100,200,255,.15)|#64c8ff&amp;#039;&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
  function catStyle(cat){&lt;br /&gt;
    var s=CAT_COLORS[cat]||&amp;#039;rgba(150,150,150,.15)|#888&amp;#039;;&lt;br /&gt;
    var p=s.split(&amp;#039;|&amp;#039;);&lt;br /&gt;
    return &amp;#039;background:&amp;#039;+p[0]+&amp;#039;;color:&amp;#039;+p[1]+&amp;#039;;border:1px solid &amp;#039;+p[1].replace(&amp;#039;)&amp;#039;,&amp;#039;, .3)&amp;#039;).replace(&amp;#039;rgb&amp;#039;,&amp;#039;rgba&amp;#039;)+&amp;#039;;&amp;#039;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function wordStatus(w){&lt;br /&gt;
    if(w&amp;lt;200)return[&amp;#039;stub&amp;#039;,&amp;#039;Stub&amp;#039;];&lt;br /&gt;
    if(w&amp;lt;600)return[&amp;#039;short&amp;#039;,&amp;#039;Short&amp;#039;];&lt;br /&gt;
    if(w&amp;lt;1500)return[&amp;#039;medium&amp;#039;,&amp;#039;Medium&amp;#039;];&lt;br /&gt;
    return[&amp;#039;long&amp;#039;,&amp;#039;Long&amp;#039;];&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function fmtDate(iso){&lt;br /&gt;
    if(!iso)return&amp;#039;—&amp;#039;;&lt;br /&gt;
    var d=new Date(iso);&lt;br /&gt;
    return d.toLocaleDateString(&amp;#039;en-GB&amp;#039;,{day:&amp;#039;2-digit&amp;#039;,month:&amp;#039;short&amp;#039;,year:&amp;#039;numeric&amp;#039;});&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function fmtSize(bytes){&lt;br /&gt;
    if(!bytes)return&amp;#039;—&amp;#039;;&lt;br /&gt;
    return(bytes/1024).toFixed(1)+&amp;#039; KB&amp;#039;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function escHtml(s){&lt;br /&gt;
    return String(s).replace(/&amp;amp;/g,&amp;#039;&amp;amp;amp;&amp;#039;).replace(/&amp;lt;/g,&amp;#039;&amp;amp;lt;&amp;#039;).replace(/&amp;gt;/g,&amp;#039;&amp;amp;gt;&amp;#039;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  var allData=[];&lt;br /&gt;
  var sortCol=&amp;#039;title&amp;#039;;&lt;br /&gt;
  var sortDir=1;&lt;br /&gt;
  var filterText=&amp;#039;&amp;#039;;&lt;br /&gt;
  var filterCat=&amp;#039;&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
  function render(data){&lt;br /&gt;
    var filtered=data.filter(function(r){&lt;br /&gt;
      var matchText=!filterText||r.title.toLowerCase().indexOf(filterText)&amp;gt;=0||(r.cat||&amp;#039;&amp;#039;).toLowerCase().indexOf(filterText)&amp;gt;=0;&lt;br /&gt;
      var matchCat=!filterCat||r.cat===filterCat;&lt;br /&gt;
      return matchText&amp;amp;&amp;amp;matchCat;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    filtered.sort(function(a,b){&lt;br /&gt;
      var av=a[sortCol]||&amp;#039;&amp;#039;,bv=b[sortCol]||&amp;#039;&amp;#039;;&lt;br /&gt;
      if(typeof av===&amp;#039;number&amp;#039;&amp;amp;&amp;amp;typeof bv===&amp;#039;number&amp;#039;)return sortDir*(av-bv);&lt;br /&gt;
      return sortDir*String(av).localeCompare(String(bv));&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    var maxWords=Math.max.apply(null,filtered.map(function(r){return r.words||0;}));&lt;br /&gt;
&lt;br /&gt;
    // Stats&lt;br /&gt;
    var totalWords=filtered.reduce(function(s,r){return s+(r.words||0);},0);&lt;br /&gt;
    var avgWords=filtered.length?Math.round(totalWords/filtered.length):0;&lt;br /&gt;
    var totalRevs=filtered.reduce(function(s,r){return s+(r.revisions||0);},0);&lt;br /&gt;
&lt;br /&gt;
    // Build cats for dropdown&lt;br /&gt;
    var cats={};&lt;br /&gt;
    data.forEach(function(r){if(r.cat)cats[r.cat]=1;});&lt;br /&gt;
    var catList=Object.keys(cats).sort();&lt;br /&gt;
&lt;br /&gt;
    var html=&amp;#039;&amp;#039;;&lt;br /&gt;
    // Header&lt;br /&gt;
    html+=&amp;#039;&amp;lt;div class=&amp;quot;axcp-header&amp;quot;&amp;gt;&amp;#039;;&lt;br /&gt;
    html+=&amp;#039;&amp;lt;div class=&amp;quot;axcp-title&amp;quot;&amp;gt;&amp;amp;#9881; Admin Control Panel&amp;lt;/div&amp;gt;&amp;#039;;&lt;br /&gt;
    html+=&amp;#039;&amp;lt;div class=&amp;quot;axcp-subtitle&amp;quot;&amp;gt;AlphaX Wiki &amp;amp;mdash; Article Database &amp;amp;mdash; Live Data&amp;lt;/div&amp;gt;&amp;#039;;&lt;br /&gt;
    html+=&amp;#039;&amp;lt;div class=&amp;quot;axcp-stats-row&amp;quot;&amp;gt;&amp;#039;;&lt;br /&gt;
    html+=&amp;#039;&amp;lt;div class=&amp;quot;axcp-stat&amp;quot;&amp;gt;&amp;lt;div class=&amp;quot;axcp-stat-val&amp;quot;&amp;gt;&amp;#039;+filtered.length+&amp;#039;&amp;lt;/div&amp;gt;&amp;lt;div class=&amp;quot;axcp-stat-label&amp;quot;&amp;gt;Articles&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;#039;;&lt;br /&gt;
    html+=&amp;#039;&amp;lt;div class=&amp;quot;axcp-stat&amp;quot;&amp;gt;&amp;lt;div class=&amp;quot;axcp-stat-val&amp;quot;&amp;gt;&amp;#039;+avgWords.toLocaleString()+&amp;#039;&amp;lt;/div&amp;gt;&amp;lt;div class=&amp;quot;axcp-stat-label&amp;quot;&amp;gt;Avg Words&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;#039;;&lt;br /&gt;
    html+=&amp;#039;&amp;lt;div class=&amp;quot;axcp-stat&amp;quot;&amp;gt;&amp;lt;div class=&amp;quot;axcp-stat-val&amp;quot;&amp;gt;&amp;#039;+totalWords.toLocaleString()+&amp;#039;&amp;lt;/div&amp;gt;&amp;lt;div class=&amp;quot;axcp-stat-label&amp;quot;&amp;gt;Total Words&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;#039;;&lt;br /&gt;
    html+=&amp;#039;&amp;lt;div class=&amp;quot;axcp-stat&amp;quot;&amp;gt;&amp;lt;div class=&amp;quot;axcp-stat-val&amp;quot;&amp;gt;&amp;#039;+totalRevs.toLocaleString()+&amp;#039;&amp;lt;/div&amp;gt;&amp;lt;div class=&amp;quot;axcp-stat-label&amp;quot;&amp;gt;Total Revisions&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;#039;;&lt;br /&gt;
    html+=&amp;#039;&amp;lt;div class=&amp;quot;axcp-stat&amp;quot;&amp;gt;&amp;lt;div class=&amp;quot;axcp-stat-val&amp;quot;&amp;gt;&amp;#039;+catList.length+&amp;#039;&amp;lt;/div&amp;gt;&amp;lt;div class=&amp;quot;axcp-stat-label&amp;quot;&amp;gt;Categories&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;#039;;&lt;br /&gt;
    html+=&amp;#039;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
    // Controls&lt;br /&gt;
    html+=&amp;#039;&amp;lt;div class=&amp;quot;axcp-controls&amp;quot;&amp;gt;&amp;#039;;&lt;br /&gt;
    html+=&amp;#039;&amp;lt;input class=&amp;quot;axcp-search&amp;quot; id=&amp;quot;axcp-search&amp;quot; type=&amp;quot;text&amp;quot; placeholder=&amp;quot;&amp;amp;#128269; Search articles...&amp;quot; value=&amp;quot;&amp;#039;+escHtml(filterText)+&amp;#039;&amp;quot;&amp;gt;&amp;#039;;&lt;br /&gt;
    html+=&amp;#039;&amp;lt;select class=&amp;quot;axcp-select&amp;quot; id=&amp;quot;axcp-cat-filter&amp;quot;&amp;gt;&amp;lt;option value=&amp;quot;&amp;quot;&amp;gt;All Categories&amp;lt;/option&amp;gt;&amp;#039;;&lt;br /&gt;
    catList.forEach(function(c){html+=&amp;#039;&amp;lt;option value=&amp;quot;&amp;#039;+escHtml(c)+&amp;#039;&amp;quot;&amp;#039;+(filterCat===c?&amp;#039; selected&amp;#039;:&amp;#039;&amp;#039;)+&amp;#039;&amp;gt;&amp;#039;+escHtml(c)+&amp;#039;&amp;lt;/option&amp;gt;&amp;#039;;});&lt;br /&gt;
    html+=&amp;#039;&amp;lt;/select&amp;gt;&amp;#039;;&lt;br /&gt;
    html+=&amp;#039;&amp;lt;span class=&amp;quot;axcp-badge-count&amp;quot;&amp;gt;&amp;#039;+filtered.length+&amp;#039; articles&amp;lt;/span&amp;gt;&amp;#039;;&lt;br /&gt;
    html+=&amp;#039;&amp;lt;button class=&amp;quot;axcp-refresh&amp;quot; id=&amp;quot;axcp-reload&amp;quot;&amp;gt;&amp;amp;#8635; Refresh Data&amp;lt;/button&amp;gt;&amp;#039;;&lt;br /&gt;
    html+=&amp;#039;&amp;lt;/div&amp;gt;&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
    // Table&lt;br /&gt;
    html+=&amp;#039;&amp;lt;div class=&amp;quot;axcp-table-wrap&amp;quot;&amp;gt;&amp;lt;table class=&amp;quot;axcp-table&amp;quot;&amp;gt;&amp;#039;;&lt;br /&gt;
    html+=&amp;#039;&amp;lt;thead&amp;gt;&amp;lt;tr&amp;gt;&amp;#039;;&lt;br /&gt;
    var cols=[&lt;br /&gt;
      {key:&amp;#039;title&amp;#039;,label:&amp;#039;Article&amp;#039;},&lt;br /&gt;
      {key:&amp;#039;cat&amp;#039;,label:&amp;#039;Category&amp;#039;},&lt;br /&gt;
      {key:&amp;#039;subcat&amp;#039;,label:&amp;#039;Subcategory&amp;#039;},&lt;br /&gt;
      {key:&amp;#039;words&amp;#039;,label:&amp;#039;Words&amp;#039;},&lt;br /&gt;
      {key:&amp;#039;size&amp;#039;,label:&amp;#039;Size&amp;#039;},&lt;br /&gt;
      {key:&amp;#039;status&amp;#039;,label:&amp;#039;Status&amp;#039;},&lt;br /&gt;
      {key:&amp;#039;created&amp;#039;,label:&amp;#039;Created&amp;#039;},&lt;br /&gt;
      {key:&amp;#039;touched&amp;#039;,label:&amp;#039;Last Edited&amp;#039;},&lt;br /&gt;
      {key:&amp;#039;revisions&amp;#039;,label:&amp;#039;Revisions&amp;#039;},&lt;br /&gt;
      {key:&amp;#039;watchers&amp;#039;,label:&amp;#039;Watchers&amp;#039;},&lt;br /&gt;
      {key:&amp;#039;links&amp;#039;,label:&amp;#039;Inbound Links&amp;#039;}&lt;br /&gt;
    ];&lt;br /&gt;
    cols.forEach(function(c){&lt;br /&gt;
      var cls=sortCol===c.key?(sortDir===1?&amp;#039;sorted-asc&amp;#039;:&amp;#039;sorted-desc&amp;#039;):&amp;#039;&amp;#039;;&lt;br /&gt;
      html+=&amp;#039;&amp;lt;th class=&amp;quot;&amp;#039;+cls+&amp;#039;&amp;quot; data-col=&amp;quot;&amp;#039;+c.key+&amp;#039;&amp;quot;&amp;gt;&amp;#039;+c.label+&amp;#039;&amp;lt;/th&amp;gt;&amp;#039;;&lt;br /&gt;
    });&lt;br /&gt;
    html+=&amp;#039;&amp;lt;/tr&amp;gt;&amp;lt;/thead&amp;gt;&amp;lt;tbody&amp;gt;&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
    if(filtered.length===0){&lt;br /&gt;
      html+=&amp;#039;&amp;lt;tr&amp;gt;&amp;lt;td colspan=&amp;quot;11&amp;quot; style=&amp;quot;text-align:center;padding:40px;color:#666;&amp;quot;&amp;gt;No articles match your filters.&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;#039;;&lt;br /&gt;
    }&lt;br /&gt;
    filtered.forEach(function(r){&lt;br /&gt;
      var st=wordStatus(r.words||0);&lt;br /&gt;
      var barW=maxWords&amp;gt;0?Math.round(((r.words||0)/maxWords)*80):0;&lt;br /&gt;
      var cs=catStyle(r.cat||&amp;#039;&amp;#039;);&lt;br /&gt;
      html+=&amp;#039;&amp;lt;tr&amp;gt;&amp;#039;;&lt;br /&gt;
      html+=&amp;#039;&amp;lt;td&amp;gt;&amp;lt;a class=&amp;quot;axcp-title-link&amp;quot; href=&amp;quot;/wiki/&amp;#039;+encodeURIComponent((r.title||&amp;#039;&amp;#039;).replace(/ /g,&amp;#039;_&amp;#039;))+&amp;#039;&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;&amp;#039;+escHtml(r.title||&amp;#039;&amp;#039;)+&amp;#039;&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;&amp;#039;;&lt;br /&gt;
      html+=&amp;#039;&amp;lt;td&amp;gt;&amp;#039;+(r.cat?&amp;#039;&amp;lt;span class=&amp;quot;axcp-cat-badge&amp;quot; style=&amp;quot;&amp;#039;+cs+&amp;#039;&amp;quot;&amp;gt;&amp;#039;+escHtml(r.cat)+&amp;#039;&amp;lt;/span&amp;gt;&amp;#039;:&amp;#039;&amp;lt;span style=&amp;quot;color:#444&amp;quot;&amp;gt;—&amp;lt;/span&amp;gt;&amp;#039;)+&amp;#039;&amp;lt;/td&amp;gt;&amp;#039;;&lt;br /&gt;
      html+=&amp;#039;&amp;lt;td style=&amp;quot;color:#777;font-size:12px;&amp;quot;&amp;gt;&amp;#039;+escHtml(r.subcat||&amp;#039;—&amp;#039;)+&amp;#039;&amp;lt;/td&amp;gt;&amp;#039;;&lt;br /&gt;
      html+=&amp;#039;&amp;lt;td class=&amp;quot;axcp-num&amp;quot;&amp;gt;&amp;#039;+((r.words||0).toLocaleString())+&amp;#039;&amp;lt;span class=&amp;quot;axcp-bar-wrap&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;axcp-bar&amp;quot; style=&amp;quot;width:&amp;#039;+barW+&amp;#039;px&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/td&amp;gt;&amp;#039;;&lt;br /&gt;
      html+=&amp;#039;&amp;lt;td class=&amp;quot;axcp-num&amp;quot;&amp;gt;&amp;#039;+fmtSize(r.size)+&amp;#039;&amp;lt;/td&amp;gt;&amp;#039;;&lt;br /&gt;
      html+=&amp;#039;&amp;lt;td&amp;gt;&amp;lt;span class=&amp;quot;axcp-status status-&amp;#039;+st[0]+&amp;#039;&amp;quot;&amp;gt;&amp;#039;+st[1]+&amp;#039;&amp;lt;/span&amp;gt;&amp;lt;/td&amp;gt;&amp;#039;;&lt;br /&gt;
      html+=&amp;#039;&amp;lt;td style=&amp;quot;color:#777;white-space:nowrap;&amp;quot;&amp;gt;&amp;#039;+fmtDate(r.created)+&amp;#039;&amp;lt;/td&amp;gt;&amp;#039;;&lt;br /&gt;
      html+=&amp;#039;&amp;lt;td style=&amp;quot;color:#777;white-space:nowrap;&amp;quot;&amp;gt;&amp;#039;+fmtDate(r.touched)+&amp;#039;&amp;lt;/td&amp;gt;&amp;#039;;&lt;br /&gt;
      html+=&amp;#039;&amp;lt;td class=&amp;quot;axcp-num&amp;quot; style=&amp;quot;color:&amp;#039;+(r.revisions&amp;gt;10?&amp;#039;#FF6600&amp;#039;:&amp;#039;#777&amp;#039;)+&amp;#039;&amp;quot;&amp;gt;&amp;#039;+((r.revisions||0))+&amp;#039;&amp;lt;/td&amp;gt;&amp;#039;;&lt;br /&gt;
      html+=&amp;#039;&amp;lt;td class=&amp;quot;axcp-num&amp;quot; style=&amp;quot;color:&amp;#039;+(r.watchers&amp;gt;0?&amp;#039;#3ddc84&amp;#039;:&amp;#039;#444&amp;#039;)+&amp;#039;&amp;quot;&amp;gt;&amp;#039;+(r.watchers!=null?(r.watchers&amp;gt;0?&amp;#039;&amp;amp;#128065; &amp;#039;+r.watchers:&amp;#039;0&amp;#039;):&amp;#039;—&amp;#039;)+&amp;#039;&amp;lt;/td&amp;gt;&amp;#039;;&lt;br /&gt;
      html+=&amp;#039;&amp;lt;td class=&amp;quot;axcp-num&amp;quot;&amp;gt;&amp;#039;+((r.links||0))+&amp;#039;&amp;lt;/td&amp;gt;&amp;#039;;&lt;br /&gt;
      html+=&amp;#039;&amp;lt;/tr&amp;gt;&amp;#039;;&lt;br /&gt;
    });&lt;br /&gt;
    html+=&amp;#039;&amp;lt;/tbody&amp;gt;&amp;lt;/table&amp;gt;&amp;lt;/div&amp;gt;&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
    root.innerHTML=html;&lt;br /&gt;
&lt;br /&gt;
    // Bind events&lt;br /&gt;
    document.getElementById(&amp;#039;axcp-search&amp;#039;).addEventListener(&amp;#039;input&amp;#039;,function(){filterText=this.value.toLowerCase();render(allData);});&lt;br /&gt;
    document.getElementById(&amp;#039;axcp-cat-filter&amp;#039;).addEventListener(&amp;#039;change&amp;#039;,function(){filterCat=this.value;render(allData);});&lt;br /&gt;
    document.getElementById(&amp;#039;axcp-reload&amp;#039;).addEventListener(&amp;#039;click&amp;#039;,function(){loadData();});&lt;br /&gt;
    document.querySelectorAll(&amp;#039;table.axcp-table th&amp;#039;).forEach(function(th){&lt;br /&gt;
      th.addEventListener(&amp;#039;click&amp;#039;,function(){&lt;br /&gt;
        var col=this.getAttribute(&amp;#039;data-col&amp;#039;);&lt;br /&gt;
        if(sortCol===col){sortDir*=-1;}else{sortCol=col;sortDir=1;}&lt;br /&gt;
        render(allData);&lt;br /&gt;
      });&lt;br /&gt;
    });&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  async function loadData(){&lt;br /&gt;
    root.innerHTML=&amp;#039;&amp;lt;div class=&amp;quot;axcp-loading&amp;quot;&amp;gt;&amp;amp;#9881; Loading article data from API&amp;amp;hellip;&amp;lt;/div&amp;gt;&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
    try{&lt;br /&gt;
      // Step 1: get all article page IDs + basic info&lt;br /&gt;
      var pages=[];&lt;br /&gt;
      var apcontinue=null;&lt;br /&gt;
      do{&lt;br /&gt;
        var url=&amp;#039;/api.php?action=query&amp;amp;list=allpages&amp;amp;apnamespace=0&amp;amp;aplimit=500&amp;amp;format=json&amp;#039;;&lt;br /&gt;
        if(apcontinue)url+=&amp;#039;&amp;amp;apcontinue=&amp;#039;+encodeURIComponent(apcontinue);&lt;br /&gt;
        var r=await fetch(url);&lt;br /&gt;
        var d=await r.json();&lt;br /&gt;
        pages=pages.concat(d.query.allpages);&lt;br /&gt;
        apcontinue=d.continue?d.continue.apcontinue:null;&lt;br /&gt;
      }while(apcontinue);&lt;br /&gt;
&lt;br /&gt;
      // Step 2: batch fetch page props (size, touched, lastrevid, categories) in chunks of 50&lt;br /&gt;
      var map={};&lt;br /&gt;
      pages.forEach(function(p){map[p.pageid]={title:p.title,cat:&amp;#039;&amp;#039;,subcat:&amp;#039;&amp;#039;,words:0,size:0,created:&amp;#039;&amp;#039;,touched:&amp;#039;&amp;#039;,revisions:0,watchers:null,links:0};});&lt;br /&gt;
&lt;br /&gt;
      var ids=pages.map(function(p){return p.pageid;});&lt;br /&gt;
      for(var i=0;i&amp;lt;ids.length;i+=50){&lt;br /&gt;
        var chunk=ids.slice(i,i+50).join(&amp;#039;|&amp;#039;);&lt;br /&gt;
        var r2=await fetch(&amp;#039;/api.php?action=query&amp;amp;pageids=&amp;#039;+chunk+&amp;#039;&amp;amp;prop=info|categories|revisions&amp;amp;inprop=watchers&amp;amp;rvprop=size|timestamp&amp;amp;rvdir=newer&amp;amp;rvlimit=1&amp;amp;cllimit=10&amp;amp;format=json&amp;#039;);&lt;br /&gt;
        var d2=await r2.json();&lt;br /&gt;
        Object.keys(d2.query.pages).forEach(function(pid){&lt;br /&gt;
          var pg=d2.query.pages[pid];&lt;br /&gt;
          if(!map[pid])return;&lt;br /&gt;
          map[pid].size=pg.length||0;&lt;br /&gt;
          map[pid].touched=pg.touched||&amp;#039;&amp;#039;;&lt;br /&gt;
          map[pid].watchers=pg.watchers!=null?pg.watchers:null;&lt;br /&gt;
          // categories&lt;br /&gt;
          if(pg.categories){&lt;br /&gt;
            pg.categories.forEach(function(c){&lt;br /&gt;
              var cn=c.title.replace(&amp;#039;Category:&amp;#039;,&amp;#039;&amp;#039;);&lt;br /&gt;
              var knownCats=[&amp;#039;Sexual Health&amp;#039;,&amp;#039;Dating, Sex &amp;amp; Relationships&amp;#039;,&amp;#039;Kink &amp;amp; BDSM&amp;#039;,&amp;#039;Culture, History &amp;amp; Politics&amp;#039;,&amp;#039;Fashion &amp;amp; Visual Signaling&amp;#039;,&amp;#039;Community &amp;amp; Identity&amp;#039;,&amp;#039;Drugs, Party Culture &amp;amp; Harm Reduction&amp;#039;,&amp;#039;Life Planning&amp;#039;];&lt;br /&gt;
              if(knownCats.indexOf(cn)&amp;gt;=0){&lt;br /&gt;
                if(!map[pid].cat)map[pid].cat=cn;&lt;br /&gt;
              }else if(!cn.startsWith(&amp;#039;Pages&amp;#039;) &amp;amp;&amp;amp; !cn.startsWith(&amp;#039;Articles&amp;#039;)){&lt;br /&gt;
                if(!map[pid].subcat)map[pid].subcat=cn;&lt;br /&gt;
              }&lt;br /&gt;
            });&lt;br /&gt;
          }&lt;br /&gt;
          // creation date from first revision&lt;br /&gt;
          if(pg.revisions&amp;amp;&amp;amp;pg.revisions[0])map[pid].created=pg.revisions[0].timestamp||&amp;#039;&amp;#039;;&lt;br /&gt;
        });&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // Step 3: get revision counts and word counts via separate calls&lt;br /&gt;
      for(var j=0;j&amp;lt;ids.length;j+=50){&lt;br /&gt;
        var chunk2=ids.slice(j,j+50).join(&amp;#039;|&amp;#039;);&lt;br /&gt;
        // revision count via revisions prop count&lt;br /&gt;
        var r3=await fetch(&amp;#039;/api.php?action=query&amp;amp;pageids=&amp;#039;+chunk2+&amp;#039;&amp;amp;prop=revisions&amp;amp;rvprop=ids&amp;amp;rvlimit=max&amp;amp;format=json&amp;#039;);&lt;br /&gt;
        var d3=await r3.json();&lt;br /&gt;
        Object.keys(d3.query.pages).forEach(function(pid){&lt;br /&gt;
          var pg=d3.query.pages[pid];&lt;br /&gt;
          if(!map[pid])return;&lt;br /&gt;
          map[pid].revisions=(pg.revisions||[]).length;&lt;br /&gt;
        });&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // Step 4: get wikitext word counts (batch extracts)&lt;br /&gt;
      for(var k=0;k&amp;lt;ids.length;k+=20){&lt;br /&gt;
        var chunk3=ids.slice(k,k+20).join(&amp;#039;|&amp;#039;);&lt;br /&gt;
        var r4=await fetch(&amp;#039;/api.php?action=query&amp;amp;pageids=&amp;#039;+chunk3+&amp;#039;&amp;amp;prop=revisions&amp;amp;rvprop=content&amp;amp;rvslots=main&amp;amp;format=json&amp;#039;);&lt;br /&gt;
        var d4=await r4.json();&lt;br /&gt;
        Object.keys(d4.query.pages).forEach(function(pid){&lt;br /&gt;
          var pg=d4.query.pages[pid];&lt;br /&gt;
          if(!map[pid]||!pg.revisions||!pg.revisions[0])return;&lt;br /&gt;
          var content=pg.revisions[0].slots?pg.revisions[0].slots.main[&amp;#039;*&amp;#039;]:(pg.revisions[0][&amp;#039;*&amp;#039;]||&amp;#039;&amp;#039;);&lt;br /&gt;
          // Strip wiki markup&lt;br /&gt;
          var clean=content&lt;br /&gt;
            .replace(/&amp;lt;!--[sS]*?--&amp;gt;/g,&amp;#039;&amp;#039;)&lt;br /&gt;
            .replace(/&amp;lt;[^&amp;gt;]+&amp;gt;/g,&amp;#039; &amp;#039;)&lt;br /&gt;
            .replace(/[[File:[^]]+]]/gi,&amp;#039;&amp;#039;)&lt;br /&gt;
            .replace(/[[([^]|]+|)?([^]]+)]]/g,&amp;#039;$2&amp;#039;)&lt;br /&gt;
            .replace(/{{[^}]+}}/g,&amp;#039;&amp;#039;)&lt;br /&gt;
            .replace(/={2,}[^=]+=={2,}/g,&amp;#039; &amp;#039;)&lt;br /&gt;
            .replace(/[*#:;|!]/g,&amp;#039; &amp;#039;)&lt;br /&gt;
            .replace(/https?://S+/g,&amp;#039;&amp;#039;)&lt;br /&gt;
            .replace(/s+/g,&amp;#039; &amp;#039;).trim();&lt;br /&gt;
          map[pid].words=clean?clean.split(/s+/).filter(function(w){return w.length&amp;gt;0;}).length:0;&lt;br /&gt;
        });&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      // Step 5: inbound links count&lt;br /&gt;
      for(var l=0;l&amp;lt;ids.length;l+=50){&lt;br /&gt;
        var chunk4=ids.slice(l,l+50).join(&amp;#039;|&amp;#039;);&lt;br /&gt;
        var r5=await fetch(&amp;#039;/api.php?action=query&amp;amp;pageids=&amp;#039;+chunk4+&amp;#039;&amp;amp;prop=linkshere&amp;amp;lhnamespace=0&amp;amp;lhlimit=max&amp;amp;format=json&amp;#039;);&lt;br /&gt;
        var d5=await r5.json();&lt;br /&gt;
        Object.keys(d5.query.pages).forEach(function(pid){&lt;br /&gt;
          var pg=d5.query.pages[pid];&lt;br /&gt;
          if(!map[pid])return;&lt;br /&gt;
          map[pid].links=(pg.linkshere||[]).length;&lt;br /&gt;
        });&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      allData=Object.values(map);&lt;br /&gt;
      render(allData);&lt;br /&gt;
&lt;br /&gt;
    }catch(e){&lt;br /&gt;
      root.innerHTML=&amp;#039;&amp;lt;div class=&amp;quot;axcp-error&amp;quot;&amp;gt;&amp;amp;#9888; Error loading data: &amp;#039;+e.message+&amp;#039;&amp;lt;/div&amp;gt;&amp;#039;;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  loadData();&lt;br /&gt;
})();&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
</feed>