모듈:Category

최근 편집: 2017년 10월 28일 (토) 13:33
낙엽1124 (토론 | 기여)님의 2017년 10월 28일 (토) 13:33 판 (분류가 넘겨주기 된 경우 분류:분류가 넘겨주기 된 문서 를 추가합니다.)

알려진 문제

순환 참조가 발생했을 시 ?action=edit으로 내용을 변경하기 전까지 문서 로딩이 되지 않습니다.


local p = {}

-------------------------------------
-- 주어진 분류들을 표시하기 위한 HTML 코드를 만듭니다.
-- @param categories 표시할 분류들.
-- @param frame 호출되면서 자동으로 만들어진 frame 객체.
-- @return "<div id='fw-catlinks' class='fw-catlinks catlinks'>"로 시작하는 HTML 문자열을 반환합니다.
-------------------------------------
local function makeCatlinks(categories, frame)
	local listItems = ''
	for i, v in ipairs(categories) do
		if v ~= '' then 
			listItems = listItems .. frame:callParserFunction('#tag:li', '[[:분류:'..categories[i]..'|'..categories[i]..']]')
		end
	end

	return frame:callParserFunction {
		name = '#tag:div', 
		args = {
			id = 'fw-catlinks', 
			class = 'fw-catlinks catlinks', 
			['data-mw'] = 'interface', 
			frame:callParserFunction{
				name = '#tag:div', args = {
					class = 'mw-normal-catlinks',
					'[[특수:다면분류|분류]]:' .. frame:callParserFunction('#tag:ul', listItems)
				}
			}
		}
	}
end

-------------------------------------
-- 전달인자들이 포함하고 있는 분류 정보를 묶어 정해진 형태의 배열로 만듭니다.
-- @param args args은 다음 중 하나의 형태일 수 있습니다:
-- { 'A/B' } (권장)
-- { 'A/B, C/D' } (권장)
-- { 'A/B|C/D' }
-- { 'A|B|C|D' }
-- { 'A', 'B', 'C', 'D' }
-- { 'A/B', 'C/D' }
-- @return "A/B" 형식의 문자열들을 담은 배열.
-------------------------------------
local function safeCategories(args)
	if type( args ) == 'string' then args = { args } end

	local temp = {}
	--첫 번재 전달인자에 '|'가 있다면 '|'를 기준으로 분리시킵니다(예: 'A|B|C|D'이나 'A|B')
	if string.match(args[1], '|') ~= nil then
		for word in string.gmatch(args[1],'%s*([^%|]+)%s*') do
			temp[#temp+1] = word
		end
		args = temp
	end

	--첫 번재 전달인자에 슬래시가 없는데 전달인자가 하나라면 오류(예: 'A'), 첫 번재 전달인자에 슬래시가 없으면서 여럿이라면 슬래시를 추가하여 둘씩 묶습니다(예: 'A', 'B', 'C', 'D').
	if string.find(args[1],'/') == nil then
		if #args == 1 then
			error('사용하신 구문은 다면분류가 아닙니다. [[도움말:문서 분류하기]]를 참고해 주세요.',0)
		else
			temp = {}
			for i, v in ipairs(args) do
				if i % 2 ~= 0 then
					temp[#temp+1] = string.match(v,"^%s*(.-)%s*$")
				else
					temp[#temp] = temp[#temp] .. '/' .. string.match(v,"^%s*(.-)%s*$")
				end
			end
			args = temp
		end
	end

	--첫 번재 전달인자에 쉼표가 있다면 쉼표를 기준으로 각각을 분리합니다('A/B, C/D').
	if string.match(args[1],',') ~= nil then
		temp = {}
		for word in string.gmatch(args[1],'%s*([^,]+)%s*') do
			temp[#temp+1] = word
		end
		args = temp
	end

	--전체적으로 trim 합니다.
	for i in ipairs(args) do
		args[i] = string.match(args[i],"^%s*(.-)%s*$")
	end

	return args
end

-------------------------------------
-- 주어진 분류들로 문서를 분류하고 분류들을 표시하기 위한 위키텍스트를 만듭니다.
-- @param categories 표시할 분류들.
-- @param showCatlinksDisplay 반환 문자열에 분류 표시 문단을 포함할지의 여부.
-- @param frame 호출되면서 자동으로 만들어진 frame 객체.
-- @return 위키텍스트을 반환합니다. 전달인자가 올바르지 않을 경우에는 오류 메시지를 출력할 수 있는 위키텍스트를 반환합니다.
-------------------------------------
local function _categorize(categories, showCatlinksDisplay, frame)
	local returnText, title, superCategories, content, redirected = '', '', '', '', false

	for i, v in ipairs(categories) do
		if v == nil then
			error("사용하신 분류 문법이 잘못되었습니다. [[도움말:문서 분류하기]]를 참고해 주세요.",0)
			return ''
		end

		title = mw.title.new('분류:'..v)
		if title.exists and title.isRedirect then
			if not redirected then redirected = true end
			title =  mw.title.new(string.match(title:getContent(),"%[%[([^%[%]|]-)%]%]")) or title
			v = title.text
			categories[i] = title.text
		end

		returnText = returnText .. '[[분류:' .. v .. ']]'

		if title.exists then
			content = title:getContent()
			superCategories = string.match(content,"%{%{%s*분류%s*|%s*([^}]-)%s*%}%}")
			if superCategories ~= nil then
				returnText = returnText .. _categorize(safeCategories(superCategories), false, frame)
			end

			if string.match(content,"%[%[분류:접힌 분류%]%]") ~= nil then
				categories[i] = ''
			end
		end
	end

	if showCatlinksDisplay then
		returnText = returnText .. makeCatlinks(categories, frame)
		if redirected then returnText = returnText .. '[[분류:분류가 넘겨주기 된 문서]]' end
	end

	return returnText
end

-------------------------------------
-- frame 객체가 틀에서 호출되어 생긴 frame인지 바로 모듈이 호출되어 생긴 frame인지와 무관하게 args를 찾습니다.
-- @param frame 호출되면서 자동으로 만들어진 frame 객체.
-- @return args 호출되면서 전달받은 전달인자.
-------------------------------------
local function safeArgs(frame)
	if frame.args[1] ~= nil then --frame은 metatable이라 next(frame.args)가 안 된다고 하여 이리 되었습니다.
		return frame.args
	else
		return frame:getParent().args
	end
end

-------------------------------------
-- 주어진 분류들로 문서를 분류하고 분류들을 표시하기 위한 위키텍스트를 만듭니다. 만약 "{{#invoke:Category|categorize|성격/단체, 성향/페미니즘}}"과 같이 호출되었다면 다음 작업을 수행합니다:
-- 	반환값에 "[[분류:성격/단체]]"를 추가합니다.
-- 	"분류:성격/단체"라는 문서가 있는지, 있다면 상위분류가 있는지를 확인합니다.
-- 		둘다 맞다면 반환값에 "분류:성격/단체"를 전개하여 추가합니다.(해당 틀은 이 함수를 재귀호출합니다.)
-- 	'성향/페미니즘'에 대해서도 같은 작업을 수행합니다.
-- @param frame 호출되면서 자동으로 만들어진 frame 객체.
-- @return 위키텍스트을 반환합니다. 전달인자가 올바르지 않을 경우에는 오류 메시지를 출력할 수 있는 위키텍스트를 반환합니다.
-------------------------------------
function p.categorize(frame)
	return _categorize(safeCategories(safeArgs(frame)), true, frame)
end

-------------------------------------
-- 다면분류에서 패싯을 찾습니다. 예를 들어 "A/B"를 인자로 받으면 A를 반환합니다.
-- @param frame 호출되면서 자동으로 만들어진 frame 객체.
-- @return 패싯 문자열.
-------------------------------------
function p.facet(frame)
	local text = ''
	if type(frame) == 'string' then text = frame 
	else text = frame.args[1] end
	local slash = string.find(text,'/')
	if slash == nil then return text end 
	return string.sub(text,1,slash-1)
end

-------------------------------------
-- 다면분류에서 멤버를 찾습니다. 예를 들어 "A/B"를 인자로 받으면 B를 반환합니다.
-- @param frame 호출되면서 자동으로 만들어진 frame 객체.
-- @return 멤버 문자열.
-------------------------------------
function p.member(frame)
	local text = ''
	if type(frame) == 'string' then text = frame 
	else text = frame.args[1] end
	local slash = string.find(text,'/')
	if slash == nil then return text end
	return string.sub(text,slash+1,#text)
end

return p