Модуль:Publication

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

Реализует функциональность шаблона {{книга}} и {{статья}} средствами Lua.

На Модуль:Publication/Песочница есть функции из w:Модуль:Публикация Википедии, для тамошнего более сложного w:Шаблон:Публикация

local p = {}

-- объект с методами. здесь сборка результата
local tpl = {t = {}}
function tpl:add(s) if type(s) == 'string' then table.insert(self.t, s) 
	elseif type(s) == 'table' then table.insert(self.t, table.concat(s)) end end
function tpl:result() return table.concat(self.t) end


function p.render(frame)
	local BOOK, ARTICLE; if frame.args[1] == 'book' then BOOK = true 
	elseif frame.args[1] == 'article' then ARTICLE = true else return end
   
	-- параметры шаблона
	local pargs = frame:getParent().args
	-- mw.logObject(pargs,"pargs")
	local ref = is(pargs['ref'])
	local letter = is(pargs['буква'])
	local author; if is(pargs['автор']) then author = mw.text.trim(pargs['автор']:gsub('<.->', '')) end
	local part = is(pargs['часть'])
	local ilink = is(pargs['ссылка'])
	local ilink_part = is(pargs['ссылка часть'])
	local wslink_part = is(pargs['часть викитека']) or is(pargs['викитека часть'])
	local title = is(pargs['заглавие'])
	local wslink = is(pargs['викитека'])
	local wplink = is(pargs['википедия часть']) or is(pargs['википедия']); if ARTICLE then 
		wplink = is(pargs['википедия']) end
	local commonslink = is(pargs['викисклад'])
	local ilink_ed = is(pargs['ссылка издание'])
	local wslink_ed = is(pargs['викитека издание'])
	local wplink_ed = is(pargs['википедия издание'])
	local commonslink_ed = is(pargs['викисклад издание'])
	local original = is(pargs['оригинал'])
	local volumes = is(pargs['томов'])
	local ptype = is(pargs['тип'])
	local contributors = is(pargs['ответственный'])
	local nodot = is(pargs['nodot'])
	local edition = is(pargs['издание'])
	local author_edition = is(pargs['автор издания'])
	local place = is(pargs['город']) or is(pargs['место'])
	local publisher = is(pargs['издательство'])
	local year = is(pargs['год'])
	local month = is(pargs['месяц'])
	local day = is(pargs['число']) or is(pargs['день'])
	local volume_as_is = is(pargs['том как есть'])
	local volume = is(pargs['том'])
	local volume_en = is(pargs['volume'])
	local band = is(pargs['band'])
	local issue = is(pargs['выпуск'])
	local issue_number = is(pargs['номер'])
	local pages_as_is = is(pargs['страницы как есть'])
	local pages = is(pargs['страницы']); pages = hyphen2dash(pages)
	local columns = is(pargs['столбцы'])
	local pagesof_as_is = is(pargs['страниц как есть'])
	local pagesof = is(pargs['страниц'])
	local pages_en = is(pargs['pages'])
	local columns_en = is(pargs['columns'])
	local seite = is(pargs['seite'])
	local kolonnen = is(pargs['kolonnen'])
	local allpages = is(pargs['allpages'])
	local alleseiten = is(pargs['alleseiten'])
	local series = is(pargs['серия'])
	local tirage = is(pargs['тираж'])
	local isbn = is(pargs['isbn']) or is(pargs['ISBN'])
	local issn = is(pargs['issn']) or is(pargs['ISSN'])
	local doi = is(pargs['doi']) or is(pargs['DOI'])
	local lang = is(pargs['lang']) or is(pargs['language']) or is(pargs['язык'])
	
	-- тег и id
	tpl:add('<span class="citation" ')
	if ref then	
		year = year or ''
		letter = letter or ''
		tpl:add('id="'..mw.uri.anchorEncode( ref .. year .. letter )..'"')  
	end
	tpl:add('>')
	
	if author then 
		tpl:add('<i>'..nowrap(author)..'</i>')
		if not endswith_dot(author) then tpl:add('.') end
		tpl:add(' ')
	end
	
	if part then
		part = strip_end_dot(part)
		tpl:add(link(part, wslink_part, nil, nil, ilink_part))  -- часть, делать ссылкой
		tpl:add(' // ')
	end
	
	if title then
		title = strip_end_dot(title)
		tpl:add(link(title, wslink, wplink, commonslink, ilink))  -- заглавие, делать ссылкой если дана
	end

	if original then 
		original = strip_end_dot(original)
		tpl:add(' = '..original)
	end
	
	if volumes then tpl:add(' : в '..volumes..' т.') end
	
	-- if lang then
	-- 	local s = 'шаблон:ref-'..lang
	--  	if mw.title.new(s).exists then s = ' '..frame:expandTemplate{title=s} else s = ' ('..lang..')' end
	--  	tpl:add(s)
 --	end
 
	if ptype and BOOK then tpl:add(' : '..ptype) end
	
	-- ответственные
	if contributors then
		tpl:add(' / '..contributors)
	end
	
	-- точка, если заголовок не кончается на символы пунктуации
	if not contributors 
		and not volumes 
		and ((title and not endswith_punctuation(title)) or (original and not endswith_punctuation(original))) 
		and not (ARTICLE and edition) then 
			tpl:add('.') end
	
	if edition then 
		if BOOK then
			tpl:add(' — '..edition..'.')  -- издание
		elseif ARTICLE then 
			edition = strip_end_dot(edition)
			if author_edition then 
				tpl:add(' // <i>'..author_edition..'</i> '..edition)
			else  
				if title then
					tpl:add(' // ')
				end
				tpl:add(link(edition, wslink_ed, wplink_ed, commonslink_ed, ilink_ed))
			end
			if ptype and ARTICLE then tpl:add(' : '..ptype) end
			tpl:add('.')
		end
	end
	
	if place or publisher or year then tpl:add(place_publisher_year(place, publisher, year)) end
	
	if ARTICLE then 
		if month then
			if day then
				local d = tonumber(day)
				local m = tonumber(month)
				local s = ''
				if (d>=1 and d <= 31) and (m>=1 and m <= 12) then s = '0000-'..month..'-'..day end
				tpl:add('&nbsp;— '.. mw.getContentLanguage():formatDate('j xg', s))
			end
		end
	end
	
	if BOOK then
		if (volume_as_is or volume or volume_en or band) and title then	tpl:add(' — ') end
		if volume_as_is then tpl:add(volume_as_is..'.') 
		elseif volume then tpl:add('Т. '..volume..'.')
		elseif volume_en then tpl:add('Vol. '..volume_en..'.') 
		elseif band then tpl:add('Bd. '..band..'.') 
		end
		
		if pagesof_as_is then tpl:add(' — '..pagesof_as_is..'.') 
		elseif pages then 
			tpl:add(' — С. ')
			if columns then tpl:add('['..pages..'] (стб. '..columns..')')	else tpl:add(pages) end
			tpl:add('.')
		elseif pagesof_as_is then tpl:add(' — '..pagesof_as_is..'.')
		elseif pagesof then tpl:add(' — '..pagesof..' с.') 
		elseif pages_en then
			tpl:add(' — P. ')
			if columns then tpl:add('['..pages_en..'] (col. '..columns..').')	else tpl:add(pages_en) end
		elseif seite then
			tpl:add(' — S. ')
			if kolonnen then tpl:add('['..seite..'] (Kol. '..kolonnen..').') else tpl:add(seite) end
		elseif allpages then tpl:add(' — '..allpages..' p.')
		elseif alleseiten then tpl:add(' — '..alleseiten..' S.') 
		end
			
		if series then tpl:add(' — ('..series..').') end
		if tirage then tpl:add(' — '..tirage..' экз.') end
		if isbn then tpl:add(' — ISBN '..isbn..'.') end
		if doi then tpl:add(' — '..doi) end
	
	elseif ARTICLE then 
		if volume or volume_en or band or issue or issue_number then
			if month then tpl:add(' (') else tpl:add(' — ') end
			
			if volume then	
				if month then tpl:add('т. '..volume) 
				else tpl:add('Т. '..volume) end
			end
			if volume_en then	
				if month then tpl:add('vol. '..volume_en) 
				else tpl:add('Vol. '..volume_en) end
			end
			if band then
				if month then tpl:add('bd. '..band) 
				else tpl:add('Bd. '..band) end
			end
			if issue then	
				if volume then 
					tpl:add(', вып. '..issue) 
				else
					if month then tpl:add('вып. '..issue)
					else tpl:add('Вып. '..issue) end
				end
			end
			if issue_number then
				if (volume or volume_en or band) then 
					tpl:add(', № '..issue_number) 
				else
					if month then tpl:add('№ '..issue_number)
					else tpl:add('№ '..issue_number) end
				end
			end
			
			if month then tpl:add(')') end
			
			-- if issue_number then
			-- 	if (volume or volume_en or band) then 
			-- 		tpl:add(', № '..issue_number) 
			-- 	else
			-- 		tpl:add(' — № '..issue_number)
			-- 	end
			-- end
			
			tpl:add('.')
		end
		
		
		if pages then 
			tpl:add(' — С. '..pages)
			tpl:add('.')
		elseif pages_en then
			tpl:add(' — P. '..pages_en)
			tpl:add('.')
		end
		
		if isbn then tpl:add(' — ISBN '..isbn..'.') end
		if issn then tpl:add(' — [[ISSN]]  '..issn..'.') end
		if doi then tpl:add(' — '..doi) end
		
	end
	
	
	tpl:add('</span>')
	-- mw.logObject(tpl)
	return tpl:result()
end

-- ***********

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

-- выбор приоритетной переменной из двух. если есть обе - первой. если нет обоих - ''
function onevar(var1,var2)
    if (var1 and var1 ~= '') then return var1  elseif (var2 and var2 ~= '') then return var2  else return '' end
end

-- создание ссылки на ВТ, ВП, Commons, интернет
function link(anchor, wslink, wplink, commonslink, inetlink)
	if is(anchor) then
		if     is(wslink) 	then return '[[s:ru:'..wslink..'|'..anchor..']]'
		elseif is(wplink) 	then return '[[w:ru:'..wplink..'|'..anchor..']]'
		elseif is(commonslink) then return '[[commons:'..commonslink..'|'..anchor..']]'
		elseif is(inetlink) then return '['..inetlink..' '..anchor..']'
		else return anchor end
	end
end

-- место, издательство, год
function place_publisher_year(place, publisher, year)
	local t = {}; function add(s) table.insert(t, s) end
	if place or publisher or year then 
		add(' — ')
		if place and publisher and year then add(place..': '..publisher..', '..year)
		elseif place and publisher then add(place..': '..publisher)
		elseif place and year then add(place..', '..year)
		elseif publisher and year then add(publisher..', '..year)
		elseif place then add(place)
		elseif publisher then add(publisher)
		elseif year then add(year)
		end
		add('.')
		return table.concat(t)
	else return ''
	end
end

function nowrap(s) return '<span style="white-space: nowrap;">'..s..'</span>' end

-- дефис в тире
function hyphen2dash(s)
	if not s then return end
	local patterns = { "%[%[[^|%]]+|", "%[%[[^|%]]+%]%]", "%[http" }  -- исключения
	for _, pattern in pairs(patterns) do
		if mw.ustring.find ( s, pattern ) then return s end
	end
	return s:gsub( '%s*-%s*', '—' )
end

function strip_end_dot(s)
	if mw.ustring.find(s, '%.%.%.$')
		or mw.ustring.find(s, '…') 
		or mw.ustring.find(s, '%?%.%.$') 
		or mw.ustring.find(s, '%!%.%.$') then s = mw.ustring.gsub(s, '%.$', '') end
	return s
end
function endswith_dot(s) if s and (s:match('%.$') or s:match('%.%]%]$')) then return true end end
function endswith_punctuation(s) if s and mw.ustring.find(s, '[!?.]', -1) then return true end end

return p