모듈:행간주석

이 모듈에 대한 설명문서는 모듈:행간주석/설명문서에서 만들 수 있습니다

local p = {}

local function trim(s)
	return s and mw.text.trim(s) or s
end

local function smartSplit(s)
	local result = {}
	if not s then return result end
	local braceDepth = 0  -- {{ }} 깊이
	local linkDepth = 0   -- [[ ]] 깊이
	local tagDepth = 0    -- < > 깊이 (HTML 태그 안쪽)
	local buf = {}
	local i = 1
	local len = #s

	local function inProtected()
		return braceDepth > 0 or linkDepth > 0 or tagDepth > 0
	end

	while i <= len do
		local two = s:sub(i, i + 1)
		local c = s:sub(i, i)

		if two == '{{' then
			braceDepth = braceDepth + 1
			table.insert(buf, two)
			i = i + 2
		elseif two == '}}' then
			if braceDepth > 0 then braceDepth = braceDepth - 1 end
			table.insert(buf, two)
			i = i + 2
		elseif two == '[[' then
			linkDepth = linkDepth + 1
			table.insert(buf, two)
			i = i + 2
		elseif two == ']]' then
			if linkDepth > 0 then linkDepth = linkDepth - 1 end
			table.insert(buf, two)
			i = i + 2
		elseif c == '<' and tagDepth == 0 and braceDepth == 0 then
			tagDepth = tagDepth + 1
			table.insert(buf, c)
			i = i + 1
		elseif c == '>' and tagDepth > 0 then
			tagDepth = tagDepth - 1
			table.insert(buf, c)
			i = i + 1
		else
			if c:match('%s') and not inProtected() then
				if #buf > 0 then
					table.insert(result, table.concat(buf))
					buf = {}
				end
			else
				table.insert(buf, c)
			end
			i = i + 1
		end
	end
	if #buf > 0 then
		table.insert(result, table.concat(buf))
	end
	return result
end

local function looksLikeAbbrev(text)
	if not text then return false end
	if text:find('{{') or text:find('%[%[') or text:find('<') then return false end
	if text:find('%a') and not text:find('%l') then
		return true
	end
	return false
end

local ALIASES = {
	orig        = { '원어', '原語' },
	trans       = { '전사', '転写' },
	gloss       = { '주석', '注釈' },
	translation = { '번역', '翻訳' },
	source      = { '출처', '出典' },
	glossstyle  = { '주석스타일', '注釈スタイル' },
}

function p.gloss(frame)
	local parentArgs = frame:getParent() and frame:getParent().args or {}
	local args = frame.args

	local function getArg(field, suffix)
		suffix = suffix or ''
		for _, name in ipairs(ALIASES[field]) do
			local key = name .. suffix
			local v = args[key]
			if v ~= nil and trim(v) ~= '' then return trim(v) end
			v = parentArgs[key]
			if v ~= nil and trim(v) ~= '' then return trim(v) end
		end
		return nil
	end

	local glossStyleOff = (getArg('glossstyle') == '없음' or getArg('glossstyle') == 'なし')

	local words = {}

	local i = 1
	while true do
		local w = getArg('orig', i)
		local g = getArg('gloss', i)
		local t = getArg('trans', i)
		if not w and not g then break end
		table.insert(words, { orig = w or '', trans = t, gloss = g or '' })
		i = i + 1
	end

	if #words == 0 then
		local origs = smartSplit(getArg('orig'))
		local transs = smartSplit(getArg('trans'))
		local glosses = smartSplit(getArg('gloss'))
		for idx, o in ipairs(origs) do
			table.insert(words, { orig = o, trans = transs[idx], gloss = glosses[idx] or '' })
		end
	end

	local translation = getArg('translation')
	local source = getArg('source')

	local container = mw.html.create('div')
		:addClass('interlinear-gloss')
		:css('display', 'block')
		:css('margin', '1rem 0')
		:css('line-height', '1.4')

	local row = container:tag('div')
		:css('display', 'flex')
		:css('flex-wrap', 'wrap')
		:css('column-gap', '1em')
		:css('row-gap', '0.3em')

	for _, w in ipairs(words) do
		local cell = row:tag('div')
			:css('display', 'inline-block')
			:css('text-align', 'left')
			:css('vertical-align', 'top')

		cell:tag('div')
			:css('white-space', 'nowrap')
			:wikitext(w.orig)

		if w.trans and w.trans ~= '' then
			cell:tag('div')
				:css('font-style', 'italic')
				:css('white-space', 'nowrap')
				:wikitext(w.trans)
		end

		local glossCell = cell:tag('div')
			:addClass('interlinear-gloss-text')
			:css('white-space', 'nowrap')

		if not glossStyleOff and looksLikeAbbrev(w.gloss) then
			glossCell:css('font-variant', 'small-caps')
		end

		glossCell:wikitext(w.gloss)
	end

	if translation then
		container:tag('div')
			:css('margin-top', '0.4em')
			:wikitext('‘' .. translation .. '’')
	end

	if source then
		container:tag('div')
			:css('margin-top', '0.2em')
			:css('font-size', '90%')
			:wikitext(source)
	end

	return tostring(container)
end

return p