Модуль:Песочница/Vavilexxx/Индекс категории

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску
Документация
require('strict')

local getArgs = require('Модуль:Arguments').getArgs
local yesno = require('Модуль:Yesno')

local p = {}

--------------------------------------------------------------------------------
-- COSTANTS
--------------------------------------------------------------------------------

local TS_PAGE = 'Модуль:Песочница/Vavilexxx/Индекс категории/styles.css'  -- 'Модуль:Индекс категории/песочница/styles.css'

local LISTS = {
{list = {'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ж', 'З', 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ы', 'Э', 'Ю', 'Я'}, depth = 0},
{list = {'Абу', 'Бар', 'Ван', 'Гам', 'Дар', 'Евл', 'Жан', 'Зай', 'Иве', 'Йем', 'Кан', 'Лал', 'Мак', 'Най', 'Обу', 'Пас', 'Рай', 'Сан', 'Так', 'Уде', 'Фак', 'Хак', 'Цар', 'Чар', 'Шап', 'Щед', 'Ыгд', 'Эвр', 'Юди', 'Ягу'}, depth = 3},
{list = {'Ада', 'Без', 'Вве', 'Гек', 'Дел', 'Его', 'Жев', 'Зан', 'Идо', 'Йес', 'Кас', 'Лас', 'Мар', 'Нат', 'Ожи', 'Пер', 'Рац', 'Сев', 'Тва', 'Уим', 'Фед', 'Хар', 'Цви', 'Чел', 'Шва', 'Щеп', 'Ыйв', 'Эйф', 'Юли', 'Яко'}, depth = 2},
{list = {'Акт', 'Бер', 'Вес', 'Геф', 'Дец', 'Ежо', 'Жен', 'Зах', 'Ико', 'Йис', 'Ким', 'Лег', 'Мау', 'Ней', 'Оку', 'Пис', 'Рел', 'Сет', 'Тер', 'Улм', 'Фид', 'Хат', 'Цен', 'Чер', 'Шен', 'Щер', 'Ыйр', 'Экт', 'Юнг', 'Яку'}, depth = 3},
{list = {'Алт', 'Бит', 'Вин', 'Гно', 'Дин', 'Ели', 'Жиг', 'Зее', 'Имп', 'Йон', 'Кож', 'Леп', 'Мер', 'Нет', 'Опо', 'Плу', 'Рич', 'Ско', 'Тих', 'Уни', 'Фин', 'Хим', 'Цер', 'Чес', 'Шин', 'Щит', 'Ылг', 'Эли', 'Юри', 'Ямб'}, depth = 1},
{list = {'Анд', 'Бол', 'Вла', 'Гон', 'Дов', 'Епи', 'Жир', 'Зен', 'Инт', 'Йоп', 'Кон', 'Лин', 'Мим', 'Нил', 'Орн', 'Пор', 'Рой', 'Сод', 'Топ', 'Урб', 'Фок', 'Хок', 'Циг', 'Чиж', 'Шма', 'Щук', 'Ымс', 'Энг', 'Юрк', 'Яно'}, depth = 3},
{list = {'Апп', 'Боя', 'Вок', 'Гра', 'Дор', 'Еро', 'Жуа', 'Зин', 'Иос', 'Йос', 'Кра', 'Лов', 'Мож', 'Нов', 'Осл', 'Пре', 'Рот', 'Спе', 'Три', 'Урю', 'Фоф', 'Хоп', 'Цин', 'Чка', 'Шта', 'Щуч', 'Ысп', 'Эпо', 'Юрь', 'Яро'}, depth = 2},
{list = {'Арх', 'Бул', 'Вос', 'Гру', 'Дув', 'Ест', 'Жуп', 'Зом', 'Исм', 'Йот', 'Кря', 'Лук', 'Мот', 'Ном', 'Отк', 'Пуг', 'Рут', 'Стр', 'Тум', 'Утр', 'Фро', 'Хре', 'Цна', 'Чум', 'Шув', 'Щёг', 'Ыты', 'Эсс', 'Юсу', 'Яст'}, depth = 3},
}

local DIGRAPHS = {
{'Ав', 'Бв', 'Вв', 'Гв', 'Дв', 'Ев', 'Жв', 'Зв', 'Ив', 'Йв', 'Кв', 'Лв', 'Мв', 'Нв', 'Ов', 'Пв', 'Рв', 'Св', 'Тв', 'Ув', 'Фв', 'Хв', 'Цв', 'Чв', 'Шв', 'Щв', 'Ыв', 'Эв', 'Юв', 'Яв'},
{'Ад', 'Бд', 'Вд', 'Гд', 'Дд', 'Ед', 'Жд', 'Зд', 'Ид', 'Йд', 'Кд', 'Лд', 'Мд', 'Нд', 'Од', 'Пд', 'Рд', 'Сд', 'Тд', 'Уд', 'Фд', 'Хд', 'Цд', 'Чд', 'Шд', 'Щд', 'Ыд', 'Эд', 'Юд', 'Яд'},
{'Аж', 'Бж', 'Вж', 'Гж', 'Дж', 'Еж', 'Жж', 'Зж', 'Иж', 'Йж', 'Кж', 'Лж', 'Мж', 'Нж', 'Ож', 'Пж', 'Рж', 'Сж', 'Тж', 'Уж', 'Фж', 'Хж', 'Цж', 'Чж', 'Шж', 'Щж', 'Ыж', 'Эж', 'Юж', 'Яж'},
{'Аи', 'Би', 'Ви', 'Ги', 'Ди', 'Еи', 'Жи', 'Зи', 'Ии', 'Йи', 'Ки', 'Ли', 'Ми', 'Ни', 'Ои', 'Пи', 'Ри', 'Си', 'Ти', 'Уи', 'Фи', 'Хи', 'Ци', 'Чи', 'Ши', 'Щи', 'Ыж', 'Эи', 'Юи', 'Яи'},
{'Ал', 'Бл', 'Вл', 'Гл', 'Дл', 'Ел', 'Жл', 'Зл', 'Ил', 'Йл', 'Кл', 'Лл', 'Мл', 'Нл', 'Ол', 'Пл', 'Рл', 'Сл', 'Тл', 'Ул', 'Фл', 'Хл', 'Цл', 'Чл', 'Шл', 'Щл', 'Ыл', 'Эл', 'Юл', 'Ял'},
{'Ан', 'Бн', 'Вн', 'Гн', 'Дн', 'Ен', 'Жн', 'Зн', 'Ин', 'Йн', 'Кн', 'Лн', 'Мн', 'Нн', 'Он', 'Пн', 'Рн', 'Сн', 'Тн', 'Ун', 'Фн', 'Хн', 'Цн', 'Чн', 'Шн', 'Щн', 'Ын', 'Эн', 'Юн', 'Ян'},
{'Ап', 'Бп', 'Вп', 'Гп', 'Дп', 'Еп', 'Жп', 'Зп', 'Ип', 'Йп', 'Кп', 'Лп', 'Мп', 'Нп', 'Оп', 'Пп', 'Рп', 'Сп', 'Тп', 'Уп', 'Фп', 'Хп', 'Цп', 'Чп', 'Шп', 'Щп', 'Ып', 'Эп', 'Юп', 'Яп'},
{'Ас', 'Бс', 'Вс', 'Гс', 'Дс', 'Ес', 'Жс', 'Зс', 'Ис', 'Йс', 'Кс', 'Лс', 'Мс', 'Нс', 'Ос', 'Пс', 'Рс', 'Сс', 'Тс', 'Ус', 'Фс', 'Хс', 'Цс', 'Чс', 'Шс', 'Щс', 'Ыс', 'Эс', 'Юс', 'Яс'},
{'Ау', 'Бу', 'Ву', 'Гу', 'Ду', 'Еу', 'Жу', 'Зу', 'Иу', 'Йу', 'Ку', 'Лу', 'Му', 'Ну', 'Оу', 'Пу', 'Ру', 'Су', 'Ту', 'Уу', 'Фу', 'Ху', 'Цу', 'Чу', 'Шу', 'Щу', 'Ыу', 'Эу', 'Юу', 'Яу'},
{'Ах', 'Бх', 'Вх', 'Гх', 'Дх', 'Ех', 'Жх', 'Зх', 'Их', 'Йх', 'Кх', 'Лх', 'Мх', 'Нх', 'Ох', 'Пх', 'Рх', 'Сх', 'Тх', 'Ух', 'Фх', 'Хх', 'Цх', 'Чх', 'Шх', 'Щх', 'Ых', 'Эх', 'Юх', 'Ях'},
{'Ач', 'Бч', 'Вч', 'Гч', 'Дч', 'Еч', 'Жч', 'Зч', 'Ич', 'Йч', 'Кч', 'Лч', 'Мч', 'Нч', 'Оч', 'Пч', 'Рч', 'Сч', 'Тч', 'Уч', 'Фч', 'Хч', 'Цч', 'Чч', 'Шч', 'Щч', 'Ыч', 'Эч', 'Юч', 'Яч'},
{'Ащ', 'Бщ', 'Вщ', 'Гщ', 'Дщ', 'Ещ', 'Жщ', 'Зщ', 'Ищ', 'Йщ', 'Кщ', 'Лщ', 'Мщ', 'Нщ', 'Ощ', 'Пщ', 'Рщ', 'Сщ', 'Тщ', 'Ущ', 'Фщ', 'Хщ', 'Цщ', 'Чщ', 'Шщ', 'Щщ', 'Ыщ', 'Эщ', 'Ющ', 'Ящ'},
{'Аю', 'Бю', 'Вю', 'Гю', 'Дю', 'Ею', 'Жю', 'Зю', 'Ию', 'Йю', 'Кю', 'Лю', 'Мю', 'Ню', 'Ою', 'Пю', 'Рю', 'Сю', 'Тю', 'Ую', 'Фю', 'Хю', 'Цю', 'Чю', 'Шю', 'Щю', 'Ыю', 'Эю', 'Юю', 'Яю'},
}

local CAPTION = 'Содержание'
local START = 'Начало'
-- local CAPTION = 'Оглавление'
-- local TO_START = '…в начало'
-- local BULL = '·'

--------------------------------------------------------------------------------
-- LOCAL FUNCTIONS
--------------------------------------------------------------------------------


local function bold(t)
	return '<b>' .. t .. '</b>'
end


local function link(name, text, params)
	return '[' .. tostring(mw.title.makeTitle('Category', name):fullUrl(params)) .. ' ' .. text .. ']'
end


local function check_letter(i, letter_10, letter_27)
	if i == 10 then return letter_10 end
	if i == 27 then return letter_27 end
	return true
end


local function yesno_from_arg_or_true(args, en, ru)
	local raw = args[en] or args[ru]
	if raw then
		return yesno(raw)
	end
	return true
end


local function add_styles(frame, content)
	local ts = frame:extensionTag{
		name = 'templatestyles',
		args = {src = TS_PAGE},
	}
	return ts .. tostring(content)
end


local function add_caption(pgname, tbl)
	local caption = tbl:tag('div')
		:addClass('ts-module-Индекс-категории-caption')
	caption:tag('span')
		:addClass('ts-module-Индекс-категории-caption-title')
		:wikitext(CAPTION)
	caption:tag('span')
		:addClass('ts-module-Индекс-категории-link-tostart')
		:wikitext(link(pgname, START, {}))
end


local function add_link(pgname, tbl, param, text, isclass)
	-- {from = v} type(param) ~= 'table' and {} or {from = param}
	tbl:tag('li')
		:addClass(isclass and 'ts-module-Индекс-категории-bullet')
		:wikitext(link(pgname, text or param, {from = param}))
		:done()
end


--------------------------------------------------------------------------------
-- MAIN CLASS
--------------------------------------------------------------------------------

-- Индекс категории с тремя буквами
function p.three_letters(frame)
	local args = getArgs(frame)
	local pagename = args.name or args['имя'] or mw.title.getCurrentTitle().text
	local class = args.class or args['класс']
	local result = mw.html.create('div')
		:attr('role', 'presentation')
		:addClass('ts-module-Индекс-категории')
		:addClass(class)
		add_caption(pagename, result)
	local letter_10 = yesno(args['Й'] or args['й'])
	local letter_27 = yesno(args['Ы'] or args['ы'])
	local depth = tonumber(args.depth or args['глубина'] or 0)
	local nocyr = yesno(args.nocyr or args['безкир'])
	local lat = (yesno(args.lat or args['лат']) or depth >= 3) and not yesno(args.nolat or args['безлат'])
	local smallat = yesno(args.smallat or args['маллат'])
	if not nocyr then
		if depth == 0 then
			local cyr_row = result:tag('div')
				:addClass('ts-module-Индекс-категории-container')
				:tag('ul')
					:addClass('ts-module-Индекс-категории-single-item') 
			for _, letter in ipairs(LISTS[1]['list']) do
				add_link(pagename, cyr_row, letter)
			end
		else
			local cyr_row = result:tag('div')
				:addClass('ts-module-Индекс-категории-container')
			for i, data in ipairs(LISTS[1]['list']) do
				if check_letter(i, letter_10, letter_27) then
					local list = cyr_row:tag('ul')
						:addClass('ts-module-Индекс-категории-multi-items')
					add_link(pagename, list, bold(data))
					for k, row in ipairs(LISTS) do
						if k ~= 1 and row.depth <= depth then
							add_link(pagename, list, row.list[i])
						end
					end
				end
			end
		end
	end
	local function latin_row(a, z)
		local charA = mw.ustring.codepoint(a)
		local charZ = mw.ustring.codepoint(z)
		local lat_row = result:tag('div')
			:addClass('ts-module-Индекс-категории-container')
			:tag('ul')
				:addClass('ts-module-Индекс-категории-single-item')
		for i = charA, charZ do
			add_link(pagename, lat_row, mw.ustring.char(i))
		end
	end
	if lat then
		latin_row('A', 'Z')
	end
	if smallat then
		latin_row('a', 'z')
	end
	return add_styles(frame, result)
end


-- Индекс категории с двумя буквами
function p.two_letters(frame)
	local args = getArgs(frame)
	local pagename = args.name or args['имя'] or mw.title.getCurrentTitle().text
	local class = args.class or args['класс']
	local result = mw.html.create('div')
		:attr('role', 'presentation')
		:addClass('ts-module-Индекс-категории')
		:addClass(class)
		add_caption(pagename, result)
	local letter_10 = yesno(args['Й'] or args['й'])
	local letter_27 = yesno(args['Ы'] or args['ы'])
	local use_digits = yesno(args['NN'] or args['числа'])
	local content = result:tag('div')
		:addClass('ts-module-Индекс-категории-container')
	if use_digits then
		local digits = content:tag('ul')
				:addClass('ts-module-Индекс-категории-multi-items')
		add_link(pagename, digits, '0', bold('0-9'))
		for i = 1, 9 do
			add_link(pagename, digits, tostring(i))
		end
	end
	for i, letter in ipairs(LISTS[1]['list']) do
		if check_letter(i, letter_10, letter_27) then
			local list = content:tag('ul')
				:addClass('ts-module-Индекс-категории-multi-items')
			add_link(pagename, list, bold(letter))
			for k, row in ipairs(DIGRAPHS) do
				if check_letter(i, letter_10, letter_27) then
					add_link(pagename, list, row[i])
				end
			end
		end
	end
	return add_styles(frame, result)
end


-- Индекс категории только с кириллицей
function p.only_cyrillic(frame)
	local args = getArgs(frame)
	local pagename = args.name or args['имя'] or mw.title.getCurrentTitle().text
	local class = args.class or args['класс']
	local result = mw.html.create('div')
		:attr('role', 'presentation')
		:addClass('ts-module-Индекс-категории')
		:addClass(class)
		add_caption(pagename, result)
	local letter_10 = yesno(args['Й'] or args['й'])
	local letter_27 = yesno(args['Ы'] or args['ы'])
	local row = result:tag('ul')
		:addClass('ts-module-Индекс-категории-single-item')
	-- add_link(pagename, row, nil, START, true)
	for i, letter in ipairs(LISTS[1]['list']) do
		if check_letter(i, letter_10, letter_27) then
			add_link(pagename, row, letter)
		end
	end
	return add_styles(frame, result)
end


-- Индекс категории только с числами
function p.only_numbers(frame)
	local args = getArgs(frame)
	local pagename = args.name or args['имя'] or mw.title.getCurrentTitle().text
	local class = args.class or args['класс']
	local result = mw.html.create('div')
		:attr('role', 'presentation')
		:addClass('ts-module-Индекс-категории')
		:addClass(class)
		add_caption(pagename, result)
	local step = tonumber(args.step or args['шаг'] or 100)
	local max_val = tonumber(args.max or args['макс'] or 1000)
	local use_letters = yesno(args.letters or args['А'] or args['A']) -- любая - русская А или английская A
	local row = result:tag('ul')
		:addClass('ts-module-Индекс-категории-single-item')
	-- add_link(pagename, row, nil, START, true)
	local isclass
	local i = 0
	repeat
		if  use_letters and i == max_val then isclass = true end
		add_link(pagename, row, tostring(i), nil, isclass)
		i = i + step
	until i > max_val
	if use_letters then
		add_link(pagename, row, 'А')
	end
	return add_styles(frame, result)
end


-- Индекс категории в одну строку
function p.single_line(frame)
	local args = getArgs(frame)
	local pagename = args.name or args['имя'] or mw.title.getCurrentTitle().text
	local num = mw.site.stats.pagesInCategory(pagename)
	local force = yesno(args.force or args['всегда'])
	if not force and num <= 200 then
		-- 200 страниц и так умещаются на одном экране
		return ''
	end
	local use_digit = yesno_from_arg_or_true(args, 'numerals', 'числа')
	local use_cyr = yesno_from_arg_or_true(args, 'up', 'кир')
	local use_lat = yesno_from_arg_or_true(args, 'up-lat', 'лат')
	local class = args.class or args['класс']
	local result = mw.html.create('div')
		:addClass('ts-module-Индекс-категории')
		:addClass(class)
	local row = result:tag('ul')
		:addClass('ts-module-Индекс-категории-single-line')
	add_link(pagename, row, nil, START, true)
	local isclass
	if use_digit then
		if use_cyr or use_lat then isclass = true end
		add_link(pagename, row, '0', '0-9', isclass)
	end
	isclass = nil
	-- латинские имена параметров из совместимости, рекомендуется использовать кириллические
	if use_cyr then
		for _, letter in ipairs(LISTS[1]['list']) do
			if letter == 'Я' and use_lat then isclass = true end
			add_link(pagename, row, letter, nil, isclass)
		end
	end
	if use_lat then
		local charA = mw.ustring.codepoint('A')
		local charZ = mw.ustring.codepoint('Z')
		for i = charA, charZ do
			add_link(pagename, row, mw.ustring.char(i))
		end
	end
	return add_styles(frame, result)
end


-- Индекс категории настраиваемый
function p.custom(frame)
	local args = getArgs(frame)
	local pagename = args.name or args['имя'] or mw.title.getCurrentTitle().text
	local class = args.class or args['класс']
	local use_cyr = yesno(args.cyr or args['кир'])
	local use_lat = yesno(args.lat or args['лат'])
	local result = mw.html.create('div')
		:addClass('ts-module-Индекс-категории')
		:addClass(class)
	local row = result:tag('ul')
		:addClass('ts-module-Индекс-категории-single-item')
	-- add_link(pgname, tbl, param, text, isclass)
	add_link(pagename, row, nil, START, true)
	local n = require('Module:TableTools').length(args)
	local isclass
	for i = 1, n do
		if i == n and (use_cyr or use_lat) then isclass = true end
		add_link(pagename, row, args[i], nil, isclass)
	end
	isclass = nil
	if yesno(args.cyr or args['кир']) then
		for _, letter in ipairs(LISTS[1]['list']) do
			if letter == 'Я' and use_lat then isclass = true end
			add_link(pagename, row, letter, nil, isclass)
		end
	end
	if yesno(args.lat or args['лат']) then
		local charA = mw.ustring.codepoint('A')
		local charZ = mw.ustring.codepoint('Z')
		for i = charA, charZ do
			add_link(pagename, row, mw.ustring.char(i))
		end
	end
	return add_styles(frame, result)
end


-- Индекс категории по годам
function p.years(frame)
	local args = getArgs(frame)
	local pagename = args.name or args['имя'] or mw.title.getCurrentTitle().text
	local min_val = tonumber(args.min or args['мин'] or -1000)
	local max_val = tonumber(args.max or args['макс'] or 2000)
	local step = tonumber(args.step or args['шаг'] or 200)
	local bc_step = tonumber(args.bcstep or args['шаг до н. э.'] or 200)
	local prefix = args.prefix or args['префикс'] or '*'
	local use_letters = yesno(args.letters or args['А'] or args['A']) -- любая - русская А или английская A
	local class = args.class or args['класс']
	local result = mw.html.create('div')
		:addClass('ts-module-Индекс-категории')
		:addClass(class)
		add_caption(pagename, result)
	local row = result:tag('ul')
		:addClass('ts-module-Индекс-категории-single-item')
	-- add_link(pgname, tbl, param, text, isclass)
	-- add_link(pagename, row, nil, START, true)
	local isclass
	local i = min_val
	repeat
		if i == max_val and use_letters then isclass = true end
		if i < 0 then
			add_link(pagename, row, prefix .. tostring(-10000-i), tostring(i), isclass)
			i = i + bc_step
		else
			add_link(pagename, row, prefix .. tostring(i), tostring(i), isclass)
			i = i + step
		end
	until i > max_val
	if use_letters then
		add_link(pagename, row, 'А')
	end
	return add_styles(frame, result)
end

return p