Модуль:CenturyMetaCat
Модуль используется для навигиции и категоризации категорий по векам (для категорий с заголовком, включающим «<римские цифры> век/века/веке»).
- Определяет век и эру (до н.э / н.э.).
- Создаёт навигационную линейку по векам.
- Корректно работает с веками до нашей эры.
- Добавляет категории.
Использование[править код]
{{#invoke:CenturyMetaCat|main |Мир в <век> веке |Мир <тысячелетие>-го тысячелетия! <ключ> |Мир по векам! <ключ> }}
<век>
— век римскими цифрами без слова «век»<тысячелетие>
— тысячелетие числом (без окончания -е/-м/-го)<ключ>
— ключ сортировки, н. э. — номер века числом, до н. э. — отрицательное число начиная с -99 (-99 == I век до н. э. -98 == II век до н. э. и т. д.); нужен для корректной сортировки в категориях
Полная версия
{{#invoke:CenturyMetaCat|main |Категория 1![ключ сортировки]![диапазон веков от]![диапазон веков до] ... |Категория N[...] |min = до какого века рисовать линейку слева, по умолчанию -39 (0 — рисовать только века нашей эры) |max = до какого века рисовать линейку справа, по умолчанию 21 |range = сколько веков в линейке слева и справа, по умолчанию 5 |title = заголовок страницы, используемый вместо текущего (для тестов) }}
Категории[править код]
Категория состоит из 4-х полей, разделенных !
(восклицательным знаком):
- первое — название категории
- второе — ключ сортировки (необязательно)
- третье — начиная с какого века добавлять категорию (необязательно)
- четвертое — каким веком заканчивать добавление категории (необязательно)
Примеры:
|Мир по векам! <ключ>
— добавлять категорию «Мир по векам» с ключом сортировки <пробел><ключ>|Графы Средних веков!<ключ>!5!15
— добавлять категорию «Графы Средних веков» в категории с V по XV века|Книги в общественном достоянии!<ключ>!!19
— добавлять категорию «Книги в общественном достоянии» во все категории до XIX века включительно
Есть эмпирическое правило: в категории обязательно должен быть или <век> (в названии), или <ключ> (в ключе сортировки), но не оба.
Другие опции[править код]
|min = до какого века рисовать линейку слева, по умолчанию -39 (0 — рисовать только века нашей эры) |max = до какого века рисовать линейку справа, по умолчанию 21 |range = сколько веков в линейке слева и справа, по умолчанию 5 |title = заголовок страницы, используемый вместо текущего (для тестов)
Дополнительные функции[править код]
expand[править код]
- заменяет
<век>
на текущий, по необходимости добавив «до н. э.» - заменяет
<тысячелетие>
на текущее, по необходимости добавив «до н. э.» - заменяет
<ключ>
на ключ сортировки
Пример:
{{#invoke:CenturyMetaCat|expand|Мир в <век> веке}}
на странице «К:Земля I века до н. э.» вернёт:
Мир в I веке до н. э.
century_from_title[править код]
Возвращает век из заголовка числом, для веков до н.э. с минусом.
См. также[править код]
- Модуль:YearMetaCat — аналог для годов и десятилетий
- Модуль:YearMetaCat2 — аналог для годов
- Модуль:DecadeMetaCat — аналог для десятилетий
- Модуль:MetaCatDoc — для документирования шаблонов, использующих этот модуль
---*- mode: lua; coding: utf-8; -*-
local p = {}
-- константы
local ROMAN = {
I = 1,
IV = 4,
V = 5,
IX = 9,
X = 10,
--XL = 40,
--L = 50,
}
-- переменные
local cent -- век, положительное число
local roman_cent -- век римскими цифрами
local BC -- 0 == н.э. 1 == до н.э.
local templ -- строка-шаблон вида 'Мир в %s веке%s'
local title = mw.title.getCurrentTitle().text
-- опции
local cent_min -- число, по умолчанию -39, 0 == только н.э.
local cent_max -- число, по умолчанию 21 (XXI век)
local range = 5
-- экспортируемые функции
local getArgs = require('Module:Arguments').getArgs
local sparseIpairs = require('Module:TableTools').sparseIpairs
local toroman = require('Module:Roman').convert
local gsub = mw.ustring.gsub
function roman_to_int(s)
local i = 1
local num = 0
while i <= s:len() do
local c
if i < s:len() then
c = ROMAN[s:sub(i, i+1)]
end
if c then
num = num + c
i = i + 2
else
num = num + ROMAN[s:sub(i, i)]
i = i + 1
end
end
return num
end
local function get_templ(s)
-- формируем строку-шаблон вида:
-- 'Мир в XI веке до н. э.' -> 'Мир в %s веке%s'
-- определяем BC
local t
t, BC = gsub(s, '[IVX]+ (век[еа]?) до н%. э%.', '%%s %1%%s')
local n = BC
if BC ~= 1 then
t, n = gsub(s, '[IVX]+ (век[еа]?)', '%%s %1%%s')
end
if n ~= 1 then
-- не найдено или найдено больше одного
error('Век не найден')
end
-- в/во, о/об
t = gsub(t, 'во %%s веке', 'в %%s веке')
templ = gsub(t, 'об %%s веке', 'о %%s веке')
end
local function get_cent(t)
_, _, roman_cent = mw.ustring.find(t, '([IVX]+) век')
if not roman_cent then error('век не найден') end
cent = roman_to_int(roman_cent)
end
local function format(c, wiki)
local bcs, t
if c < 1 then
c = 1 - c
bcs = ' до н. э.'
--t = toroman(c)..' до н. э.'
t = '-'..toroman(c)
else
bcs = ''
t = toroman(c)
end
local s
if wiki then
-- в/во, о/об
local tt = templ
if c == 2 then
tt = gsub(tt, 'в %%s веке', 'во %%s веке')
end
if c == 11 then
tt = gsub(tt, 'о %%s веке', 'об %%s веке')
end
s = string.format(tt, toroman(c), bcs)
s = string.format('[[:Категория:%s|%s]]', s, t)
else
s = t
end
return s
end
local function navbox()
local c
c = cent
if BC == 1 then
-- пропускаем 0
-- I до н.э. c == 0, II до н.э. c == -1 и т.д.
c = 1 - cent
end
local wt = mw.html.create('table'):addClass('standard'):attr('align', 'center')
local row = wt:tag('tr')
local cstart
if cent_min < 1 then
cstart = math.max(cent_min+1, c - range)
else
cstart = math.max(cent_min, c - range)
end
local cend = math.min(cent_max, c + range) -- FIXME: до н.э.
for i = cstart, cend do
if i == 1 and i ~= cstart then row:tag('th'):wikitext('') end -- разд. до н.э./н.э.
if i == c then
row:tag('th'):wikitext(format(i, false))
else
row:tag('td'):wikitext(format(i, true))
end
end
return tostring(wt)
end
local function do_expand(s)
-- <век> - век римскими цифрами без слова "век" (XVII)
-- <тысячелетие> - тысячелетие числом (без добавления -е/-м/-го)
-- <ключ> - ключ сортировки, н.э. - номер века числом,
-- до н.э. - отрицательное число начиная с -99 (-99 == I век до н.э. -98 == II век до н.э. и т.д.)
local mil = math.floor((cent-1)/10)+1 -- тысячелетие
-- в/во, о/об ?
if mil == 2 then
s = gsub(s, ' в <тысячелетие>', ' во <тысячелетие>')
end
if BC == 1 then
s = gsub(s, '<век> (век[еа]?)', roman_cent .. ' %1 до н. э.')
s = gsub(s, '<тысячелетие>(-[емг][о]? тысячелети[еия])', mil..'%1 до н. э.') -- 2-е/2-м/2-го
s = gsub(s, '<ключ>', cent-100)
else
s = gsub(s, '<век>', roman_cent)
s = gsub(s, '<тысячелетие>', mil)
s = gsub(s, '<ключ>', cent)
end
return s
end
local function cats(args)
local c, t
local ret = ''
for _, c in sparseIpairs(args) do
t = mw.text.split(c, '!', true)
-- диапазон веков для кат.
local cmin = -99
if t[3] and t[3] ~= '' then
cmin = tonumber(t[3])
end
local cmax = 99
if t[4] and t[4] ~= '' then
cmax = tonumber(t[4])
end
local cc = cent
if BC == 1 then cc = -cent end
if cc >= cmin and cc <= cmax then
-- в/во, о/об
local tt = t[1]
if cent == 2 then
tt = gsub(tt, 'в <век> веке', 'во <век> веке')
end
if cent == 11 then
tt = gsub(tt, 'о <век> веке', 'об <век> веке')
end
if t[2] and t[2] ~= '' then
ret = ret .. string.format('[[Категория:%s|%s]]', tt, t[2])
else
ret = ret .. string.format('[[Категория:%s]]', tt)
end
end
end
return do_expand(ret)
end
function p.main(frame)
local args = getArgs(frame)
title = args['title'] or title
-- разбор аргументов
range = tonumber(args['range'] or 5)
cent_min = tonumber(args['min'] or -39)
cent_max = tonumber(args['max'] or 21)
-- нахождение текушего века
get_cent(title)
-- создание шаблона-строки
get_templ(title)
-- создание навбокса и категорий
return navbox(title) .. cats(args)
end
function p.expand(frame)
local args = getArgs(frame)
title = args['title'] or title
get_cent(title)
BC = mw.ustring.find(title, '[IVX]+ век[еа]? до н%. э%.')
if BC then
BC = 1
else
BC = 0
end
-- в/во, о/об
local tt = args[1]
if cent == 2 then
tt = gsub(args[1], 'в <век> веке', 'во <век> веке')
end
if cent == 11 then
tt = gsub(tt, 'о <век> веке', 'об <век> веке')
end
return do_expand(tt)
end
function p.century_from_title(frame)
local args = getArgs(frame)
title = args['title'] or title
BC = mw.ustring.find(title, '[IVX]+ век[еа]? до н%. э%.')
get_cent(title)
if BC then
return -cent
end
return cent
end
return p