Модуль:Tables

Версия от 23:15, 2 января 2022; imported>Putnik (порежем пробелы по краям)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)

Для документации этого модуля может быть создана страница Модуль:Tables/doc

 local p = {}

-- **********************************************************
-- Вызов через шаблон {{НумерацияТаблицы}}
-- Заменяет число в первой ячейке на номер строки
function p.AutoNumBox2(frame)
 
    local g = frame:getParent().args[1]
    local NumStr = tonumber (frame:getParent().args['Старт'] or "1");
    if g == nil then return "Нет данных" end
    g = g:gsub(".*{|(.*)|}.*", "%1")
    local Titul = g:sub(1, (g:find ("\n!") or 1) - 1)
    g = g:sub((g:find ("\n!") or 1))
    g = g:gsub("||", "\n|")
    local Pos0 = 0
    while g:find("|%-[^|]*(|[^\n]*\n)", Pos0 + 1) ~= nil do
        Pos1, Pos2 = g:find("|%-[^|]*(|[^\n]*\n)", Pos0 + 1)
        while g:find("|", Pos1 + 1) ~= nil and g:find("|", Pos1 + 1) < Pos2 do
            Pos1 = g:find("|", Pos1 + 1)
        end
        if g:find("%d", Pos1) ~= nil and g:find("%d", Pos1) < Pos2 then
            Pos3, Pos4 = g:find("%d+", Pos1)
            g = g:sub(1, Pos3 - 1)..NumStr..g:sub(Pos4 + 1)
            NumStr = NumStr + 1
        end
        Pos0 = Pos2
    end
    return "{|"..Titul..g.."|}"
end

-- **********************************************************
-- Вызов напрямую
-- Заменяет символ # в первой ячейке на номер строки
function p.AutoNumBox ( frame )
    local NumStr = tonumber (frame.args['Старт'] or "1");
    local g = frame.args[1]
    g = g:gsub("^%s- -{{", "", 1)
    g = g:gsub("}}%s- -$", "", 1)
    pattern = "|%s*#%s*%s*|"
    while string.find (g, pattern) ~= nil do
        g = g:gsub(pattern, "|"..NumStr.."\n".."|", 1)
        NumStr = NumStr + 1
    end
    return g
end

-- **********************************************************
function p.AutoNum ( frame )
    local args = frame.args;
    local Style = (frame.args['Оформление'] or "standard");
    local Column = tonumber (frame.args['Столбцов'] or "0");
    local NumStr = tonumber (frame.args['Старт'] or "1");
    local Title0 = (frame.args['Заголовок0'] or "№")
    local Titles = {}
    for i = 1, Column do
        Titles[i] =(frame.args["Заголовок"..i] or "Заголовок"..i)
    end
    local Width0 = (frame.args['Ширина0']);
    local Widths = {}
    for i = 1, Column do
        Widths[i] =(frame.args["Ширина"..i])
    end
    local Align0 = (frame.args['Выравнивание0'] or "center")
    local Aligns = {}
    for i = 1, Column do
        Aligns[i] =(frame.args["Выравнивание"..i] or "left")
    end

    local g="<table class = '"..Style.."'>"
    
-- Строка заголовков
    g = g.."<tr>"

---- Заголовок столба с номерами строк
    g = g.."<th scope='col'"; if Width0 ~= nil then g = g.." width='"..Width0.."'" end; g = g..">"
    g = g..Title0.."</th>"

---- Остальные заголовки
    for i = 1, Column do
        g = g.."<th scope='col'"; if Widths[i] ~= nil then g = g.." width='"..Widths[i].."'" end; g = g..">"
        g = g..Titles[i].."</th>"
    end
    g = g.."</tr>"
    
-- Строки данных
    J = 1
    while args[(J-1)*Column+1] ~= nil do
        g = g.."<tr><td style='text-align:"..Align0.."'>"..NumStr.."</td>"
        for i = 1, Column do
             if args[(J-1)*Column+i] == nil then
                g = g.."<td></td>"
            else
                g = g.."<td style='text-align:"..Aligns[i].."'>"..args[(J-1)*Column+i].."</td>"
             end
        end
        g = g.."</tr>"
        NumStr = NumStr + 1
        J = J + 1
    end

    g = g.."</table>"
    return g
end

-- **********************************************************
function p.AutoNumSort(frame)

    local args = frame:getParent().args
    local Column = tonumber(args['Столбцов'] or "0")
        if Column == 0 then return "Невозможно определить количество столбцов" end
    local TempSort = (args['Сортировка'] or "0")
    local SortColumn = tonumber(string.match(TempSort, "%d*")) or 0
        if SortColumn > Column then SortColumn = 0 end
    local SortAsNumber = string.match(TempSort, "#") ~= nil
    local SortDescend
        if SortAsNumber
        then SortDescend = string.find(TempSort, "<") == nil
        else SortDescend = string.find(TempSort, ">") ~= nil end

    local Strings={}
    local NumCell = 0

    while args[NumCell + 1] ~= nil or NumCell%Column ~= 0 do
        NumCell = NumCell + 1
    	if (args[NumCell] == nil) then args[NumCell]="" end
    	-- NumCell%Column==0 значит строка сформирована
    	if NumCell%Column == 0 then
    		local TempString = {NumCell-Column+1}
            if SortAsNumber then
                KeyCell=args[TempString[1]+SortColumn-1]
				KeyCell=mw.ustring.gsub(KeyCell, "<span[^>]+>","")
				KeyCell=mw.ustring.gsub(KeyCell, ",",".")
				KeyCell=mw.ustring.gsub(KeyCell, " ","")
				KeyCell=mw.ustring.gsub(KeyCell, "&nbsp;","")
				KeyCell=mw.ustring.gsub(KeyCell, "%s","")
				KeyCell=mw.ustring.match(KeyCell, "^%D*(%d+%.?%d*)") or ""
	            TempString.Key=tonumber(KeyCell)
            elseif SortColumn > 1 then
                TempString.Key = (args[TempString[1]+SortColumn-1] or "")
                -- Возможность сортировки по скрытому ключу, например через шаблон {{~}}
                TempString.Key = mw.ustring.gsub(TempString.Key, '<span[^>]+>', "")
                -- Сортировка ё как е
                TempString.Key = mw.ustring.gsub(TempString.Key, "ё", "е")
                TempString.Key = mw.ustring.gsub(TempString.Key, "Ё", "Е")
                -- trim
                TempString.Key = mw.ustring.gsub(TempString.Key, "^%s*(.-)%s*$", "%1")
            else TempString.Key = tonumber(TempString[1]) end
            TempString.Group = mw.ustring.gsub(args[TempString[1]], "[^a-zA-Zа-яА-Я0-9]", "")
            table.insert(Strings, TempString)
        end
    end

    local function SortString(a, b)
        if a.Group ~= b.Group then return a.Group < b.Group end
        if SortDescend then a, b = b, a end
        if SortAsNumber or (SortColumn < 2) then
            return a.Key < b.Key
        else
            local LenA = mw.ustring.len(a.Key)
            local LenB = mw.ustring.len(b.Key)
            for i = 1, (LenA < LenB) and LenA or LenB do
                if mw.ustring.codepoint(a.Key, i, i) ~= mw.ustring.codepoint(b.Key, i, i) then
                    return mw.ustring.codepoint(a.Key, i, i) < mw.ustring.codepoint(b.Key, i, i)
                end
            end
            return LenA < LenB
        end
    end

-- Сортировка строк по группам и ключу
    table.sort(Strings, SortString)

--  Формироание HTML-таблицы
    local HTML = mw.html.create('table')

    HTML:attr('class', (args['Оформление'] or "standard"))
    
    if args['Ручное оформление']~=('' or nil) then
    	HTML:attr('style', args['Ручное оформление'])
    end

--  Название таблицы
    if args['Название'] then
		TempCaption=HTML:tag('th')
			:wikitext(args['Название'])
			:attr('colspan', Column)
			:attr('scope', 'colgroup')
    end

--  Строка заголовков
    local TempRow
    TempRow = HTML:tag('tr')
    TempHeader=TempRow:tag('th'):attr('scope', 'col')
    if args["Ширина1"] then  TempHeader:css('width', (args["Ширина1"])) end
    TempHeader:wikitext(args['Заголовок1'] or "№")
    
    for i = 2, Column do
        TempColumn=TempRow:tag('th'):attr('scope', 'col')
        if args["Ширина"..i] then TempColumn:css('width', (args["Ширина"..i])) end
        TempColumn:wikitext(args["Заголовок"..i] or "Заголовок"..i)
		if args["Сортировка"..i]=="без сортировки" then
			TempColumn:addClass('unsortable')
		elseif args["Сортировка"..i]=="число" then
			TempColumn:attr('data-sort-type', 'number')
		elseif args["Сортировка"..i]=="дата" then
			TempColumn:attr('data-sort-type', 'date')
		end
	end

--  Строки данных
    local HideNum = 0
	local NumStr = tonumber (args['Старт'] or "1") - 1
    local Backlight = (args['Подсветка'] or "class='bright'"):gsub("\"", "'")
	for Index, TempString in pairs(Strings) do
        TempRow = HTML:tag('tr')
        local first = args[TempString[1]]

--      Стиль оформления строк
        if string.find(first, "%$") ~= nil then TempRow:attr('class', 'shadow')
        elseif string.find(first, "%%") ~= nil then TempRow:attr('class', 'bright')
        elseif string.find(first, "@") ~= nil then TempRow:attr('class', 'dark')
        elseif string.find(first, "%+") ~= nil then
            for Part in string.gmatch(Backlight, "[%w]*=%s*'[^']*'") do
                TempRow:attr(string.match(Part, "([^=]*)="), string.match(Part, "'([^']*)'"))
            end
        end
        if string.find(first, "!") ~= nil then TempRow:attr('style', 'font-weight:bold') end

--      Вывод номера строки
        if string.find(first, "-") ~= nil then
            HideNum = HideNum + 0.000001
            TempRow:tag('td')
                :tag('span')
                :attr('style', 'display: none; speak: none;')
                :wikitext( tonumber(NumStr + HideNum))
        else
            NumStr = NumStr + 1
            TempRow:tag('td')
                :css('text-align', (args['Выравнивание1'] or "center") )
                :wikitext(tonumber(NumStr))
        end
--      Вывод ячеек строки
		for i = 2, Column do
            TempTd=TempRow:tag('td')
            KeyCell=""
			if args["Сортировка"..i]=="число" then
				KeyCell=mw.ustring.gsub(args[TempString[1]+i-1], ",",".")
				KeyCell=mw.ustring.gsub(KeyCell, "&nbsp;","")
				KeyCell=mw.ustring.gsub(KeyCell, "<span[^>]+>","")
				KeyCell=mw.ustring.gsub(KeyCell, "%s","")
				KeyCell=mw.ustring.match(KeyCell, "^%D*(%d+%.?%d*)") or ""
	            TempTd:attr('data-sort-value', KeyCell)
			end
            TempTd:wikitext( mw.text.trim( args[TempString[1] + i - 1] ) )
            if args["Выравнивание"..i] and args["Выравнивание"..i] ~= "left" then
	            TempTd:css('text-align', args["Выравнивание"..i])
            end
		end
	end
    return tostring(HTML)
end

-- **********************************************************
function p.DataOutput(frame)
	
	local args = frame:getParent().args
	local Tab = args.tab
	local NumColumns = tonumber (args['Столбцов'] or "9");
	local Titul = args['Заголовок'] or "";
	local Reverse = args['Реверс'] ~= nil
    local Style = args['Оформление'] or "standard";

	local function FormatF(Number)
		local lang = mw.language.getContentLanguage()
		return lang:formatNum(tonumber(Number))
	end
 
	local function FormatT(NewRecord, OldRecord)    
		if OldRecord == nil then
			return ""
		elseif NewRecord > OldRecord then 
			if Reverse then
            	return "<span style='color: red; font-weight:bold; font-size: larger;'>↗</span>"  
            else
            	return "<span style='color: #0c0; font-weight:bold; font-size: larger;'>↗</span>"
			end
		elseif NewRecord < OldRecord then
			if Reverse then
            	return "<span style='color: #0c0; font-weight:bold; font-size: larger;'>↘</span>" 
            else
	            return "<span style='color: red; font-weight:bold; font-size: larger;'>↘</span>"  
			end
        else
            return "<span style='color:#0AF; font-weight:bold;'>→</span>"  
        end
	end

    local k, v
    local NumData = 0
    for k, v in pairs( args ) do
    	if type(k) ~= 'string' then
	        NumData = NumData + 1
		end
    end -- for k, v
    NumData = NumData / 2
    if NumData < NumColumns then
    	NumColumns = NumData 
    end
    
--  Формирование HTML-таблицы
    local HTML = mw.html.create('table')
    HTML:attr('class', Style) 

    local TempRow
    local NumRecord
    local OldRecord 
    local NewRecord
    if Titul then
    	TempRow = HTML:tag('th'):attr('scope', 'colgroup'):attr('colspan', NumColumns):wikitext(Titul)
    end
    for i = 1, math.ceil(NumData / NumColumns) do
        TempRow = HTML:tag('tr'):addClass("bright")
        for j = 1, NumColumns do
			NumRecord = ((i - 1) * NumColumns + j) * 2 - 1 
            if args[NumRecord] == nil then
                TempRow:tag('th'):attr('scope', 'col'):wikitext("")
            else
                TempRow:tag('th'):attr('scope', 'col'):wikitext(args[NumRecord])
            end
        end

        TempRow = HTML:tag('tr'):css('text-align', 'center')
        for j = 1, NumColumns do
			NumRecord = ((i - 1) * NumColumns + j ) * 2 
            if type(tonumber(args[NumRecord])) ~= "number" then
                TempRow:tag('td'):wikitext(args[NumRecord])
                OldRecord = nil
            else
            	NewRecord = tonumber(args[NumRecord])
                TempRow:tag('td'):wikitext(FormatT(NewRecord, OldRecord) .. FormatF(NewRecord))
                OldRecord = NewRecord
            end
        end
    end            

	return tostring(HTML)
end	

-- **********************************************************
function p.DataOutput2(frame)
	
	local args = frame:getParent().args
	local NumColumns
	if type(tonumber(args['Столбцов'])) == "number" then
		NumColumns = tonumber(args['Столбцов'])
	else
		NumColumns = 9
	end
	local Titul = args['Заголовок'] or '';
	local Format = args['Формат'] or 'Таблица';
	local Reverse = args['Реверс'] ~= nil
    local Style = args['Оформление'] or 'standard';

	local function FormatF(Number)
		local lang = mw.language.getContentLanguage()
		return lang:formatNum(tonumber(Number))
	end
 
	local function FormatT(NewRecord, OldRecord)    
		if OldRecord == nil then
			return ""
		elseif NewRecord > OldRecord then 
			if Reverse then
            	return "<span style='color: red; font-weight:bold; font-size: larger;'>↗</span>"  
            else
            	return "<span style='color: #0c0; font-weight:bold; font-size: larger;'>↗</span>"
			end
		elseif NewRecord < OldRecord then
			if Reverse then
            	return "<span style='color: #0c0; font-weight:bold; font-size: larger;'>↘</span>" 
            else
	            return "<span style='color: red; font-weight:bold; font-size: larger;'>↘</span>"  
			end
        else
            return "<span style='color:#0AF; font-weight:bold;'>→</span>"  
        end
	end

    local NumData = 0
	while args[(NumData + 1) * 3 - 2] ~= nil do
		NumData = NumData + 1
	end

    if NumData < NumColumns then
    	NumColumns = NumData 
    end

	if Format == 'г' or Format == 'Год' then
		return args[NumData * 3 - 2]
	elseif Format == 'ч' or Format == 'Безформат' or Format == 'Число' then
		return args[NumData * 3 - 1]
	elseif Format == 'с' or Format == 'Ссылка' then
		return args[NumData * 3]
	elseif Format == 'ф' or Format == 'Формат' then
		return FormatF(args[NumData * 3 -1])
	elseif Format == 'фс' or Format == 'ФорматСсылка' then
		return FormatF(args[NumData * 3 -1]) .. args[NumData * 3]
	elseif Format == 'фсг' or Format == 'ФорматСсылкаГод' then
		return FormatF(args[NumData * 3 -1]) .. args[NumData * 3] .. ' (' ..  args[NumData * 3 - 2] .. ')'
	elseif Format == 'т' or Format == 'Тренд' then
		return FormatT(args[NumData * 3 - 1], args[NumData * 3 - 4]) .. FormatF(args[NumData * 3 - 1])
	elseif Format == 'тс' or Format == 'Значение' or Format == 'ТрендСсылка' then
		return FormatT(args[NumData * 3 - 1], args[NumData * 3 - 4]) .. FormatF(args[NumData * 3 - 1]) .. args[NumData * 3]
	elseif Format == 'тсг' or Format == 'ТрендСсылкаГод' then
		return FormatT(args[NumData * 3 - 1], args[NumData * 3 - 4]) .. FormatF(args[NumData * 3 - 1]) .. args[NumData * 3] .. ' (' ..  args[NumData * 3 - 2] .. ')'
	else
--  Формирование HTML-таблицы
	    local HTML = mw.html.create('table')
	    HTML:attr('class', Style) 
	
	    local TempRow
	    local NumRecord
	    local OldRecord 
	    local NewRecord
	    if Titul then
	    	TempRow = HTML:tag('th'):attr('scope', 'colgroup'):attr('colspan', NumColumns):wikitext(Titul)
	    end
	    for i = 1, math.ceil(NumData / NumColumns) do
	        TempRow = HTML:tag('tr'):addClass("bright")
	        for j = 1, NumColumns do
				NumRecord = ((i - 1) * NumColumns + j) * 3 - 2 
	            if args[NumRecord] == nil then
	                TempRow:tag('th'):attr('scope', 'col'):wikitext("")
	            else
	                TempRow:tag('th'):attr('scope', 'col'):wikitext(args[NumRecord]..(args[NumRecord+2] or ""))
	            end
	        end
	
	        TempRow = HTML:tag('tr'):css('text-align', 'center')
	        for j = 1, NumColumns do
				NumRecord = ((i - 1) * NumColumns + j ) * 3 - 1
	            if type(tonumber(args[NumRecord])) ~= "number" then
	                TempRow:tag('td'):wikitext(args[NumRecord])
	                OldRecord = nil
	            else
	            	NewRecord = tonumber(args[NumRecord])
	                TempRow:tag('td'):wikitext(FormatT(NewRecord, OldRecord) .. FormatF(NewRecord))
	                OldRecord = NewRecord
	            end
	        end
	    end            
	    return tostring(HTML)
	end
end	

return p