Модуль:Header

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

Назначение

В модуле собраны преимущественно функции, предназначенные для использования в шаблонах заголовка ({{Отексте}} и его производных).

Для энциклопедий и словарей используется Модуль:Отексте.

Функции, доступные из вики-разметки

beed()

Описание
Возвращает заполненный модифицированный шаблон Отексте в виде, требуемом для статей ЭСБЕ. Вызывается исключительно из шаблона {{ЭСБЕ}}, который служит оберткой для этой функции.
Использование
{{#invoke:Header|beed|name=|quality=|disambig=|pages=|section=|w=|s=|commons=|q=|n=|wikt=|b=|species=|data=|voyage=|search=|eebe=|nes=|mesbe=|bean=|el=|beyu=|resb=|bse1=|rbs=|te1=|te2=|tsd=|pbe=|ve=|britannica=|adb=|dnb=|je=|nsrw=}}
Параметры
  • name = значение параметра НАЗВАНИЕ из шаблона;
  • quality = значение параметра КАЧЕСТВО;
  • disambig = значение параметра НЕОДНОЗНАЧНОСТЬ;
  • pages = значение параметра СТРАНИЦЫ (если присутствует), иначе 1
  • section = значение параметра СЕКЦИЯ;
  • w = значение параметра ВИКИПЕДИЯ (с префиксом Special:Search/)
  • s = значение параметра ВИКИТЕКА;
  • commons = значение параметра ВИКИСКЛАД;
  • q = значение параметра ВИКИЦИТАТНИК;
  • n = значение параметра ВИКИНОВОСТИ;
  • wikt = значение параметра ВИКИСЛОВАРЬ;
  • b = значение параметра ВИКИУЧЕБНИК;
  • species = значение параметра ВИКИВИДЫ;
  • data = значение параметра ВИКИДАННЫЕ;
  • voyage = значение параметра ВИКИГИД;
  • search = значение параметра НАЗВАНИЕ;
  • eebe = значение параметра ЕЭБЕ;
  • nes = значение параметра НЭС;
  • mesbe = значение параметра МЭСБЕ;
  • bean = значение параметра БЭАН;
  • el = значение параметра ЭЛ;
  • beyu = значение параметра БЭЮ;
  • resb = значение параметра РЭСБ;
  • bse1 = значение параметра БСЭ1;
  • rbs = значение параметра РБС;
  • te1 = значение параметра ТЭ1;
  • te2 = значение параметра ТЭ2;
  • tsd = значение параметра ТСД;
  • pbe = значение параметра ПБЭ;
  • ve = значение параметра ВЭ;
  • britannica = значение параметра Британника;
  • adb = значение параметра ADB;
  • dnb = значение параметра DNB;
  • je = значение параметра JE;
  • nsrw = значение параметра NSRW;
Примеры

title()

next()

previous()

safetitle()

subnav()

beedScan()

pagenum()

wordlist()

parseTitle()

editionsList()

fixarrowlink()

linkify()

test()

Функции, доступные из других модулей

parse_title()

local p = {}

local currtitle = mw.title.getCurrentTitle()
local currname = currtitle["text"]
local currlist = currtitle["rootText"]
local beed = require ('Module:BEED')
local issub = false 						-- Для p.subnav()

-- helper
-- проверка переменной, возврат её или nil если пустая
function is(var)
	if (var == '' or var == nil) then return nil  else return var end
end

function p.beed (frame)
	local args = frame.args
	local t = currname or ""
	local title, b_old_spell, new_style, prefix, n, n2
	t = mw.text.split (t, "/")
	-- Разбор имени статьи: ЭСБЕ/<title>[/<part>/...][/ДО]
	if t[1] ~= 'ЭСБЕ' then
		return
	end
	if t[2] == "ДО" or t[2] == "ВТ" then
		title = t[3]
		b_old_spell = (t[2] == "ДО")	-- Если имя статьи начинается на "ЭСБЕ/ДО/"
		new_style = true
		n2 = word_list (nil, nil, "А:83 Г:84 Кош:85 Прусс:86")
		prefix = frame:preprocess ('Энциклопедический словарь Брокгауза и Ефрона/{{ЕДО|ДО|ВТ}}/Словник')
	else
		title = t[2]
		b_old_spell = (t[#t] == "ДО")	-- Если имя статьи оканчивается на "/ДО"
	end
	-- Параметр НАЗВАНИЕ
	local name = args.name
	if name == '' or name == nil then
		name = title
	end
	-- Параметр СЕКЦИЯ
	local section = args.section
	if section == '' or section == nil then
		section = title
	end
	-- Ключ сортировки для {{DEFAULTSORT:}}
	local lang = mw.language.new ('ru')
	local key = lang:ucfirst ( name )
	local firstletter = lang:uc ( mw.ustring.sub ( key, 1, 1 ) )
	-- Ищем месторасположение статьи в сканах
	-- в основных томах:
	local b1 = p.beedScan (frame, 1)  -- том/страница
	local d1 = nil					  -- файл_djvu/страница
	if b1 then 
		if b1:find ( "%d+/%d+" ) then
			d1 = beed.djvu (b1)
		end
	end
	-- в дополнительных томах:
	local b2 = p.beedScan (frame, 2)  -- том/страница
	if new_style then b2 = p.beedScan (frame, 1, prefix .. '/' .. n2) end
	local d2 = nil					  -- файл_djvu/страница
	if b2 then
		if b2:find ( "%d+/%d+" ) then
			d2 = beed.djvu (b2)
		end
	end
	-- навигационные ссылки и категории
	local previous, next, subnav, wordlist, categories, contents
	if new_style then
		n = word_list ()
		if b_old_spell then
			if args.name == '' or args.name == nil then name = p.title (frame, prefix .. '/' .. n ) end
			categories = '[[Категория:ЭСБЕ:Дореформенная орфография]][[Категория:ЭСБЕ:ДО:' .. firstletter .. ']]'
			if args.pages ~= 'нет' then contents = '\n' .. beed.transclude ( frame, b1, b2, section, b_old_spell) else contents = '' end
		else
			categories = '[[Категория:ЭСБЕ]][[Категория:ЭСБЕ:' .. firstletter .. ']]'
			if args.pages ~= '' then contents = '\n' .. beed.transclude ( frame, b1, b2, section, b_old_spell) else contents = '' end
		end
		if b1 and b2 then
			subnav = frame:expandTemplate { title = 'ЭСБЕ/списки', args = { n2 } }
			subnav = p.subnav (frame, '[[' .. prefix .. '/' .. n2 .. '|' .. subnav .. ']]' )
		end
		wordlist = frame:preprocess ( '[[' .. prefix .. '|Список{{ЕДО|ъ}} статей ЭСБЕ]]&#x3a;&nbsp;' )
		wordlist = wordlist .. '[[' .. prefix .. '/' .. n .. '|' .. frame:expandTemplate { title = 'ЭСБЕ/списки', args = { n } } .. ']]. '
		previous = p.previous ( frame, prefix .. '/' .. n )
		next = p.next ( frame, prefix .. '/' .. n )
	else
		if b_old_spell then
			wordlist = '[[Викитека:Проект:ЭСБЕ/Словник/ДО|Списокъ статей ЭСБЕ]]&#x3a;&nbsp;[[Индекс:' .. (d1 or d2) .. '|' .. frame:expandTemplate { title = 'ЭСБЕ/Том', args = { (b1 or b2):gsub ('/.+', '') } } .. ']]. '
			previous = p.previous (frame, 'Индекс:' .. (d1 or d2) )
			next = p.next (frame, 'Индекс:' .. (d1 or d2) )
			if args.name == '' or args.name == nil then name = p.title (frame, 'Индекс:' .. (d1 or d2) ) end
			if b1 and b2 then
				subnav = frame:expandTemplate { title = 'ЭСБЕ/Том', args = { b2:gsub ('/.+', '') } }
				subnav = p.subnav (frame, '[[Индекс:' .. d2 .. '|' .. subnav .. ']]' )
			end
			categories = string.format ( '[[Категория:ЭСБЕ:Дореформенная орфография]][[Категория:ЭСБЕ:ДО:%s]]', firstletter )
			if args.pages ~= 'нет' then contents = '\n' .. beed.transclude ( frame, b1, b2, section, b_old_spell) else contents = '' end
		else
			n = word_list ()
			wordlist = '[[Викитека:Проект:ЭСБЕ/Словник|Список статей ЭСБЕ]]&#x3a;&nbsp;'
			wordlist = wordlist .. '[[Викитека:Проект:ЭСБЕ/' .. n .. '|' .. frame:expandTemplate { title = 'ЭСБЕ/списки', args = { n } } .. ']]. '
			previous = p.previous ( frame, 'Викитека:Проект:ЭСБЕ/' .. n )
			next = p.next ( frame, 'Викитека:Проект:ЭСБЕ/' .. n )
			categories = string.format ( '[[Категория:ЭСБЕ]][[Категория:ЭСБЕ:%s]]', firstletter )
			if args.pages ~= '' then contents = '\n' .. beed.transclude ( frame, b1, b2, section, b_old_spell) else contents = '' end
		end
	end
	-- сборка шаблона
	local noauthor = '<span style="font-style:normal">[[Энциклопедический словарь Брокгауза и Ефрона|Энциклопедическ{{ЕДО|і|и}}й словарь Брокгауза и Ефрона]] '
	noauthor = noauthor .. '<span id="header_override" style="display:none">[[Энциклопедический словарь Брокгауза и Ефрона|ЭСБЕ]]. [[Россия|Росс{{ЕДО|і|и}}я]], '
	noauthor = noauthor .. '[[ЭСБЕ/Санкт-Петербург, столица России|Санкт-Петербург{{ЕДО|ъ}}]], [[w:1890 год|1890]]—[[w:1907 год|1907]]</span></span>'
	noauthor = frame:preprocess (noauthor)
	local source = p.beedScan (frame, 3)
	local misc = '[[Файл:Brockhaus Lexikon.jpg|20px]] ' .. wordlist .. source .. (args.alt or '')
	
	local search = args.search;
	if ( not search or #search == 0 ) then
		search = name;
	end

	return frame:expandTemplate { 
		title = 'Отексте', 
		args = { 
			['НАЗВАНИЕ'] = name, 
			['НЕТ_АВТОРА'] = noauthor, 
			['ДРУГОЕ'] = misc,
			['ПРЕДЫДУЩИЙ'] = previous,
			['СЛЕДУЮЩИЙ'] = next,
			['НАВИГАЦИЯ'] = subnav, 
			['КАЧЕСТВО'] = args.quality,
			['НЕОДНОЗНАЧНОСТЬ'] = args.disambig,
			['ВИКИПЕДИЯ'] = args.w,
			['ВИКИТЕКА'] = args.s,
			['ВИКИСКЛАД'] = args.commons,
			['ВИКИЦИТАТНИК'] = args.q,
			['ВИКИНОВОСТИ'] = args.n,
			['ВИКИСЛОВАРЬ'] = args.wikt,
			['ВИКИУЧЕБНИК'] = args.b,
			['ВИКИВИДЫ'] = args.species,
			['ВИКИДАННЫЕ'] = args.data,
			['ВИКИГИД'] = args.voyage,
			['ПОИСК'] = search,
			['ЕЭБЕ'] = args.eebe,
			['НЭС'] = args.nes,
			['МЭСБЕ'] = args.mesbe,
			['БЭАН'] = args.bean,
			['ЭЛ'] = args.el,
			['БЭЮ'] = args.beyu,
			['РЭСБ'] = args.resb,
			['БСЭ1'] = args.bse1,
			['РБС'] = args.rbs,
			['ТЭ1'] = args.te1,
			['ТЭ2'] = args.te2,
			['ТСД'] = args.tsd,
			['ПБЭ'] = args.pbe,
			['ВЭ'] = args.ve,
			['ГСС'] = args.gss,
			['МСР'] = args.msr,
			['РСКД'] = args.rskd,
			['БСА'] = args.bsa,
			['Британника'] = args.britannica,
			['ADB'] = args.adb,
			['DNB'] = args.dnb,
			['JE'] = args.je,
			['NSRW'] = args.nsrw,
			['NIE'] = args.nie
			}
		} .. categories .. frame:preprocess ( '{{DEFAULTSORT:' .. key .. '}}' ) .. '&nbsp;\n\n<div class="text" style="max-width:100%"><div class="innertext">' .. contents
end

function p.title (frame, lst) return makelink (frame, "title", lst); end
function p.titlefirst (frame, lst)
	local name, fromlist = is ( frame.args[1] ), is ( frame.args.fromlist )
	local firstletter
	if fromlist then
		firstletter = makelink ( frame, "title", lst );
	else
		firstletter = name or p.parse_title ( currname, "subpages" ) or p.parse_title ( currname, "subpages1" )
	end
	firstletter = mw.ustring.sub ( mw.ustring.gsub ( firstletter, "[%s%p]", "" ), 1, 1 );
	return mw.ustring.upper ( firstletter );
end
function p.next (frame, lst) return makelink (frame, "next", lst); end
function p.previous (frame, lst) return makelink (frame, "previous", lst); end
function p.subnav (frame, lst)
	issub = true
	local list = lst or frame.args[1]
	if not is(list) then return end
	if list:find ("headertemplate") then
		list = list:gsub ( "(header_backlink[^%[<>]+>)([^%[<>]*%[%[)", "%1← %2")
		list = list:gsub ( "(header_forelink[^<]+%]%][^%]<>]*)<", "%1 →<")
		return list 
	end
	if not list:find ("%[%[.-%]%]") then list = "[[" .. list .. "]]" end
	local previous = p.previous (frame, list)
	if previous == "" then previous = nil end
	local next = p.next (frame, list)
	if next == "" then next = nil end
	issub = false
	return frame:expandTemplate { title = "sub-nav", args = { previous, next, list } }
end

-- Параметр lst м.б. задан только если эта ф-ция вызывается из других ф-ций этого модуля (p.beed()), а не из шаблона или вики-страницы
function makelink (frame, rel, lst)
	local args = frame.args
	local name, list, text, oldspell, vtype, safe, inherit, noarrow = is(args[1]), is(args[2]), is(args[3]), is(args["ДО"]), is(args.type), is(args.safe), is(args.inherit), is(args.noarrow)
	local result = {}
	local pre, post = "[[", "]]"
	local suffix, found, j

	if lst then
		name = currname
		list = lst
	else
		name = name or currname
		if list == "0" then
			list = word_list ( nil, nil, nil, "full" )
		else
			list = list or currlist
		end
	end
	if not (name and list) then return end

	name = name:gsub ("^ *%[%[(.-)%]%].*", "%1") -- [[name]] -> name
	name = name:gsub ("[#|].+", "") -- name#anchor -> name, name|text -> name

	if name:find ("/ДО$") or name:find ("/ДО/") then oldspell = true end
	
	if not issub then -- только для основной навигации
		-- убираем подстраницы многостраничных статей
		if not oldspell then name = name:gsub ("^(ЭСБЕ/[^/]+)/.*", "%1") end -- напр. ЭСБЕ/Россия
		name = name:gsub ("^(РБС/[^/]+/[^/]+)/.*", "%1") -- напр. РБС/ВТ/Александр II
	end
	
	-- режим inherit: навигация наследуется от родительской страницы
	if inherit then name, suffix = name:match ( "^(.-)/([^/]+)" ) end
	
	noarrow = noarrow or name:find ("^ЭСБЕ/")

	local t = makelist (list, oldspell, safe, name)
	if not t then return end

	for i, v in ipairs (t) do
		if escapePattern(v[1]) == escapePattern(name) then
			found = true
			if rel == "next" then
				j = i+1
				if not noarrow then post = post .. " →" end
			elseif rel == "previous" then
				j = i-1
				if not noarrow then pre = "← " .. pre end
			else 	-- rel == "title"
				vtype = "title"
				result.title = v[3] or v[2] or v[1] break
			end
			if t[j] and (t[j][1] ~= "Викитека:Граница списка в оглавлении") then
				result.link = t[j][1]
				if inherit then result.link = result.link .. "/" .. suffix end
				result.name = text or t[j][2] or t[j][1]
				if result.link == result.name then
					result.complete = pre .. result.link .. post
				else
					result.complete = pre .. result.link .. "|" .. result.name .. post
				end
			end
			break		-- found
		end
	end

	if result.complete then result.complete = result.complete:gsub (">", "") end

	if found then
		if vtype then
			return result[vtype]
		else
			return result.complete
		end
	else
		if safe then
			return
		else
			error ( string.format ('Страница «%s» в оглавлении «%s» не найдена', name, list))
		end
	end
end

function makelist (listname, oldspell, safe, titlename)
	local x, result
	-- проверка наличия и обработка имени оглавления
	if not is(listname) then error ('Оглавление не указано') end
	listname = listname:gsub ( "^ *%[%[(.-)%]%].*", "%1" ) -- минус [[]] и все, что за ними
	listname = listname:gsub ( "[#|].+", "" ) -- минус якорь и текст
	-- проверка корректности имени оглавления
	local title = mw.title.new (listname)
	if not title then error ('Недопустимое имя оглавления: ' .. listname) end
	-- проверка на редирект
	if title.isRedirect then
		x = title.redirectTarget:getContent()
	else
		x = title:getContent()
	end
	-- проверка наличия страницы оглавления
	if not x then 
		if safe then
			return
		else
			error ( string.format ('Оглавление «%s» не найдено', title.text )) 
		end
	end
	-- Подстановка переменных
	x = x:gsub("{{PAGENAME}}", title.text)
	x = x:gsub("{{НАЗВАНИЕ_СТРАНИЦЫ}}", title.text)
	-- Шаблоны-ссылки в простые ссылки
	titlename = is(titlename) or currname
	local root = p.parse_title (titlename, "root")
	local edition = p.parse_title (titlename, "edition")

	-- маркер-граница списка (в виде шаблона)
	x = x:gsub("{{Начало списка в оглавлении}}", "[[Викитека:Граница списка в оглавлении]]")
	x = x:gsub("{{Конец списка в оглавлении}}", "[[Викитека:Граница списка в оглавлении]]")

	x = x:gsub("{{2О Статья в словнике|", "{{Статья в словнике|") -- 2О - rus. О
	x = x:gsub("{{2O Статья в словнике|", "{{Статья в словнике|") -- 2O - lat. O (alias)
	
	x = x:gsub("{{[Tt]sds|", "{{Статья в словнике3|") -- ТСД
	x = x:gsub("{{[Тт]сдс|", "{{Статья в словнике3|") -- ТСД
	x = x:gsub("{{[Сс]татья в словнике ТСД|", "{{Статья в словнике3|") -- ТСД
	x = x:gsub("{{статья в словнике", "{{Статья в словнике")

	if edition == "ДО" or edition == "ВТ" then
		-- для {{ЭСБЕ/Статья}}
		x = x:gsub("{{ЭСБЕ/Статья|([^|]-)}}", "[[ЭСБЕ/" .. edition .. "/%1|%1]]")
		x = x:gsub("{{ЭСБЕ/Статья|([^|]-)|[0-9/|]*}}", "[[ЭСБЕ/" .. edition .. "/%1|%1]]")
		-- для {{Статья в словнике}}
		x = x:gsub(		  "{{Статья в словнике|([^|]+)|[%s]*|[^{}]-}}", "[[" .. root .. "/" .. edition .. "/%1|%1]]")
		x = x:gsub("{{Статья в другом словнике|([^{|}]+)}}", "[[>" .. root .. "/" .. edition .. "/%1|%1]]")
		x = x:gsub("{{Статья в другом словнике|([^{|}]+)|}}", "[[>" .. root .. "/" .. edition .. "/%1|%1]]") -- Не уверен, что надо учитывать этот вариант; м.б. объединен с предыдущим
		x = x:gsub("{{Статья в другом словнике|([^{|}]+)|[%s]*|[^{}]-}}", "[[>" .. root .. "/" .. edition .. "/%1|%1]]") -- Надо посмотреть на практике в словниках -- если совершенно не нужно окажется записывать номера страниц для этого шаблона и от этого откажемся -- эту строку можно будет удалить
		if edition == "ДО" then
			x = x:gsub(		  "{{Статья в словнике|([^{|}]+)|([^{|}]*)|[^{}]-}}", "[[" .. root .. "/" .. edition .. "/%1|%2]]")
			x = x:gsub(		 "{{Статья в словнике3|([^{|}]+)[%s|]*}}", "[[" .. root .. "/" .. edition .. "/%1|%1]]")
			x = x:gsub(		 "{{Статья в словнике3|([^{|}]+)|[%s]*|[^{}]-}}", "[[" .. root .. "/" .. edition .. "/%1|%1]]")
			x = x:gsub(		 "{{Статья в словнике3|([^{|}]+)|([^{|}]*)[%s|]*}}", "[[" .. root .. "/" .. edition .. "/%1|%2]]")
			x = x:gsub(		 "{{Статья в словнике3|([^{|}]+)|([^{|}]*)|[^{}]-}}", "[[" .. root .. "/" .. edition .. "/%1|%2]]")
			x = x:gsub("{{Статья в другом словнике|([^{|}]+)|([^{}]-)}}", "[[>" .. root .. "/" .. edition .. "/%1|%2]]")
			x = x:gsub("{{Статья в другом словнике|([^{|}]+)|([^{|}]*)|[^{}]-}}", "[[>" .. root .. "/" .. edition .. "/%1|%2]]") -- Надо посмотреть на практике в словниках -- если совершенно не нужно окажется записывать номера страниц для этого шаблона и от этого откажемся -- эту строку можно будет удалить
		else
			x = x:gsub(		  "{{Статья в словнике|([^{|}]+)|([^{|}]*)|[^{}]-}}", "[[" .. root .. "/" .. edition .. "/%1|%1]]")
			x = x:gsub("{{Статья в другом словнике|([^{|}]+)|([^{}]-)}}", "[[>" .. root .. "/" .. edition .. "/%1|%1]]")
			x = x:gsub("{{Статья в другом словнике|([^{|}]+)|([^{|}]*)|[^{}]-}}", "[[>" .. root .. "/" .. edition .. "/%1|%1]]") -- Надо посмотреть на практике в словниках -- если совершенно не нужно окажется записывать номера страниц для этого шаблона и от этого откажемся -- эту строку можно будет удалить
		end
	else
		-- при указанном oldspell возвращать название в ДО, независимо от заголовка страницы. Применяется в шапках ТСД для отображения названий в обоих орфографиях
		if oldspell then 
			x = x:gsub(		 "{{Статья в словнике3|([^{|}]+)[%s|]*}}", "[[" .. root .. "/%1|%1]]")
			x = x:gsub(		 "{{Статья в словнике3|([^{|}]+)|[%s]*|[^{}]-}}", "[[" .. root ..  "/%1|%1]]")
			x = x:gsub(		 "{{Статья в словнике3|([^{|}]+)|([^{|}]*)[%s|]*}}", "[[" .. root .. "/%1|%2]]")
			x = x:gsub(		 "{{Статья в словнике3|([^{|}]+)|([^{|}]*)|[^{}]-}}", "[[" .. root .. "/%1|%2]]")
		end
		x = x:gsub("{{ЭСБЕ/Статья|([^|]-)}}", "[[ЭСБЕ/%1|%1]]")
		x = x:gsub("{{ЭСБЕ/Статья|([^|]-)|[0-9/|]*}}", "[[ЭСБЕ/%1|%1]]")
		x = x:gsub(		  "{{Статья в словнике|([^|]+)|[^{}]-}}", "[[" .. root .. "/%1|%1]]")
		x = x:gsub(		  "{{Статья в словнике|([^{|}]+)|[^{|}]*|[^{}]-}}", "[[" .. root .. "/%1|%1]]")
		x = x:gsub(		 "{{Статья в словнике3|([^{|}]+)[%s|]*}}", "[[" .. root .. "/%1|%1]]")
		x = x:gsub(		 "{{Статья в словнике3|([^{|}]+)|[%s]*|[^{}]-}}", "[[" .. root .. "/%1|%1]]")
		x = x:gsub(		 "{{Статья в словнике3|([^{|}]+)|([^{|}]*)[%s|]*}}", "[[" .. root .. "/%1|%1]]")
		x = x:gsub(		 "{{Статья в словнике3|([^{|}]+)|[^{|}]*|[^{}]-}}", "[[" .. root .. "/%1|%1]]")
		x = x:gsub("{{Статья в другом словнике|([^{|}]+)}}", "[[>" .. root .. "/%1|%1]]")
		x = x:gsub("{{Статья в другом словнике|([^{|}]+)|}}", "[[>" .. root .. "/%1|%1]]") -- Не уверен, что надо учитывать этот вариант; м.б. объединен с предыдущим
		x = x:gsub("{{Статья в другом словнике|([^{|}]+)|[%s]*|[^{}]-}}", "[[>" .. root .. "/%1|%1]]") -- Надо посмотреть на практике в словниках -- если совершенно не нужно окажется записывать номера страниц для этого шаблона и от этого откажемся -- эту строку можно будет удалить
		x = x:gsub("{{Статья в другом словнике|([^{|}]+)|([^{}]-)}}", "[[>" .. root .. "/%1|%1]]")
		x = x:gsub("{{Статья в другом словнике|([^{|}]+)|([^{|}]*)|[^{}]-}}", "[[>" .. root .. "/%1|%1]]") -- Надо посмотреть на практике в словниках -- если совершенно не нужно окажется записывать номера страниц для этого шаблона и от этого откажемся -- эту строку можно будет удалить
		x = x:gsub(		 "{{Статья в словнике2|([^{|}]+)|[%s]*|[^{}]-}}", "[[" .. root .. "/%1|%1]]")
		x = x:gsub(		 "{{Статья в словнике2|([^{|}]+)|([^{|}]*)|[^{}]-}}", "[[" .. root .. "/%1|%2]]")
	end

	-- Шаблон {{2О}}
	-- x = string.gsub(x, "{{2[OО]|(.-)}}", "[[%1]]") -- не работает
	if oldspell then
		x = x:gsub( "{{2О|([^{}|]-)}}", "[[%1/ДО|%1]]" ) -- cyr. - no pipe
		x = x:gsub( "{{2O|([^{}|]-)}}", "[[%1/ДО|%1]]" ) -- lat. - no pipe
		x = x:gsub( "{{2О|([^{}|]-)|[^{}|]-|([^{}]-)}}", "[[%1/ДО|%2]]" ) -- cyr. - 2 pipes
		x = x:gsub( "{{2O|([^{}|]-)|[^{}|]-|([^{}]-)}}", "[[%1/ДО|%2]]" ) -- lat. - 2 pipes
		x = x:gsub( "{{2О|([^{}|]-)|([^{}]-)}}", "[[%1/ДО|%2]]" ) -- cyr.
		x = x:gsub( "{{2O|([^{}|]-)|([^{}]-)}}", "[[%1/ДО|%2]]" ) -- lat.
	else
		x = x:gsub( "{{2О|(.-)}}", "[[%1]]" ) -- cyr.
		x = x:gsub( "{{2O|(.-)}}", "[[%1]]" ) -- lat.
	end
	-- Убираем лишние фигурные скобки
	x = x:gsub( "\n{|", "\n" )
	x = x:gsub( "\n|}", "\n" )
	x = x:gsub( "{{Oncolor *|", "" )
	x = x:gsub( "{{oncolor *|", "" )
	x = x:gsub( "{{Dotted TOC", "" )
	x = x:gsub( "{{dotted TOC", "" )
	x = x:gsub( "{{ВАР",  "" )
	x = x:gsub( "{{ВАР2", "" )
	x = x:gsub( "{{:MediaWiki:Proofreadpage.index.template", "" )
	x = x:gsub( "( *{{skip *|)", "…%1" )
	-- Удаляем оставшиеся шаблоны и пр.
	x = x:gsub( "%b{}", "" )
	x = x:gsub( "\n== *См%. также *==.*", "" )
	x = x:gsub( "\n== *Примечания *==.*", "" )
	x = x:gsub( "\n==[^=\n]-==",     "" ) -- м.б. ссылки в заголовках
	x = x:gsub( "\n===[^=\n]-===",   "" ) -- "
	x = x:gsub( "\n====[^=\n]-====", "" ) -- "
	-- Ссылки на неосновное пространство имен, интервики и пр.
	x = x:gsub( "%[%[[:#][^%[%]]-%]%]", "" )
	x = x:gsub( "%[%[%a: *[^%[%]]-%]%]", "" ) -- Википедия и пр.
	x = x:gsub( "%[%[commons: *[^%[%]]-%]%]", "" )
	x = x:gsub( "%[%[wikilivres: *[^%[%]]-%]%]", "" )
	x = x:gsub( "%[%[%a%a: *[^%[%]]-%]%]",   "" ) -- интервики
	x = x:gsub( "%[%[%a%a%a: *[^%[%]]-%]%]", "" ) -- "
	x = x:gsub( "%[%[Категория: *[^%[%]]-%]%]", "" )
	x = x:gsub( "%[%[Файл: *[^%[%]]-%]%]", "" )
	-- Для подстраниц
	x = x:gsub( "%[%[/", "[[" .. listname .. "/" )
	-- Пробелы
	x = mw.ustring.gsub( x, "%s+", " " )
	-- Оставшиеся ссылки собираем в таблицу
	local t= {}
	for m in string.gmatch (x, "%[%[[^%[%]]-%]%]") do
		table.insert (t, m)
	end
	if #t == 0 then error ('Пустое оглавление') end
	-- Чистка и разборка ссылок в таблице
	for i, v in ipairs (t) do
		v = mw.ustring.gsub ( v, "[%s_]", " " ) -- Подчеркивания -> пробелы, нормализация пробелов
		v = v:gsub ( "^%[%[ *(.-) *%]%]$", "%1" ) -- Убираем [[]]
		v = v:gsub ( " +", " " ) -- Еще нормализация пробелов
		v = v:gsub ( "'''", "" ) -- Убираем ''' в тексте
		v = v:gsub ( "''",  "" ) -- И '' тоже
		v = mw.text.split (v, " *| *")
		-- Делаем сокращенную версию длинного текста ссылок
		local txt = v[2]
		if txt then
			local length = mw.ustring.len (txt)
			local pos = mw.ustring.find (txt, "[ \t\n]+", 40) -- Ищем первый пробел после 40 позиции
			if pos and (pos < length) then
				txt = mw.ustring.sub (txt, 1, pos-1) -- Отрезаем найденный пробел и все, что за ним
				txt = mw.ustring.gsub (txt, "[.,;:]$", "") .. "…" -- Отсекаем ненужную пунктуацию и добавляем многоточие
				txt = mw.ustring.gsub (txt, "(«[^»]-)$",   "%1»") -- Восстанавливаем закрывающую кавычку
				txt = mw.ustring.gsub (txt, "(%([^%)]-)$", "%1)") -- Восстанавливаем закрывающую скобку
				table.insert(v, 2, txt) -- Вставляем сокращенный текст перед длинным
			end
		end
		t[i] = v -- Возвращаем очищенную и разобранную ссылку
	end
	return t
end

function escapePattern( pattern_str )
	return mw.ustring.gsub( pattern_str, "([%(%)%.%%%+%-%*%?%[%^%$%]])", "%%%1" );
end

function p.beedScan (frame, noframe, lst)
	local list, name, raw = frame.args[1], frame.args[2], frame.args[3]
	local new_style, flag
	if (name == "") or (name == nil) or noframe then name = currname end
	name = name:gsub ("^ЭСБЕ/", "")
	if name:find ("^ДО/") or name:find ("^ВТ/") then
		new_style = true
		flag = mw.ustring.sub (name,  1, 2)
		name = mw.ustring.sub (name, 4)
	end
	name = name:gsub ("/.*", "")
	if (list == "") or (list == nil) or noframe then 
		if new_style then
			list = "Энциклопедический словарь Брокгауза и Ефрона/" .. flag .. "/Словник/" .. p.wordlist (frame)
		else
			list = "Викитека:Проект:ЭСБЕ/" .. p.wordlist (frame)
		end
	end
	if lst then list = lst end
	raw = noframe or raw
	if not (name and list) then return end
	local title = mw.title.new (list)
	if not title then error ('Недопустимое имя оглавления: ' .. name) end
	local page = title["getContent"]
	local x = page (title)
	if not x then error ( string.format ('Оглавление «%s» не найдено', title.text )) end
	local m = string.match (x, "{{ЭСБЕ/Статья| *" .. escapePattern (name) .. " *|([^{}]-)}}")
	if m then
		m = mw.text.split (m, "|")
	else
		if string.find (x, "{{ЭСБЕ/Статья| *" .. escapePattern (name) .. " *}}") then
			return "<!-- Скан этой страницы временно отсутствует. -->"
		else
			error ( string.format ('Статья «%s» не найдена в списке «%s».', name, list ))
		end
	end
	local t = {}
	for i, v in ipairs (m) do
		local part = beed.parseVolumeStr(v)
		if part ~= nil then
		  table.insert (t, frame:expandTemplate { title = 'ЭСБЕ/Скан', args = {part.volume, part.page, part.numpages}})
		end
	end
	local volumes = mw.loadData('Module:BEED/volumes')
	local volume_key = ""
	for i, v in ipairs (t) do
		v = string.gsub (v, "&nbsp;", " ")
		volume_key = string.match (v, "''(.-), ")
		if volumes[volume_key] then
			v = string.gsub (v, "([^%p%s]+), ", volumes[volume_key] .. ", с. ")
		else
			v = string.gsub (v, "([^%p%s]+), ", "т. %1, с. ")
		end
		v = string.gsub (v, "''", "")
		t[i] = v
	end
	local result = frame:expandTemplate { title = "ЕДО", args = { "Источникъ", "Источник" }} .. ": " .. table.concat (t, "; ")
	if raw then
		if tonumber (raw) == 1 then
			return m[1]
		elseif tonumber (raw) == 2 then
			return m[2]
		else
			return result
		end
	else
		return result
	end
end

function p.pagenum (frame)
	-- hard - номера страниц в печатном издании, soft — в скане
	local vtype, name, listno, list, _phard, _psoft = frame.args[1], frame.args["name"], frame.args["listno"], frame.args["list"], frame.args["phard"], frame.args["psoft"]
	if not is(name) then name = currname end
	local result = {}

	if (_phard == nil) and (_psoft == nil) then
		-- Получаем ссылку на раздел словника
		if not list then
			list = word_list (nil, name, nil, 'full', listno)
		end
		if not is(list) then return end

		-- Получаем название статьи из имени страницы
		local subpages = p.parse_title (name, 'subpages')
		if subpages == nil or subpages == "" then
			subpages = p.parse_title (name, 'subpages1')
		end
		subpages = subpages:gsub ("/.*", "")
		subpages = escapePattern (subpages)

		-- Получаем содержимое словника
		local title = mw.title.new (list)
		if not title then error ('Недопустимое имя оглавления: ' .. subpages) end
		local page = title["getContent"]
		local x = page (title)
		if not x then error ( string.format ('Оглавление «%s» не найдено', title.text )) end
		
		-- Альтернативные шаблоны --> {{Статья в словнике}}
		x = x:gsub("{{2О Статья в словнике|", "{{Статья в словнике|") -- 2О - rus. О
		x = x:gsub("{{2O Статья в словнике|", "{{Статья в словнике|") -- 2O - lat. O (alias)
		x = x:gsub("{{[Tt]sds|", "{{Статья в словнике|") -- ТСД
		x = x:gsub("{{[Тт]сдс|", "{{Статья в словнике|") -- ТСД
		x = x:gsub("{{[Сс]татья в словнике ТСД|", "{{Статья в словнике|") -- ТСД

		-- Параметры шаблона в переменные
		x = mw.ustring.match (x, "{{([Сс]татья в словнике[23]?|[%s]*" .. subpages .. "[%s]*|[^{}]*)}}")
		if x == nil then return "?" end
		x = mw.text.split (x, "|", true)
		for i, v in ipairs(x) do
			if v:find ("=") then x[i] = nil end -- именованные параметры не нужны
		end
		result.phard, result.psoft, result.phard1, result.psoft1 = x[4], x[5], x[6], x[7]
		result.test = x
	else
		result.phard = _phard
		result.psoft = _psoft
	end

	if result.phard then
		result.hard, result.pagination = unpack( mw.text.split (result.phard, "/") )
		result.numhard = result.phard:gsub ("^%D*(%d+).-$", "%1")
	end
	if result.psoft then
		result.soft, result.stop, result.skip = unpack( mw.text.split (result.psoft, "/") )
		result.numsoft = result.soft:gsub ("^%D*(%d+).-$", "%1")
	end
	if result.phard1 then
		result.numhard1 = result.phard1:gsub ("^%D*(%d+).-$", "%1")
	end
	if result.psoft1 then
		result.soft1, result.stop1, result.skip1 = unpack( mw.text.split (result.psoft1, "/") )
		result.numsoft1 = result.soft1:gsub ("^%D*(%d+).-$", "%1")
	end

	return result[vtype] or ""
end

function p.wordlist (frame, noframe)
	local list = frame.args[1];
	local name = frame.args[2];
	local supplement = frame.args[3];
	local type = frame.args["type"];
	local listno = frame.args["listno"];
	return word_list (list, name, supplement, type, listno);
end;

function word_list (list, name, supplement, type, listno)
	local digits = 2
	local root, n, flag, title, new_style, prefix
	if (name == "") or (name == nil) then name = currname end
	n = mw.text.split (name, "/")
	if #n == 1 then return end
	if n[2] == "ДО" or n[2] == "ВТ" then
		if #n == 2 then
			return
		else
			flag, title = n[2], n[3]
			new_style = true
		end
	else
		title = n[2]
	end
	title = title:gsub ("(.+)%b()$", "%1")
	title = title:gsub (",", "00000")
	if n[1] == "БЭАН" then
		title = title:gsub ("^Св%. ", "")
		title = title:gsub ("^От ", "")
	elseif n[1] == "ЭСБЕ" then
		title = title:gsub ("^д’Еон", "Еон")
		title = title:gsub ("^д’Аннунцио", "Аннунцио")
	end
	local hasRuDiacritics = mw.ustring.find ( title, "[ЙйЁё]" )
	if not ( hasRuDiacritics and hasRuDiacritics < 5 ) then title = mw.ustring.toNFD(title) end
	title = mw.ustring.gsub ( title, "[%p%s]", "" )
	--title = title:gsub ("00000", ", ")
	title = title:gsub ("ё", "е")
	local lang = mw.language.new (mw.language.getContentLanguage().code)
	title = lang:ucfirst ( lang:lc (title) )
	if (list == "") or (list == nil) then
		if n[1] == "ЭСБЕ" then
			if new_style then
				root = "Энциклопедический словарь Брокгауза и Ефрона/" .. flag .. "/Словник/"
			else
				root = "Викитека:Проект:ЭСБЕ/"
			end
			digits = 3
			list = [[A N А Аг Аз Ал Ало Ам Ан Анк Ао Ар Арм Ас Ау Б Бак Бар Бас Бб Бел Бем Бер Бес Би Био Бл Бо Бок Бор Бр Бри Бу Буо Бх
			В Вам Вас Вве Вел Вер Вес Виа Вим Вкл Вои Вом Вр Вы Г Гал Гао Гва Гем Гер Гжа Гим Гл Го Гом Гос Гра Грж Гуа Гуп
			Д Дао Деа Дел Дер Дж Ди Дио До Доо Дуа Е Ел Ж Жи З Зап Зе Зл И Иж Ил Ин Ио Ис Й
			К Кай Кам Кан Кар Карл Кас Кв Ке Ки Кл Км Коа Кол Ком Кон Коо Кос Кра Крж Ку Кур Л Лан Леа Лем Ли Лио Ло Лу Ль
			М Мак Мам Мар Мас Меа Мек Мер Ми Мир Мо Моо Мп Мх Н Нар Не Нем Ни Но Нр О Ог Ол Ор Ос От
			П Пан Пас Пеа Пер Пес Пи Пир Пл По Пол Пом Пос Пра Прж Про Пс Пф Р Рал Ре Рек Ри Роа Рок Ру Рш
			С Сал Сан Сар Сб Се Сем Сер Си Син Ск Сл Со Сом Сп Ста Сти Су Сф Т Тан Теа Теп Ти То Тра Три Тс У Ум Ус
			Ф Фе Фео Фи Фио Фо Фр Фт Х Хе Хм Хр Ц Це Ци Ч Чер Чж Ш Шар Ше Ши Шм Шт Щ Э Эк Эм Эр Ю Я Ян Яя+]]
			if supplement then list = supplement end
		elseif n[1] == "БЭАН" then
			root = "Библейская энциклопедия архимандрита Никифора/Словник/"
			list = 'А:А Б:Б В:В Г:Г Д:Д Е:Е Ж:Ж З:З И:И К:К Л:Л М:М Н:Н О:О П:П Р:Р С:С Т:Т У:У Ф:Ф Х:Х Ц:Ц Ч:Ч Ш:Ш Щ:Щ Э:Э Ю:Ю Я:Я Яя:0'
		elseif n[1] == "МЭСБЕ" then
			root = "Малый энциклопедический словарь Брокгауза и Ефрона/Словник/"
			list = [[A А Агуас Аланс Альфр Анемн Араго Асб Б Бандель Батш Бенас Библия. Боброва Боркг Бриар Букса
			В Варне Венз Вие Вкусо Ворв Г Гань Геку Гершт Глейхенр Горбы Гренг Д Делес Диаме Дониц Е Ж З Зеленч
			И Индос К Камера Каркасс Квип Клавик Кола Контор Кошкар Крыс Л Легит Литейный М Маннит Медв Мизе Монн
			Н Несторис О Ону П Пегу Пинде Полиц Призы Р Резек Родил С Сараи Секу Сиги Славя Социн Страсбургер
			Т Тенез Торговоес У Ф Фисо Х Ц Ч Ш Шипуч Ъ Эмболия Ю Яя+]]
		elseif n[1] == "ЕЭБЕ" then
			if new_style then
				root = "Еврейская энциклопедия Брокгауза и Ефрона/" .. flag .. "/Словник/"
			else
				root = "Еврейская энциклопедия Брокгауза и Ефрона/Словник/"
			end
			list = [[A:01 Ac:03 Ad:02 Al:03 Alt:04 An:05 Ar:06 B:08 Be:09 Bet:10 Bo:11 Bu:12 C:29
			Co:32 Cr:33 D:21 Do:22 Dz:21 E:62 Em:63 F:56 Fo:57 G:17 Gl:18 Gr:19 Gu:20 H:17
			Hi:18 I:25 Is:26 Iz:25 J:27 Jor:28 Jov:27 Ju:28 Jude:29 Ken:30 Ker:31 Ko:32
			Koh:31 Kol:32 Kr:33 L:34 Le:35 Li:36 M:37 Me:38 Mi:39 Mo:40 N:41 Neu:42 O:43
			P:44 Pi:45 Pro:46 R:47 S:49 Sc:51 Se:50 Sn:51 So:52 Ste:61 Sti:53 Tas:54 Tr:55
			Ty:54 V:56 Veri:14 Vr:15 W:13 Wo:15 Z:59
			А:01 Ав:02 Аж:03 Ал:03:04 Алмо:04 Анак:05 Ар:05:06 Арабско:06 Ат:07 Б:08 Бе:09 Бед:09:12
			Бее:09 Беж:09:12 Без:09 Бел:09:12 Бем:09 Бер:09:10 Бере:09 Бержн:10:12
			Бери:09:10 Берк:09 Берм:09:10 Берн:10 Бес:09:10 Бет:10 Беч:10:12 Би:10 Бле:11
			Бресс:11:12 Брет:12 В:13 Векш:13:15 Вели:13 Вена:15 Венг:14 Вене:14:15 Венз:14
			Венс:14:15 Верб:14 Верн:14:15 Верр:14 Вес:15 Весе:14 Вестн:14:15 Ветт:14 Веч:15
			Веш:14 Во:15 Гад:15:16 Ге:17 Гес:18 Гол:19 Грех:20 Грец:19 Гри:20
			Дан:20:21 Дани:20 Данф:21 Дети:22 Детм:21 До:22 Ж:23 Зелин:23:24 Зем:24 Иа:27
			Иб:24 Ибнэ:24:25 Ие:27 Из:25 Ии:25:27 Ик:25 Ио:27 Иом:28 Ип:25 Ис:26 Иссо:64
			Ист:26 Иу:28 Иудан:29 Иудап:28 Иудг:29 Иф:26 Й:27 Йон:28 К:29 Кап:30 Кел:30:33 Кем:30
			Кеп:31 Код:32 Кр:33 Ладенбург:33:34 Лев:34:35 Леве:34 Леви:34:35 Левк:35
			Лес:35:36 Либ:35 Лио:36 Лип:35 Лис:35:36 Лиси:36 М:37 Мау:38 Медн:40 Меж:38
			Мелец:40 Мели:38 Мен:40 Менан:38 Меры:40 Мес:38 Мест:38:40 Мет:38 Мехо:40
			Мехол:38 Мещ:40 Мз:38 Ми:39 Миб:38 Миддот:38:39 Миро:40 Миров:39 Мол:40 Н:41
			Неж:42 Нез:41 Неме:41:42 Неп:41 Неу:42 Обет:43 Обеч:42 Обы:43 П:44 Пени:46
			Пенин:44 Песн:46 Песс:44 Пи:44:45 Пик:44 Пио:45 Пип:44 Пир:45 Преш:46 Прж:45
			Прокл:46 Раф:47 Ред:47:48 Рей:47 Реп:48 Рес:47 Реч:47:48 Реше:47:48 Роз:48 С:49
			Сарае:50 Сев:50:53 Сег:50 Сед:50:53 Сеж:50 Сен:50:53 Серп:50 Си:51 Сиб:50
			Сие:51 Сик:50 Сил:51 Сол:52 Сти:53 Тас:54 Телес:55 Телех:54 Трани:54:55 Ф:56
			Федо:64 Фей:56 Феод:64 Фер:56 Фесс:64 Фест:56 Фив:64 Фиг:56 Фим:64 Фин:56 Фо:57
			Х:58 Хи:59 Ч:60 Шем:60:61 Шемо:61 Штер:62 Элиа:63 Элиг:62 Элие:63 Элик:62
			Элио:63 Элип:62 Элиэ:63 Ю:64 Яя:00]]
		elseif n[1] == "ПБЭ" then
			root = "Православная богословская энциклопедия/ВТ/Словник/"
			list = [[A:00 Can:26 Cl:30 Col:31 Com:32 Κοινη:28 Κοινή:31
			А:01 Ад:02 Алф:01:02 Аль:02 Ам:03 Ап:04 Архео:05 Б:06 Бе:06:07 Би:06 Бо:07 В:08 Ват:09 Ве:09:10 Ви:09 Вл:10
			Г:11 Гера:11:13 Герб:11 Ги:12 Гум:12:13 Гур:12 Д:13 Де:13:14 Ди:13 Донс:14 Е:15 Ел:16 Ж:17
			Иа:20 Иако:20:21 Иам:20 Ив:18 Ие:20 Иерар:20:26 Иерат:20 Иеро:21 Из:18 Ии:21 Ик:18
			Ио:21 Иоанн:22:21 Ион:23 Ип:19 Иу:23 Иуда:23:26 Иуде:23 Иф:19 Ия:23 Йог:22 Йон:23
			К:24 Кад:24:25 Казанская:24:26 Казанский:25:25 Каи:24 Календарь.:25 Кано:26 Карме:27
			Кв:28 Кинн:29:30 Кино:29 Кл:30 Книгаи:31 Книгак:30 Книгиз:31 Книгин:30 Книгип:31 Колон:32
			Л:00 С:20:21 Я:00]]
			-- Статьи на 'Иоанн' относятся к 21 или 22 списку, точнее автоматически определить невозможно
			-- Есть несколько статей на С и др. буквы, также требующих ручного определения
		elseif n[1] == "РБС" then
			root = "Русский биографический словарь/ДО/Словник/"
			list = [[А:01 Алексе:01:02 Алекси:02 Ано:03 Б:04 Бау:05 Бег:05:08 Бет:06 Бол:07 Бу:08
			Г:09 Гв:10 Гербер:11 Гол:24 Д:12 Де:12:13 Ди:13 Ж:14 З:15 Зд:16
			Иа:19 Иб:17 Ие:19 Иж:17 Ии:19 Ик:18 Ио:19 Иоас:20 Ип:18 Иу:20 Иф:18
			К:21 Кач:22 Кн:23 Кос:24 Л:25 Лен:26 Лес:26:27 Лет:26:27 Леф:26 Лов:27
			Н:28 О:29 Ол:30 П:31 Пар:32 Пев:32:37 Пер:33:37 Пи:33 Пл:34 Поз:35 Поп:36 Прит:37
			Р:38 Ред:38:42 Рейт:39 Реп:39:42 Рер:39 Реш:39:42 Рж:39 Рих:40 Ром:41 Руд:42
			С:43 Се:44 Сев:44:48 Сес:44 Сим:45 Сме:46 Сми:45 Сне:46 Стар:47 Суворо:48 Т:49 Тен:50
			Ф:51 Фаво:64 Фавс:51 Фадд:64 Фаде:51:64 Фед:64:51 Фез:51
			Фео:64 Ферап:64 Ферб:51 Фету:52 Феф:64 Фех:51 Фив:64 Фиг:51 Фин:52 Фиод:64 Фиор:52 Флее:64 Флей:52 Фом:64:52 Фон:52
			Х:53 Ц:54 Ч:55 Черн:56 Ш:57 Ше:58 Шн:59 Щ:60 Э:61 Ю:62 Я:63 Яя:00]]
			-- Некоторые фамилии на 'Фаде', 'Фед' и 'Фом' имеют двоякое написание, определять вручную
		elseif n[1] == "ВЭ" then
			root = "Военная энциклопедия (Сытин, 1911—1915)/ВТ/Словник/"
			list = [[A:01 C:11 G:08 M:15
			А:01 Алжир:01:02 Алжирскиеэ:02 Арал:03
			Б:04 Бег:04:05 Без:04 Бел:04:05 Бем:04 Бом:04:05 Бомбар:05
			Веж:05:07 Верещ:05:06 Верея:06:07 Вз:06 Воин:06:07 Вой:07 Восс:06 Вост:07
			Гие:08 Гиз:07 Гимр:08 Две:08:09 Дви:08 Двин:09 Ели:10 Ие:11:12 Иж:10 Инк:11
			Калья:12 Кобл:13 Креп:13:14 Крес:13 Крук:14 Лес:14:15 Леф:14 Линту:15
			Мед:15:16 Ми:15 Миа:15:16 Мик:15 Минв:16 Минг:15 Минны:15:16 Мино:16
			Неж:16:17 Нен:16 Ниа:16:17 Ник:16 Нит:17 Пау:18 Я:00]]
		elseif n[1] == "ЭЛ" then
			root = "Энциклопедический лексикон/ДО/Словник/"
			list = [[D:15 De:16 A:01 А:01 Алмо:02 Аль:01 Альмо:02 Альп:02 Ар:03 Ара:02 Аран:03
			Б:04 Баррер:05 Бег:05:07 Би:05 Бино:06 Бранд:06:07 Брани:07 Булгаков:07:12
			В:08 Вар:08:09 Варшава:09:12 Вас:09:12 Вессел:10:12 Вл:11 Воо:12 Вреде:12:14
			Г:13 Гемо:14 Горны:14:15 Горо:15
			Д:15:17 Дв:16:17 Дио:16:17 Дип:16 Дл:17 Я:00]]
		elseif n[1] == "БСЭ1" then
			root = "Викитека:Проект:БСЭ1/Словник/"
			list = [[A:01 Af:04 Ai:01 Al:02 Ap:03 Av:01 B:05 Bo:07 V:08 Vi:10 Vim:11 Viv:10 Voc:13 Vox:12
			А:01 Акон:02 Анрио:03 Атол:04 Бары:05 Бессар:06 Больн:07 Буковы:08 Варлен:09:08 Венгр:10
			Вильо:11 Воден:12 Волч:13 Высше:14 Гейль:15 Германия:16 Гимна:17 Город:18 Граци:19 Гурьевк:20
			Дейл:21 Джуц:22 Дод:23 Евре:24 Железо:25 Зазу:26 Зерновыеэ:27 Империалис:28 Интерполяция:29 История:30
			Камбо:31 Кауч:32 Классы:33 Конкурс:34 Крестьянскаяг:35 Ларт:36 Лилль:37 Мамми:38 Мерав:39 Мон:40
			Наган:41 Нидерланды:42 Оклад:43 Пализ:44 Перемыш:45 Пола:46 Призн:47 Рави:48 Робе:49 Ручно:50
			Серн:51 Созн:52 Страти:53 Телецк:54 Трихоц:55 Украинц:56 Фе:57 Флора:58 Францо:59 Хол:60
			Ч:61 Шахта:62 Э:63 Электрофор:64 Эфем:65 Яяя:00]]
		elseif n[1] == "ЭСГ" then
			root = "Викитека:Проект:ЭСГ/Словник/"
			list = [[А:01]]
		elseif n[1] == "ТСД" and supplement == "1" then
			root = "ТСД-словник/1/"
			list = [[А:А Б:Б:Би Би:Би В:В:Вы Во:Во Вы:Вы Г:Г Д:Д:Дон Дон:Дон Е:Е:Ѣ Ё:Е:Ѣ Ж:Ж З:З Зал:Зал Заст:Заст 
			И:И:І,Ѵ Изу:Изу:І,Ѵ К:К:Кор Ки:Ки Кор:Кор Л:Л М:М Н:Н Нак:Нак Нар:Нар Не:Не О:О Обц:Обц Ор:Ор Ото:Ото 
			П:П Перел:Перел:Прор Пи:Пи Под:Под Подт:Подт Пок:Пок Поо:Поо Пор:Пор Пот:Пот Приг:Приг Про:Про Прор:Прор 
			Р:Р Расп:Расп С:С:Сп Сл:Сл Сп:Сп Т:Т У:У Ф:Ф:Ѳ Х:Х Ц:Ц Ч:Ч Ш:Ш Щ:Щ 
			Ъ:Ъ-Ы-Ь Ы:Ъ-Ы-Ь Ь:Ъ-Ы-Ь Ѣ:Ѣ Э:Э Ю:Ю Ѧ:Ѧ Я:Я]]
		elseif n[1] == "ТСД" and supplement == "2" then
			root = "ТСД-словник/2/"
			list = [[А:А Б:Б:Би Би:Би В:В:Вы Во:Во Вы:Вы Г:Г Д:Д:Дон Дон:Дон Е:Е:Ѣ Ё:Е:Ѣ Ж:Ж З:З Зал:Зал Заст:Заст 
			И:И:І,Ѵ Изу:Изу:І,Ѵ К:К:Кор Ки:Ки Кор:Кор Л:Л М:М Н:Н Нак:Нак Нар:Нар Не:Не О:О Обц:Обц Ор:Ор Ото:Ото 
			П:П Перел:Перел:Прор Пи:Пи Под:Под Подт:Подт Пок:Пок Поо:Поо Пор:Пор Пот:Пот Приг:Приг Про:Про Прор:Прор 
			Р:Р Расп:Расп С:С:Сп Сл:Сл Сп:Сп Т:Т У:У Ф:Ф:Ѳ Х:Х Ц:Ц Ч:Ч Ш:Ш Щ:Щ 
			Ъ:Ъ-Ы-Ь Ы:Ъ-Ы-Ь Ь:Ъ-Ы-Ь Ѣ:Ѣ Э:Э Ю:Ю Ѧ:Ѧ Я:Я]]
		elseif n[1] == "ТСД" and supplement == "3" then
			root = "ТСД-словник/3/"
			list = [[А:А Б:Б:Би Би:Би В:В:Вы Во:Во Вы:Вы Г:Г Д:Д:Дон Дон:Дон Е:Е:Ѣ Ё:Е:Ѣ Ж:Ж З:З Зал:Зал Заст:Заст 
			И:И:І,Ѵ Изу:Изу:І,Ѵ К:К:Кор Ки:Ки Кор:Кор Л:Л М:М Н:Н Нак:Нак Нар:Нар Не:Не О:О Обц:Обц Ор:Ор Ото:Ото 
			П:П Перел:Перел:Прор Пи:Пи Под:Под Подт:Подт Пок:Пок Поо:Поо Пор:Пор Пот:Пот Приг:Приг Про:Про Прор:Прор 
			Р:Р Расп:Расп С:С:Сп Сл:Сл Сп:Сп Т:Т У:У Ф:Ф:Ѳ Х:Х Ц:Ц Ч:Ч Ч1:Ч1 Ш:Ш Щ:Щ 
			Ъ:Ъ-Ы-Ь Ы:Ъ-Ы-Ь Ь:Ъ-Ы-Ь Ѣ:Ѣ Э:Э Ю:Ю Ѧ:Ѧ Я:Я]]
		elseif n[1] == "ГСС" then
			root = "Географическо-статистический словарь Российской империи/ДО/Словник/"
			list = [[А:01 Але:02 Ап:03 Б:04 Бе:05:07 Бо:06 Бу:07 В:08:11 Вес:09:11 Вн:10 Вор:11 Г:12 Гом:13
			Д:14:16 Дз:15 Дон:16 Е:17 Ж:18 З:19 И:20:21 Ип:21 К:22 Кам:23 Карб:24 Кв:25:31 Кис:26:31 Ког:27 Ком:28 Кр:29 Кс:30 Курж:31
			Л:32:33 Лиф:33 М:34 Мар:35 Мей:36:38 Ми:36:37 Мис:37 Мос:38 Н:39 Не:39:42 Ни:40 Но:41 Новоп:42 О:43 Оли:44 Оре:45 Оси:46
			П:47 Пе:47:51 Перл:48:51 Пи:49 Пол:50 При:51 Р:52 Ре:52:53 Ри:52 Рос:53 С:54 Санн:55
			Сб:56 Се:56:62 Сер:57:62 Си:57:58 Сир:58 Сок:59 Ст:60 Сте:60:61 Стр:61 Сэ:62
			Т:63 Тас:64 Тен:65 Теш:65:68 Ти:65 То:66 Тос:67 Тум:68 У:69 Ус:70 Ф:71 Х:72 Хи:73
			Ц:74 Ч:75 Черл:76 Чес:77 Ш:78 Шен:79 Щ:80 Ю:81 Я:82 Ян:83 Яяя:00]]
		elseif n[1] == "МСР" then
			root = "Музыкальный словарь Римана/ВТ/Словник/"
			list = [[A:01 Aub:10 Aug:01 B:02 C:15:07 Ca:07 Cd:15 Cem:13 Cembalo:15 
			Cha:16 Chap:15 Che:16 Chi:07 Chif:16 Cho:15 Chu:16 Ci:15 Cl:07 Cm:15 Co:07 Cy:15 
			D:05 E:06 Ec:16 Edu:06 Eg:16 Ei:06 Ek:16 Em:06 En:16 Es:06 Esa:16 Eses:06 Esp:16 Ev:06 Ew:06:16 
			F:15 G:04 Ger:05 Ges:04 Gi:05 Gis:04 Giu:05 Gl:04 H:04:15 Hande:04 Hay:10 Hd:04:15 
			He:04 His:04:15 Hisp:04 Hm:04:15 Ho:04 Hora:04:15 Horn:04 Hur:04:15 Hy:04 
			I:06 Jah:06:16 Jal:06 K:07 L:08 M:09 N:10 Ouv:14 P:11 Ph:15 Pi:11 Q:07 R:12 
			S:13 Sc:13:16 Schot:16 Sci:13 Sh:16 Si:13 Sing:06:13 Sini:13 T:14 V:03 Vier:15 Vig:03 Z:15
			А:01 Б:02 В:03 Г:04 Д:05 Е:06 К:07 Л:08 М:09 Н:10 П:11 Р:12 С:13 Т:14 
			Ф:15 Фом:15:16 Фон:15 Ш:16 Яя:00]]
		elseif n[1] == "НЭС" then
			root = "Новый энциклопедический словарь/Словник/"	
			list = [[A:01:04 Ali:02 Ant:03 Asc:04 Av:01 B:04 Bar:05 Bi:06 Bo:07 Bre:08 
			D:15:16 Deu:16 E:17 G:12 Ge:13 Gr:14 Gu:15 H:12 Ho:14 
			Le:24 M:25 Ne:28 O:29 V:09 Ve:10 Vo:11:09 
			А:01:02 Алекси:02 Антидот:03 Аскания:04 Балюс:05:08 Белоры:05:09 Берар:06:09 
			Беск:05:08 Бесн:07 Бесп:05:08 Бет:06:09 Беши:06:07 Бобт:07 Брачный:08 Бэ:09 
			Вед:09:12 Вельн:10:12 Виа:10:11 Влась:11 Выгоре:12 
			Гейе:12:15 Генеральный:12:13 Генерат:13:14 Головнич:14:15 Гривн:15 
			Дев:15:17 Деми:15 Десн:16 Душевны:17 Жуко:18 
			Иа:20 Иб:18 Иво:19 Ие:20 Иж:19 Ии:20 Ик:19 Ио:20 Ип:19 Итам:20 Каринт:21:22 Кнос:22 Котош:23:24 
			Ламбет:24 Лес:24:25 Лув:25 Мац:26 Мед:26:27 Молочница:27 Наруш:28:29 Ньюф:29 Оу:000]]
		elseif n[1] == "БЭЮ" then
			root = "Большая энциклопедия Южакова/Словник/"
			list = [[А:001 Аг:002 Аз:003 Ал:004 Альв:005 Ан:006 Анти:007 Арбу:008 Арт:009 Ат:010 
			Б:011 Бал:012 Барв:013 Бат:014 Бе:014:025 Беллинг:014:015 Беллини:015:025 Берез:016:025 
			Би:017 Бл:018 Бо:019 Бом:020 Бр:021 Брн:022 Бугур:023 Бурд:024 Бэ:025 
			В:026 Ван:027 Ве:028:036 Вер:029:036 Вж:030 Византия:031:032 Вип:032 Вм:033 Вол:034 Вп:035 Въ:036 
			Г:037 Гадан:038 Гам:039 Гас:040 Гей:041 Гем:042 Гер:043 Гес:044 Гим:045 Глаз:045:046 Глан:046 
			Гол:047 Гор:048 Гос:049 Гре:050 Гру:051 Гун:052 Гюгс:053 
			Дар:054 Де:055:061 Ден:056:061 Дж:057 Дин:058 До:059 Др:060 Духовенство:060:061 Духовн:061 
			Е:062 Ж:063 Жер:064 З:065 Зб:066 Зл:067 И:068 Иа:072 Ив:068 Ид:069:072 Ин:070:072 Ир:071:072 
			К:073 Кал:074 Кан:075 Кар:076 Кас:077 Кв:078 Ки:079:080 Киты:080 Км:081 
			Кол:082 Кон:083 Кор:084 Кот:085 Крж:086 Кс:087 Кур:088 
			Л:089 Ландау:090 Ле:090:095 Леда:091:095 Лж:092 Лит:093 Лол:094 Лун:095 
			М:096 Мал:097 Мар:098 Мат:099 Мелан:100 Мес:101 Мин:102:105 Мо:103 Моп:104 Му:105 
			Н:106 Наф:107 Нерчинский:107::108 Нерш:108 Ним:109 Нож:110 О:111 Ож:112 Оп:113 Ос:114 
			П:115 Пап:116 Пат:117 Пень:118 Пес:119 Пис:120 По:121 Пол:122 Пор:123 
			Пре:124:126 Прок:125 Пуль:125:126 Пулю:126 
			Р:127 Рар:128:132 Ре:129:132 Рин:130 Ром:131 Рус:132 
			С:133 Саль:133:134 Салэ:134 Сап:135 Сво:136:145 Сен:137:145 Сж:138 Сит:139 
			Сл:140 Сод:141 Сп:142 Статистик:142:143 Статистич:143 Сту:144 Сф:145 
			Т:146 Тв:147 Тес:148 То:149 Тре:150 Ту:151 У:152 Ундол:153 
			Ф:154:171 Фер:155:171 Фл:156:171 Фр:157:171 Х:158 Хо:159 Ц:160 
			Ци:161 Ч:162 Чахо:163 Чи:164 Ш:165 Шем:166 Шп:167 Щ:168 Эк:169 Эн:170 Ю:171
			Яя:000]]
		elseif n[1] == "БЭЮ1" then
			root = "Большая энциклопедия Южакова/Словник/Дополнение/"
			list = [[A:1 А:1 Д:2 Л:3 П:4 Т:5 Яя:0]]
		elseif n[1] == "БЭЮ2" then
			root = "Большая энциклопедия Южакова/Словник/2-е издание/"
			list = [[А:01 Менд:02 Яя:00]]
		elseif n[1] == "РСКД" then
			root = "РСКД/Словник/"
			list = [[A:A B:B C:C D:D E:E F:F G:G H:H I:I L:L M:M N:N O:O P:P Q:Q R:R S:S T:T U:U V:V X:X Z:Z
			Α:A:H Β:B Γ:G Δ:D Ε:E Ζ:Z Η:H Θ:T Ι:H Λ:L Κ:C Μ:M Ν:N Ξ:X Π:P Ρ:R Σ:S Τ:T Φ:P Ψ:P
			Ἀ:A Ἀ:A:H Ἐ:H Ἐ:E:H Ἔ:E Ἠ:H Ἱ:H Ὁ:H Ὀ:O Ῥ:R Ὑ:H Ὥ:H Ὠ:O]]
		else
			root = n[1] .. "/ДО"
			list = ""
		end
	end
	if type == "full" then prefix = root else prefix = "" end
	-- разбиение списка начальных букв словников в массив, по символам ' ' и ':'
	if (listno == "") or (listno == nil) and (list ~= "") then
		local m = mw.text.split (list, '%s+')
		for i, v in ipairs (m) do
			v = mw.text.split (v, ':')
			if not v[2] then v[2] = string.format ("%0" .. digits .. "d", i) end
			m[i] = v
		end
		-- поиск соответствующего словника по заголовку статьи
		for i = 1, #m do
			if  (i == #m) or (title >= m[i][1] and title < m[i+1][1]) then
				-- сборка викиссылки к словнику
				if m[i][3] then  -- искать в доп. словнике, если он указан после второго ':'
					local t = makelist (root .. m[i][2])
					if t then 
						for j, v in ipairs (t) do
							if escapePattern(v[1]) == escapePattern(name) then
								return prefix .. m[i][2]
							end
						end
					end
					return prefix .. m[i][3]
				else
					return prefix .. m[i][2]
				end
			end
		end
	else
		return prefix .. (listno or "")
	end
	return "Oops"
end

--[=[
Функция parseTitle
Разбивает название страницы на сегменты в соответствии с механизмом редакций

Использование:
{{#invoke:Header|parseTitle|segment|[name]}}

Допустимые значения segment:
	root: корневая часть названия со списком редакций
	edition: первый уровень подстраниц (обозначение текущей редакции)
	fulledition: полный путь к текущей редации от корня
	subpages: остальные уровни подстраниц как единое целое
	subpages1: все уровни подстраниц (если механизм редакций не используется)
	isPRS: true, если название редакции соответствует ДО, иначе false
	test: выводит все компоненты, для тестирования поведения
]=]
function p.parseTitle (frame)
	local segment, name = frame.args[1], frame.args[2]
	if (name == "") or (name == nil) then name = currname end
	return p.parse_title (name, segment)
end

function p.parse_title (title, s)
	local name = title
	local parts = {}
	-- выделение корневого элемента
	if name:find ("^[^/%(%)]+%([^%(%)]+/[^%(%)]+%)/") then
		parts.root = name:gsub ("^([^/%(%)]+%([^%(%)]+/[^%(%)]+%))/.+", "%1")
		name = name:gsub ("^[^/%(%)]+%([^%(%)]+/[^%(%)]+%)/", "")
	elseif name:find ("^[^/%(%)]+%([^%(%)]+/[^%(%)]+%)$") then
		parts.root = name
		name = ""
	elseif name:find ("/") then
		parts.root = name:gsub ("^([^/]+)/.+", "%1")
		name = name:gsub ("^[^/]+/", "")
	else
		parts.root = name
		name = ""
	end
	parts.subpages1 = name
	if name:find ("/") then
		parts.edition = name:gsub ("^([^/]+)/.+", "%1")
		parts.subpages = name:gsub ("^[^/]+/", "")
	else
		parts.edition = name
		parts.subpages = ""
	end
	if parts.edition ~= "" then
		parts.fulledition = parts.root .. "/" .. parts.edition
		parts.isPRS = (parts.edition == "ДО") or parts.edition:find("^.+ +%(ДО%)$") or parts.subpages1:find("/ДО$")
	else
		parts.fulledition = ""
	end
	if parts.isPRS then
		parts.isPRS = true
	else
		parts.isPRS = false
	end
	if s == "test" then
		return "title: " .. title .. ", root: " .. parts["root"] .. ", edition: " .. parts["edition"] .. ", fulledition: " .. parts["fulledition"] .. 
			", subpages: " .. parts["subpages"] .. ", subpages1: " .. parts["subpages1"] .. ", isPRS: " .. tostring(parts["isPRS"])
	else
		return parts[s]
	end
end

function p.editionsList (frame)
	local mode = frame.args[1]
	local name = p.parse_title (currname, "root")
	local edition = p.parse_title (currname, "edition")
	local subs = p.parse_title (currname, "subpages")
	local flag = ""
	local edition_pre = ""
	if ( edition == "ДО" or edition == "ВТ" ) and is ( subs ) then -- для словарей
		flag = "|" .. edition .. "|"
		edition_pre = "Редакция "
	elseif edition:find ( "^.*%([^%(%)]+%)$" ) then
		flag = edition:gsub ("^.*%(([^%(%)]+)%)$", "|%1|")
	end
	-- не соответствует схеме именования редакций
	if flag == "" or not string.find ("|ДО|СО|ВТ|ВТ1|ВТ2|ВТ:Ё|ВТ:У|", flag) then return end
	-- поддержка ДО
	--local str_toc = frame:expandTemplate { title = "ЕДО", args = { "оглавленіе", "оглавление" }}
	local str_editions = frame:expandTemplate { title = "ЕДО", args = { "Редакціи", "Редакции" }}
	local title = mw.title.new (name)
	if not title then error ('Недопустимое имя списка: ' .. name) end
	local page = title["getContent"]
	local x = page (title)
	-- список редакций отсутствует или пуст
	if not x or not ( x:find ("\n%*") or x:find ("^%*") ) then
		return "'''[[" .. name .. "|" .. str_editions .. "]]'''"
	end
	-- чистка списка редакций
	x = x:gsub ("\n%s*\n", "\n") -- пустые строки
	x = x:gsub ("^.-\n%*", "*") -- текст до начала списка
	x = x:gsub ("\n[^%*].+", "\n") -- текст после конца списка
	x = x:gsub ("%]%].-\n", "]]\n") -- текст после ссылок
	local y = x -- альтернативный список
	y = y:gsub ("%[%[([^%[%]/]-/)([^%[%]|]-)|[^%[%]]-%]%]", "[[%1%2|" .. edition_pre .. "%2]]") -- edition как отображаемый текст
	x = x:gsub ("%[%[/", "[[" .. name .. "/") -- относительные ссылки в абсолютные
	y = y:gsub ("%[%[/", "[[" .. name .. "/") -- относительные ссылки в абсолютные
	-- добавление ссылок на оглавления (для подстраниц)
	if subs ~= nil and subs ~= "" and mode ~= "short" then
		x = x:gsub ("%* *%[%[([^%[%]|]-)|([^%[%]]-)%]%]",  "<tr><td></td><td style='padding-right:1em;'>[[%1/" .. subs .. "|%2]]</td><td><small>([[%1|огл.]])</small></td></tr>")
		y = y:gsub ("%[%[([^%[%]|]-)|([^%[%]]-)%]%]", "[[%1/" .. subs .. "|%2]]")
	else
		x = x:gsub ("%* *(%[%[[^%[%]|]-|[^%[%]]-%]%])",  "<tr><td></td><td>%1</td></tr>")
	end
	-- добавление значка для ДО
	x = x:gsub ("</td>(<td[^<>]->%[%[[^%[%]|]- %(ДО%) *|[^%[%]]-%]%])", "[[File:Ять 4.jpg|16px|link=|Дореформенная ор{{ф}}ограф{{и}}я]]&nbsp;</td>%1")
	x = x:gsub ("</td>(<td[^<>]->%[%[[^%[%]|]- %(ДО%)/[^%[%]|]-|[^%[%]]-%]%])", "[[File:Ять 4.jpg|16px|link=|Дореформенная ор{{ф}}ограф{{и}}я]]&nbsp;</td>%1")
	x = x:gsub ("</td>(<td[^<>]->%[%[[^%[%]|]-/ДО *|[^%[%]]-%]%])</td>", "[[File:Ять 4.jpg|16px|link=|Дореформенная ор{{ф}}ограф{{и}}я]]&nbsp;</td>%1")
	x = x:gsub ("</td>(<td[^<>]->%[%[[^%[%]|]-/ДО/[^%[%]|]-|[^%[%]]-%]%])</td>", "[[File:Ять 4.jpg|16px|link=|Дореформенная ор{{ф}}ограф{{и}}я]]&nbsp;</td>%1")
	-- оформление списка
	x = "<table>\n" .. x .. "\n<tr><td colspan=3 style='text-align:center;'><small>([[" .. name .. "|список{{ъ}} редакц{{и}}й]])</small></td></tr>\n</table>"
	x = "<div id='editions_toggle'>\n'''" .. str_editions .. "'''\n<div id='editions_cont'>\n" .. frame:preprocess(x) .. "</div></div>"
	x = x .. "<div id='altEditions' style='display:none;'>\n\n" .. frame:preprocess(y) .. "\n</div>"
	if mode == "flag" then
		return flag
	else
		return x
	end
end

function p.fixarrowlink (frame)
	local link = frame.args[1]
	link = link:gsub ("^←%s*%[%[([^%[%]|]+)|([^%[%]]+)%]%]%s*$", "<span style='display:table-cell;vertical-align:middle;font-size:200%%;'>[[%1|⇦]]</span> <span style='display:table-cell;vertical-align:middle;width:100%%;'>[[%1|%2]]</span>")
	link = link:gsub ("^←%s*%[%[([^%[%]|]+)%]%]%s*$", "<span style='display:table-cell;vertical-align:middle;font-size:200%%;'>[[%1|⇦]]</span> <span style='display:table-cell;vertical-align:middle;width:100%%;'>[[%1|%1]]</span>")
	link = link:gsub ("^←%s*([^%[].*)$", "<span style='display:table-cell;vertical-align:middle;font-size:200%%;'>⇦</span> <span style='display:table-cell;vertical-align:middle;width:100%%;'>%1</span>")
	link = link:gsub ("^%s*%[%[([^%[%]|]+)|([^%[%]]+)%]%]%s*→$", "<span style='display:table-cell;vertical-align:middle;width:100%%;'>[[%1|%2]]</span> <span style='display:table-cell;vertical-align:middle;font-size:200%%;'>[[%1|⇨]]</span>")
	link = link:gsub ("^%s*%[%[([^%[%]|]+)%]%]%s*→$", "<span style='display:table-cell;vertical-align:middle;font-size:100%%;'>[[%1|%1]]</span> <span style='display:table-cell;vertical-align:middle;font-size:200%%;'>[[%1|⇨]]</span>")
	link = link:gsub ("^%s*(.*[^%]])%s*→$", "<span style='display:table-cell;vertical-align:middle;font-size:100%%;'>%1</span> <span style='display:table-cell;vertical-align:middle;font-size:200%%;'>⇨</span>")
	return link
end

-- Преобразует переданную текстовую строку в ссылку, если она не содержит ссылок;
-- в противном случае, возвращает ее без изменений
function p.linkify (frame)
	local link = frame.args[1]
	if link == nil or link == "" then return end
	if not link:find ("%[%[") then
		link = "[[" .. link .. "]]"
	end
	return link
end

function p.test (frame)
	local a = frame.args[1]
	local t = makelist (a)
	for i, v in ipairs (t) do
		v = table.concat (v, ' @@@ ')
		t[i] = v
	end
	return table.concat (t, '\n')
end



-- запрос данных из подмодуля данных
-- пример: {{#invoke:Header|data|ТСД2|year_of_volume|4}}  или  data('ТСД2', 'year_of_volume', 4)  →  вернёт 1882
function data(project, var, volume)
	local d = mw.loadData('Модуль:Header/Data')
	if volume then
		return d[project][var][tonumber(volume)]
	else
		return d[project][var]
	end
end
function p.data(frame) return data(frame.args[1], frame.args[2], frame.args[3]) end


-- Рассчитывает страницу скана по странице книги, добавляя смещение.  Возврат: стр.скана. Параметры:
--  project, tom, pagebook  —  имя проекта (напр. 'ТСД', 'ЭСБЕ'), номер тома, страница книги
--  othernumeration - для страниц по опечатке в книге имеющих один номер, для второй стр. указать "2", или для доп. нумераций - 'numeration2' и т.п.
function pagescan_calc(project, tom, pagebook, othernumeration)
	local pb = tonumber(mw.ustring.match(tostring(pagebook), '%d+'))  -- учитывать только первые цифры диапазона страниц ('15' в '15-16')
	if not is(pb) or pb <= 0 then return end
	local offset = data(project, 'pageoffset_of_volume', tonumber(tom))
	local interleaved = data(project, 'interleaved')   -- страницы издания считать через одну (например, если пагинация страниц по колонкам: 2-3, 4-5, 6-7)

	if not is(interleaved) then
		do  -- список исключений
			if project == 'ТСД1' and tom == 4 then
				-- в ТСД1-4 ошибка: номера 467-468 у двух страниц, этим сбита последующая пагинация
				if pb >= 469 or ((pb == 467 or pb == 468) and othernumeration == '2') then offset = 3 end
			elseif project == 'ЭЛ' then
				if tom == 1 and pb >= 559  then offset = 15 end
				if tom == 2 and pb >= 490  then ofset = 3 end
				if tom == 4 then
					if pb >= 370 or (pb == 369 and othernumeration == '2') then offset = 7 end
					if pb >= 390 then offset = 5 end
					if othernumeration == 'numeration2' then offset = 398 end
				end
				if tom == 7 then
					if othernumeration == 'numeration2' then offset = 645 end
					if othernumeration == 'numeration3' then offset = 143 end  -- доп. оглавление с нумерацией с 513 (дублирует страницы статей >= 513)
					-- if othernumeration == 'numeration0' then offset = 0 end  -- римская в предисловии
				end
			end
	    end
		return pb + offset
	else
		local _, x = math.modf(pb / 2)  -- проверка, что номер страницы чётный
		if x ~= 0 then pb = pb + 1 end
		-- если этот авторасчёт будет глючить (в ТСД-3 работает), то попробовать вариант с явным заданием чётности параметром
		return pb / 2 + offset
	end
end
function p.pagescan_calc(frame) return pagescan_calc(frame.args[1], frame.args[2], frame.args[3], frame.args[4]) end


-- возвращает номер тома по первой букве слова/статьи
function volume_calc(project, word)
	word = word:gsub('^[^a-zа-яёѣѵіѳA-ZА-ЯЁѢѴІѲѦ]+', '')  -- пропуск первых не-букв в слове
	word = mw.ustring.upper(mw.text.trim(word))  -- сверка букв в верхнем регистре
	if not is(word) then return '' end

	local list = data(project, 'volume_by_letter')
	local v = mw.text.split (list, '%s+')
	local cmp_n, cmp_n1
	for n = 1, #v do  -- перебор томов
		cmp_n = compare_words_utf8(word, mw.ustring.upper(v[n]))
		if cmp_n == 2 then
			if not v[n+1] then return n end  -- если последний том
			cmp_n1 = compare_words_utf8(word, mw.ustring.upper(v[n+1]))
			if     cmp_n1 == 1 then return n
			elseif cmp_n1 == 3 then return n+1  end
		elseif cmp_n == 3 then return n      -- слово равно буквам тома
		elseif cmp_n == 1 then return 'oops'
		end
	end
end
function p.volume_calc(frame) return volume_calc(frame.args[1], frame.args[2]) end

-- год издания тома по названию статьи
function p.year_of_volume_by_term(frame)
	local project, word = frame.args[1], frame.args[2]
    local volume = volume_calc(project, word)
    return data(project, 'year_of_volume', tonumber(volume))
end

-- год издания тома по номеру тома
function p.year_of_volume(frame)
	local project, volume = frame.args[1], frame.args[2]
    return data(project, 'year_of_volume',  tonumber(volume))
end


function compare_words_utf8(word1, word2)
	-- Сравнение слов в кодировке utf8, т.е. какое слово левее по алфавиту.
	-- Возврат: 1 — буквы первого слова перед вторым, 2 — ... после второго, 3 — слова равны
	-- Для корректной сверки слова заранее переводить в верхний регистр
	order_chars = ' 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZАБВГДЕЁЖЗИІКЛМНОПРСТУФХЦЧШЩЪЫЬѢЭЮѦЯѲѴ'
	word1 = mw.ustring.upper(mw.text.trim(word1))
	word2 = mw.ustring.upper(mw.text.trim(word2))
	for i = 1, math.min( #order_chars, #word1, #word2) do
		c1 = mw.ustring.sub( word1, i, i )
		c2 = mw.ustring.sub( word2, i, i )
		oc1 = mw.ustring.find( order_chars, c1 )
		oc2 = mw.ustring.find( order_chars, c2 )
		if oc1 == nil then oc1 = 1000 end  -- неалфавитные символы
		if oc2 == nil then oc2 = 1000 end  -- 
		if     oc1 < oc2 then return 1
		elseif oc1 > oc2 then return 2 end
	end
	if     #word1 < #word2  then return 1
	elseif #word1 > #word2  then return 2
	elseif #word1 == #word2 then return 3 end
end
function p.compare_words_utf8(frame) return compare_words_utf8(frame.args[1], frame.args[2]) end



return p