Участник:Arbnos/Написание статей/Модуль:Category

-- Модуль для работы с категориями. Пока всё через хитрые хаки. local M={} local rcmtab = {all="^(%d+):",categories="(%d+) кат.",pages="(%d+) с.",files="(%d+) ф."};

local function gelement(a,b,c)-- Итератор

   -- NB! В будущем в список возврата, возможно, войдёт ключ сортировки,
   -- а в параметры — от какого элемента начинать.
   local n,m,nss=a,b,c;
   if type(n)=='table' then
       n=a.name;
       m=a.mode or m or 'all';
       nss=a.namespaces or nss
   end
   local cc = mw.text.unstrip(
       mw.getCurrentFrame():extensionTag(
           'categorytree',  n,
           {mode = m, hideroot='on', hideprefix='always', namespaces = nss, showcount='on'}
       )
   )
   local func, static, var =
       cc:gmatch('<a%s[^>]-class%s?=[^>]-CategoryTreeLabelNs(%d+)[^>]->%s*([^<>]-)%s*</a>()');
   return function(st,va)
       local ns,g,f = func(st,va);
       local all,cats,pgs,files;
       if ns=='14' then
           local mpatt = cc:match("^[^<>]*<span[^>]*>%(([^<>]+)%)",f) or ;-- не работает при mode=parents
           all,cats,pgs,files =
               mpatt:match(rcmtab.all), mpatt:match(rcmtab.categories),
               mpatt:match(rcmtab.pages), mpatt:match(rcmtab.files)
       end
       return g,tonumber(ns),all,cats,pgs,files
   end, static, var

end

M.gelement=gelement

function M.content(f)

   local r = {};
   for g,ns,all,cats,pgs,files
   in gelement(f.args['name'] or f.args[1], f.args['mode'] or 'all', f.args['namespaces'])
   do table.insert(r,{g,ns,all,cats,pgs,files}) end
   if f.args['sort'] then--сортируем по шаблону, {{{sortdel}}} = вырезать элемент
       if f.args['sort']==']' then --сортировка в обратном порядке
           local t,c ={}, #r+1;
           for i,v in ipairs(r) do
               t[c-i] = v
           end
           r = t
       else
           local cmp,t,e,m,h =
            require('Module:String')._strcmp,{},nil,f.args['sort']:match('^([<>]?)%s*(.*)');
           if h~= then
               for k,v in ipairs(r) do
                   e = f:expandTemplate{
                       title = h, args = {v[1], v[2], f.args['name'] or f.args[1],f.args['sortarg'],
                         all=v[3], categories=v[4], pages=v[5], files=v[6]} 
                   };
                   if e ~= f.args.sortdel then table.insert(t, {v,e}) end
               end
               table.sort( t, m=='>' and function(a,b) return cmp(b[2],a[2])<0 end
                                     or  function(a,b) return cmp(a[2],b[2])<0 end )
               r = {}
               for k, v in pairs(t) do r[k] = v[1] end
           else
               table.sort( r, m=='>' and function(a,b) return cmp(b[1],a[1])<0 end
                                     or  function(a,b) return cmp(a[1],b[1])<0 end )
           end
       end
   end
   if f.args['t'] then --передаём в шаблон
       for k,v in pairs(r) do
           r[k] = f:expandTemplate{
               title = f.args['t'],
               args = {v[1], v[2], f.args['name'] or f.args[1],f.args['targ'],
                   all=v[3], categories=v[4], pages=v[5], files=v[6]
               } 
           }
       end
   else --форматируем в строку
      for k,v in pairs(r) do
           r[k] = mw.message.newRawMessage(f.args.format or [==[
$2}}]==]
           	):rawParams(mw.site.namespaces[v[2]].name,v[1],v[3] or ,v[3] and table.concat{
                   (v[4] and (f.args.fccategories or "%i кат."):format(v[4]) or (v[5] or v[6]) and (f.args.fcsep or ', ') or ),
                   (v[5] and (f.args.fcpages or "%i с."):format(v[5]) .. (v[6] and (f.args.fcsep or ', ')) or ),
                   v[6] and (f.args.fcfiles or "%i ф."):format(v[6]) or 
               } or ,v[2]
           ):plain()
       end
   end
   return table.concat(r, f.args['j'] or '\n')

end

local function Supercats(n)

   -- NB! Когда-нибудь может появиться параметр количества
   local cc, res = mw.text.unstrip( mw.getCurrentFrame():extensionTag( 
       'categorytree', n, {mode = 'parents',hideroot = 'on'}
   ) ), {};
   for cat in cc:gmatch("<a%s[^>]*>%s*(.-)%s*</a>") do table.insert(res,cat) end
   return res

end

M.Supercats = Supercats;

function M.supercats(f)

   local r = Supercats(f.args.name or f.args[1]);
   if f.args['sort'] then--сортируем по шаблону, {{{sortdel}}} = вырезать элемент
       if f.args['sort']==']' then --сортировка в обратном порядке
           local t,c ={}, #r+1;
           for i,v in ipairs(r) do
               t[c-i] = v
           end
           r = t
       else
           cmp,m,h =
            require('Module:String')._strcmp,f.args['sort']:match('^([<>]?)%s*(.*)');
           if h~= then
               local t,e = {}
               for k,v in ipairs(r) do
                   e = f:expandTemplate{
                           title = h, args = {v, f.args['name'] or f.args[1],f.args['sortarg']} 
                   };
                   if e ~= f.args.sortdel then table.insert(t, {v,e}) end
               end
               table.sort( t, m=='>' and function(a,b) return cmp(b[2], a[2])<0 end
                                     or  function(a,b) return cmp(a[2], b[2])<0 end )
               r = {}
               for k, v in pairs(t) do r[k] = v[1] end
           else
               table.sort( r, m=='>' and function(a,b) return cmp(b, a)<0 end
                                     or  function(a,b) return cmp(a, b)<0 end )
           end
       end
   end
   if f.args['t'] then --передаём в шаблон
       for k,v in pairs(r) do
           r[k] = f:expandTemplate{
               title = f.args['t'],
               args = {v, f.args['name'] or f.args[1], f.args['targ']} 
           }
       end
   else --форматируем в строку
      for k,v in pairs(r) do
           r[k] = mw.message.newRawMessage(f.args['format'] or ": $1")
           :rawParams(v):plain()
       end
   end
   return table.concat(r, f.args['j'] or '\n')

end

return M