Модуль:Отексте/Документ

Документация Документация

Расширение Модуль:Отексте (шаблона {{Отексте}}) для шаблона {{Документ}}.

Литералы
local p = {}

local util = require("Module:Util")
local countries_with_cases = util.get_json('MediaWiki:Отексте/Документ/countries_with_cases.json')  -- страны с падежами
local authorities_with_cases = util.get_json('MediaWiki:Отексте/Документ/authorities_with_cases.json') -- органы с падежами
local types = util.get_json('MediaWiki:Отексте/Документ/doc_types.json')

local N, G, NONE = "им.", "род.", "н/у"  -- падежи
local BOLD = {["font-weight"] = "bold"}
local BOLDUPPER = {["font-weight"] = "bold", ["text-transform"] = "uppercase"}
local docInfo = {}; local authorities = {}; local editions = {}
local categories = {}
local s = {
	deprecated = " <span class='deprecated'>Документ утратил силу, см. %s</span>",
	cat = {
		["deprecated"] = "Документы, утратившие силу",
		["unknownType"] = "Документы с неизвестным видом документа",
		["unknownAuth"] = "Документы неизвестного органа",
	}
}
local lang = mw.language.new (mw.language.getContentLanguage().code)

-- Основная функция ------------------------------------------------------------
--------------------------------------------------------------------------------
function p.wrapper ( frame, pargs )
	local args = frame.args; local type = args.type
	docInfo = {
		type = pargs["ВИД"] or "",
		to = pargs["КОМУ"] or "",
		date = pargs["ДАТА"] or "",
		num = pargs["№"] or pargs["НОМЕР"] or "", -- НОМЕР в некоторых шаблонах
		num2 = pargs["№2"] or "",
		num3 = pargs["№3"] or "",
		classified = pargs["ГРИФ"] or "",
		title = pargs["НАЗВАНИЕ"] or "",
		deprecated = pargs["УТРАТИЛ СИЛУ"] or "",
		editionsNote = pargs["ПРИМЕЧАНИЕ ПО РЕДАКЦИЯМ"] or "",
		passed = pargs["ПРИНЯТ"] or "",
		arms = pargs["ГЕРБ"] or "",
		style = pargs["СТИЛЬ"] or "",
		cat = pargs["КАТЕГОРИЯ"] or "",
		-- флаги
		noDate = is ( pargs["НЕТ ДАТЫ"] ),
		noQuotes = is ( pargs["НЕТ КАВЫЧЕК"] ),
		uTitle = is ( pargs["ПОДЧЁРКИВАТЬ НАЗВАНИЕ"] ),
		uDate = is ( pargs["ПОДЧЁРКИВАТЬ ДАТУ"] ),
		uNum = is ( pargs["ПОДЧЁРКИВАТЬ НОМЕР"] ),
	}
	--[[ доп. параметры:
	-- Ш:Закон о поправке к Конституции
	docInfo.datePassed = pargs["ДАТА ПРИНЯТИЯ ГОСДУМОЙ"]
	docInfo.dateApproved = pargs["ДАТА ОДОБРЕНИЯ СОВЕТОМ ФЕДЕРАЦИИ"]
	-- Ш:Конституция СССР
	docInfo.passed1 = pargs["ПРИНЯТА"] -- не дата
	docInfo.approved = pargs["УТВЕРЖДЕНА"] -- не дата
	docInfo.previous = pargs["ПРЕДЫДУЩАЯ"]
	docInfo.next = pargs["СЛЕДУЮЩАЯ"]
	docInfo.disambig = pargs["НЕОДНОЗНАЧНОСТЬ"] -- передавать напрямую?
	-- Ш:Краевой закон
	--pargs["КРАЕВОЙ"] -- ?
	--pargs["КРАЯ"] -- ?
	-- Ш:Областной закон
	--pargs["ОБЛАСТНОЙ"] -- ?
	--pargs["ОБЛАСТИ"] -- ?
	-- Ш:Определение Конституционного Суда РФ
	-- Ш:Постановление Конституционного Суда РФ
	docInfo.noHeader = pargs["БЕЗШАПКИ"]
	-- Ш:Постановление Правительства РФ
	-- Ш:Постановление Совета Министров - Правительства РФ
	-- Ш:Постановление Совета Министров РСФСР
	-- Ш:Постановление Совета Министров СССР
	-- Ш:Приказ Верховного Главнокомандующего
	-- Ш:Приказ Минобороны РФ
	-- Ш:Приказ НКО
	-- Ш:Приказ Росстандарта
	-- Ш:Приказ Ростехнадзора
	-- Ш:Распоряжение Правительства РФ
	-- Ш:Распоряжение Президента РФ
	-- Ш:Редакция Федерального закона
	docInfo.datePassed = pargs["ДАТА ПРИНЯТИЯ ГОСДУМОЙ"]
	docInfo.dateApproved = pargs["ДАТА ОДОБРЕНИЯ СОВЕТОМ ФЕДЕРАЦИИ"]
	docInfo.editionYear = pargs["ГОД РЕДАКЦИИ"]
	docInfo.editionMonth = pargs["МЕСЯЦ РЕДАКЦИИ"]
	docInfo.editionDay = pargs["ЧИСЛО РЕДАКЦИИ"]
	-- Ш:Решение суда РФ
	docInfo.court = pargs["СУДА"]
	docInfo.matter = pargs["ДЕЛО"]
	docInfo.location = pargs["МЕСТО"]
	-- Ш:Указ Президента РБ
	-- Ш:Указ Президента РК
	-- Ш:Указ Президента РФ
	docInfo.position = pargs["ДОЛЖНОСТЬ"]
	-- Ш:Указ Президента РЮО
	-- Ш:Указ Президента СССР
	-- Ш:Указ Президента Украины
	docInfo.origLang = "uk"
	docInfo.translator = pargs["ПЕРЕВОДЧИК"]
	-- Ш:Указ Президиума Верховного Совета
	docInfo.country = pargs["ОРГАН"] -- ошибка в шаблоне?
	docInfo.approved = pargs["УТВЕРЖДЁН"] -- не дата
	-- Шаблон:Указ Президиума Верховного Совета СССР -- не нужен?
	--pargs["КОМУ"] --?
	--pargs["ГРИФ"] --?
	-- Ш:Федеральный закон, Ш:Федеральный конституционный закон
	docInfo.datePassed = pargs["ДАТА ПРИНЯТИЯ ГОСДУМОЙ"]
	docInfo.dateApproved = pargs["ДАТА ОДОБРЕНИЯ СОВЕТОМ ФЕДЕРАЦИИ"]
	]]
	if docInfo.cat then localAddCat ( docInfo.cat ) end
	
	-- альтернативный формат даты и проверка
	if not is(docInfo.date) then
		local dateparts = { pargs["ДЕНЬ"] or pargs["ЧИСЛО"], pargs["МЕСЯЦ"], pargs["ГОД"] }
		docInfo.date = table.concat( dateparts, "." )
	end
	if not pcall( lang.formatDate, lang, "от j xg Y года", docInfo.date ) then docInfo.date = "" end
	
	-- сбор серийных параметров в таблицы
	for k, v in pairs(pargs) do
		if mw.ustring.find( k, "ОРГАН" ) then
			local n
			if k == "ОРГАН" then n = 1 else n = tonumber ( string.match( k, "%d+" ) ) end; mw.log(k, v, n)
			if n then authorities[n] = { name = is(v) } end
		elseif mw.ustring.find( k, "РЕДАКЦИЯ " ) then
			local n = tonumber ( string.match( k, "%d+" ) )
			if n then editions[n] = { name = is(v) } end
		end
	end
	--if #authorities == 0 then return {}, {}, "" end
	for k, v in pairs(pargs) do
		if mw.ustring.find( k, "СТРАНА" ) then
			local n
			if k == "СТРАНА" then n = 1 else n = tonumber ( string.match( k, "%d+" ) ) end
			if n then
				if authorities[n] then authorities[n].country = is(v) else authorities[n] = { country = is(v) } end
			end
		elseif mw.ustring.find( k, "ОПИСАНИЕ РЕДАКЦИИ " ) then
			local n = tonumber ( string.match( k, "%d+" ) )
			if n and editions[n] then editions[n].desc = is(v) end
		end
	end
	-- чистка
	for i = #authorities, 1, -1 do 
		local v = authorities[i]; if not (v.name or v.country) then table.remove( authorities, i ) end
	end
	mw.logObject(authorities,"authorities")
	for i = #editions, 1, -1 do 
		local v = editions[i]; if not (v.name) then table.remove( editions, i ) end
	end
	mw.logObject(editions,"editions")
	if authorities[1] and authorities[1].name and not authorities[1].country then authorities[1].country = "" end
	for i, v in ipairs(authorities) do
		if i > 1 and v.name and not v.country then v.country = authorities[1].country end
	end

	pargs = {
		["НЕТ_АВТОРА"] = "",
		["ЯЗЫКОРИГИНАЛА"] = "",
		["НАЗВАНИЕ"] = makeTitle (),
		["ИСТОЧНИК"] = pargs["ИСТОЧНИК"],
		["КАЧЕСТВО"] = pargs["КАЧЕСТВО"],
		["ВИКИПЕДИЯ"] = pargs["ВИКИПЕДИЯ"],
		["ДРУГОЕ"] = pargs["ДРУГОЕ"] or "",
		["ЛИЦЕНЗИЯ"] = is(pargs["ЛИЦЕНЗИЯ"]) or "exempt",
		["ДАТАПУБЛИКАЦИИ"] = pargs["ДАТАПУБЛИКАЦИИ"],
	}
	
	if is ( docInfo.deprecated ) then
		pargs["ДРУГОЕ"] = pargs["ДРУГОЕ"] .. string.format ( s.deprecated, docInfo.deprecated )
		localAddCat ( s.cat.deprecated )
	end
	pargs["ДРУГОЕ"] = is(pargs["ДРУГОЕ"]) -- не передаем пустую строку
	if authorities[1] and authorities[1].country == "ООН" then pargs["ЛИЦЕНЗИЯ"] = "PD-UN" end
	
	local beforetext = makeEditions() .. makeHeader()
	makeCategories();mw.logObject(categories)
	mw.logObject(pargs,"pargs");mw.logObject(beforetext,"beforetext");
	return pargs, categories, beforetext
end

-- заголовок -------------------------------------------------------------------
--------------------------------------------------------------------------------
function makeTitle ()
	local title = docInfo.type; if not title then return "" end
	local function append(str) if is(str) then title = title .. " " .. str end end
	local links = {}
	for i, v in ipairs(authorities) do
		table.insert ( links, wpLink ( v.name, v.country ))
	end
	append ( mw.text.listToText ( links ))
	append ( docInfo.to )
	if is(docInfo.date) and not docInfo.noDate then append ( lang:formatDate ( "от j xg Y года", docInfo.date ) ) end
	if is(docInfo.num) then append ( "№ " .. makeDocNum() ) end
	if is(docInfo.title) then 
		if docInfo.noQuotes then append ( docInfo.title ) else append ( "«" .. docInfo.title .. "»" ) end
	end
	
	return title
end

-- блок редакций ---------------------------------------------------------------
--------------------------------------------------------------------------------
function makeEditions ()
	local suffix = "следующих редакциях:"
	if #editions == 0 then do return "" end
	elseif #editions == 1 then suffix = "следующей редакции:"
	end
	
	local caption = mw.html.create()
	caption:tag( "hr" ):css( "margin-bottom", "2em" ):done()
		:wikitext( "Документ приводится в " .. suffix )
		:tag( "br" ):done()

	local result = mw.html.create( "ul" )
	for i, v in ipairs(editions) do
		if is(v.name) then
			local item = v.name
			if is(v.desc) then item = item .. "&nbsp;— " .. v.desc end
			result:tag ( "li" ):wikitext ( item ):done()
		end
	end
	result:allDone()

	local append = mw.html.create( "div" )
	if is(docInfo.editionsNote) then 
		append:tag( "p" ):wikitext( "'''Примечание:'''<br>" .. docInfo.editionsNote ):done()
	end
	append:tag( "hr" ):css( "margin", "2em auto" ):done()
	if is(docInfo.passed) then
		append
			:tag( "div" )
				:css( "align", "right" )
				:wikitext( docInfo.passed )
				:done()
			:tag( "hr" ):css( "margin", "1em auto" ):done()
	end

	return tostring(caption) .. tostring(result) .. tostring(append)
end

-- заголовок документа ---------------------------------------------------------
--------------------------------------------------------------------------------
function makeHeader ()
	local preHeader = ""
	if is(docInfo.classified) then
		local arms, rso
		if authorities[1].name == "ГКО" then 
			arms = "[[Image:Герб СССР.jpg]]"
			rso = "Подлежит возврату в секретариат ГКО (II часть)"
		end
		preHeader = makeClassification ( arms, rso )
	end
	preHeader = preHeader .. docInfo.arms
	if is(docInfo.style) then 
		preHeader = preHeader .. "<div class='" .. docInfo.style .. "'>" 
	end
	
	local header = mw.html.create()
	header:wikitext( preHeader )
	local headerString = ""
	local date
	if is(docInfo.date) and not docInfo.noDate then 
		date = lang:formatDate ( "j xg Y года", docInfo.date ) 
		if docInfo.uDate then date = "<u>" .. date .. "</u>" end
	end
	local title = is(docInfo.title)
	if title and docInfo.uTitle then title = "<u>" .. title .. "</u>" end
	local num = is(makeDocNum())
	if num and docInfo.uNum then num = "<u>" .. num .. "</u>" end
	
	-- Если есть параметр «КОМУ», то это докладная записка или донесение и ей не нужен такой большой заголовок
	if is(docInfo.to) then
		local auth = {}
		for i, v in ipairs(authorities) do 
			table.insert( auth, getAuthorityName( v.name, G )) 
		end
		local headerText = docInfo.type or ""
		headerText = headerText .. " " .. mw.text.listToText( auth ) .. docInfo.to
		if title then headerText = headerText .. " " .. title end
		local nameFormatted = mw.html.create( "center" )
		nameFormatted
			:css( BOLD )
			:wikitext( mw.text.listToText( headerText ) )
		headerString = tostring( nameFormatted )
		if date then headerString = headerString .. " " .. date end
		header:wikitext( headerString )
		
	-- Это обычный заголовок
	else
		for i, v in ipairs(authorities) do 
			local name
			local case = G; if v.name == NONE then case = N end
			if getAuthorityName( v.name, G ) == "ЦК ВКП(б)" then 
				name = "Центральный Комитет ВКП(б)"
			else
				name = getAuthorityName( v.name, N )
			end
			if is(name) then 
				name = name .. getCountryName( v.name, v.country, case )
				local nameFormatted = mw.html.create( "center" )
				nameFormatted
					:css( BOLDUPPER )
					:wikitext( name )
				headerString = headerString .. tostring(nameFormatted)
			end
		end
		local docType = docInfo.type
		if not is(headerString) and authorities[1] then 
			docType = docType .. " " .. getCountryName( authorities[1].name, authorities[1].country, G )
		end
		header:wikitext( headerString )
			:tag( "br" ):done()
			:tag( "center" )
				:css( BOLDUPPER )
				:wikitext( docType ):done()
		if date then
			local dateString = "от " .. date
			if num then dateString = dateString .. " № " .. num end
			header:tag( "center" )
				:css( BOLD )
				:wikitext( dateString ):done()
				:tag( "br" ):done()
		end
		if title then
			header:tag( "center" )
				:css( BOLDUPPER )
				:wikitext( title ):done()
				:tag( "br" ):done()
		end
	end
	return tostring(header)
end

-- категории -------------------------------------------------------------------
--------------------------------------------------------------------------------
function makeCategories ()
	local type = getDocType(docInfo.type)
	if not is(type) then localAddCat ( s.cat.unknownType ) end
	local nums = { docInfo.num, docInfo.num2, docInfo.num3 }
	for i, v in ipairs(authorities) do 
		local authG = getAuthorityName(v.name, G)
		local country = getCountryName(v.name, v.country, "cat")
		if is(authG) or is(country) then
			local cat = type .. " " .. authG .. country
			if is(docInfo.date) and not docInfo.noDate then 
				cat = cat .. lang:formatDate( " Y года", docInfo.date ) .. "| "
				cat = cat .. lang:formatDate( "m-d", docInfo.date )
				if is(nums[i]) then cat = cat .. " " .. nums[i] end
			end
			localAddCat ( cat )
		else
			localAddCat ( s.cat.unknownAuth )
		end
	end
	return
end

-- Шаблон:Документ/Гриф --------------------------------------------------------
--------------------------------------------------------------------------------
function makeClassification ( arms, rso )
	local c = {
		["ОВ"] = { "Особой важности", "Документы особой важности" },
		["СС"] = { "СОВ. СЕКРЕТНО", "Совершенно секретные документы" },
		["С"] = { "СЕКРЕТНО", "Секретные документы" },
		["СС ОП"] = { "Сов. секретно<br/>(особая папка)", "" },
	}
	c["СС/ОВ"] = c["ОВ"]; c["ОСОБОЙ ВАЖНОСТИ"] = c["ОВ"]; c["Особой важности"] = c["ОВ"]
	c["Сов. секретно"] = c["СС"]; c["СОВ. СЕКРЕТНО"] = c["СС"]
	c["Секретно"] = c["С"]; c["СЕКРЕТНО"] = c["С"]
	c["Сов. секретно (особая папка)"]="СС ОП"
	local classification = c[docInfo.classified] or ""
	if not is(classification) then return "" end
	mw.logObject(classification)
	
	local result = mw.html.create( "table" )
	result:attr ({ ["border"] = "0", ["width"] = "100%" })
		:tag ( "tr" )
			:tag ( "td" )
				:attr ({ ["align"] = "left", ["valign"] = "center", ["width"] = "33%" })
				:wikitext ( rso or "" ):done()
			:tag ( "td" )
				:attr ({ ["align"] = "center", ["valign"] = "center", ["width"] = "33%" })
				:wikitext ( arms or "" ):done()
			:tag ( "td" )
				:attr ({ ["align"] = "right", ["valign"] = "center" })
				:tag ( "s" ):tag ( "u" ):wikitext ( classification[1] ):allDone()
	localAddCat ( classification[2] )
	return tostring ( result )
end

-- номер документа -------------------------------------------------------------
--------------------------------------------------------------------------------
function makeDocNum ()
	if not is(docInfo.num) then return "" end
	local suffix = ""
	if is(docInfo.num2) then suffix = "/" .. docInfo.num2 end
	if authorities[1].name == "ГКО" then 
		return "ГКО-" .. docInfo.num .. mw.ustring.lower(docInfo.classified) .. suffix
	else
		return docInfo.num .. suffix
	end
end

-- Шаблон:Документ/Орган -------------------------------------------------------
-- Возращает склонение названия органа по падежу
--------------------------------------------------------------------------------
function getAuthorityName ( name, case )
	if not is(name) then return "" end
	local cases
	local n = mw.ustring.upper(name)
	local cases = get_entity_from_table_by_name ( authorities_with_cases, n )
	local result = cases and cases[case]
	return result or name
	
end

-- Шаблон:Документ/Вид ---------------------------------------------------------
--------------------------------------------------------------------------------
function getDocType ( type )
	return types[mw.ustring.lower(type)] or ""
end

-- Шаблон:Страна и Шаблон:СтранаДляКатегории -----------------------------------
--------------------------------------------------------------------------------
function getCountryName ( authority, country, case )
	if not country then return "" end
	local sep = ""; if authority then sep = " " end
	local noCountry = [[
		|ВТОРОЙ СЪЕЗД СОВЕТОВ СССР|ВТОРОЙ СЪЕЗД СОВЕТОВ РСФСР|
		|ТРЕТИЙ СЪЕЗД СОВЕТОВ РСФСР|СЕДЬМОЙ СЪЕЗД СОВЕТОВ РСФСР|ВОСЬМОЙ СЪЕЗД СОВЕТОВ РСФСР|
		|ЦК ВКП(Б)|ЦК КПСС|ПОЛИТБЮРО ЦК ВКП(Б)|ПОЛИТБЮРО ЦК КПСС|ВЦИК|ПРЕЗИДИУМ ВЦИК|
		|ГКО|СВГК|СТАВКА ВГК|СТАВКА ВЕРХОВНОГО ГЛАВНОКОМАНДОВАНИЯ|
		|САНКТ-ПЕТЕРБУРГСКИЙ ГОРСОВЕТ|ЛЕНСОВЕТ|
	]]
	if authority and mw.ustring.find ( noCountry, "|" .. mw.ustring.upper ( authority ) .. "|", 1, true ) then return "" end
	
	local result = ""
	local cases = get_entity_from_table_by_name ( countries_with_cases, country )  -- падежи
	if cases then 
		if case == "cat" then 
			result = cases[case] or cases[G] or country
		else
			result = cases[case] or country 
		end
	else 
		result = country 
	end
	return sep .. result
end

-- Шаблон:Ссылка на орган власти в Википедии -----------------------------------
--------------------------------------------------------------------------------
function wpLink ( authority, country, case )
	if authority == NONE then return "" end
	local _auth = getAuthorityName ( authority, case or N )
	local authN = getAuthorityName ( authority, N )
	local authG = getAuthorityName ( authority, G )
	local _ctry = getCountryName ( authority, country, case or N )
	local ctryG = getCountryName ( authority, country, G )
	local function formatLink ( pattern ) return string.format ( pattern, authG, _ctry ) end
	local links = {
		-- Органы, которые в Викитеке и Википедии называется по-разному (ЦК ВКП(б) и ЦК КПСС и проч.)
		["ЦЕНТРАЛЬНЫЙ КОМИТЕТ ВКП(Б)"] = formatLink ( "[[w:ЦК КПСС|%s%s]]" ),
		["СОВЕТ РЕСПУБЛИК ВС СССР"] = formatLink ( "[[w:Верховный Совет СССР|%s%s]]" ),
		["ПРЕЗИДИУМ ВСЕРОССИЙСКОГО ЦЕНТРАЛЬНОГО ИСПОЛНИТЕЛЬНОГО КОМИТЕТА"] = formatLink ( "[[w:Всероссийский Центральный Исполнительный Комитет|%s%s]]" ),
		["ПОЛИТБЮРО ЦК ВКП(Б)"] = formatLink ( "[[w:Политбюро ЦК КПСС|%s%s]]" ),
		["ТРЕТИЙ СЪЕЗД СОВЕТОВ РСФСР"] = formatLink ( "[[w:III Всероссийский съезд Советов|%s]]" ),
		["ВТОРОЙ СЪЕЗД СОВЕТОВ СССР"] = formatLink ( "[[w:II съезд Советов СССР|%s%s]]" ),
		["СТАВКА ВЕРХОВНОГО ГЛАВНОКОМАНДОВАНИЯ"] = formatLink ( "[[w:Ставка Верховного Главнокомандования|%s%s]]" ),
		-- Органы, для которых нет ссылки в Википедии
		[false] = _auth or authG,
		-- Остальные органы
		[true] = string.format ( "[[w:%s%s|%s%s]]", authN, ctryG, authG, ctryG ),
	}
	-- aliases
	links["КОМАНДОВАНИЕ 20-Й АРМИИ"] = links[false]
	links["СВГК"] = links["СТАВКА ВЕРХОВНОГО ГЛАВНОКОМАНДОВАНИЯ"]
	links["СТАВКА ВГК"] = links["СТАВКА ВЕРХОВНОГО ГЛАВНОКОМАНДОВАНИЯ"]

	local result = links[mw.ustring.upper(authN)] or links[true]
	return result
end


-- Используется для итерации по значениям в таблицах по падежам (см. выше json)
-- Аргументы: таблица, название
function get_entity_from_table_by_name ( tbl, name )
	for i, a in ipairs(tbl['list']) do 
		if a['aliases'] then
			for i, v in ipairs(a['aliases']) do 
				if v == name then
					return a
				end
			end
		end
	end	
end

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

-- добавление категории в таблицу
function localAddCat ( cat ) if is(cat) then table.insert( categories, "[[Категория:" .. cat .. "]]" ) end end

return p