Lompat ke isi

Modul:kelas

Dari Wikikato

Dokumentasi untuk modul ini dapat dibuat di Modul:kelas/doc

local p = {}

local langModule = require("Modul:bahasa")
local linkModule = require("Modul:pranala")
local utils = require("Modul:utilitas")

-- POS types
local posTypes = {
	-- content words
	n    = "Kato bando",
	pn   = "Namo diri", -- proper noun < noun
	v    = "Kato karajo",
	ptcp = "Partisip", -- participle < verb
	adj  = "Kato sipaik",
	num  = "Kato bilangan",
	adv  = "Kato katarangan",
	-- function words
	pron = "Kato ganti",
	conj = "Kato sambuang",
	intj = "Kato saru",
	ptcl = "Partikel",
	det  = "Panantu",
	art  = "Artikel",
	clf  = "Panggoloang",
	-- adpositions
	prep  = "Kato muko",
	postp = "Kato balakang",
	circp = "Kato apik",
	ambip = "Ambiposisi",
	-- morphemes
	pref   = "Awalan",
	suf    = "Akiran",
	inf    = "Sisipan",
	circf  = "Apitan",
	intf   = "Sambuangan",
	rt   = "Aka",
	-- phrase
	ph = "Frasa",
	pb = "Papatah-patitiah",
	-- other
	rom = "Latin",
	ltr  = "Uruih",
	sym  = "Lambang"
}

-- Special separators
local specialLabels = {
	["atau"] = true,
	["dan"]   = true,
}

-- Parse <entry:...> or <nolink:1>
local function parseTag(item)
	if not item then return item, nil, false end
	local base, display = mw.ustring.match(item, "^(.-)<entry:(.-)>$")
	if base then return base, display, false end
	local base2 = mw.ustring.match(item, "^(.-)<nolink:1>$")
	if base2 then return base2, nil, true end
	return item, nil, false
end

-- Strip inline tags like <q:...>, <t:...>, <lit:...>, etc.
local function stripInlineTags(text)
	if not text then return text end
	return text
		:gsub("<tr:.->", "")
		:gsub("<t:.->", "")
		:gsub("<lit:.->", "")
		:gsub("<id:.->", "")
		:gsub("<entry:.->", "")
		:gsub("<q:.->", "")
		:gsub("<class:.->", "")
end

-- Format a single item
local function formatItem(item, isForm, lang, nolinkGlobal)
	if not item or item == "" then
		return ""
	elseif isForm then
		local base, display, nolinkTag = parseTag(item)
		local forceNolink = nolinkTag or (nolinkGlobal and not display)

		-- Keep the original 'base' (with inline tags) so Modul:links can parse it.
		local rawBase = base or item

		-- Create a cleaned display string for the visible link text (strip inline tags)
		local function stripInlineTagsLocal(text)
			if not text then return text end
			return text
				:gsub("<tr:.->", "")
				:gsub("<t:.->", "")
				:gsub("<lit:.->", "")
				:gsub("<id:.->", "")
				:gsub("<entry:.->", "")
				:gsub("<q:.->", "")
				:gsub("<class:.->", "")
		end

		-- If an explicit <entry:...> display was provided, prefer that (but cleaned).
		local cleanedDisplay = stripInlineTagsLocal(display or rawBase or item)

		if forceNolink then
			return "<b>" .. (cleanedDisplay or rawBase or item) .. "</b>"
		else
			-- Pass the original rawBase (so Modul:links.parseInline sees the inline tags),
			-- but pass a cleaned 'entry' so the visible link text doesn't show the tags.
			return linkModule.makeMention{
				[1] = lang or "",
				[2] = rawBase or "",
				entry = cleanedDisplay or "",
				notext = "1",
				noitalic = "1",
				bold = "1",
			}
		end
	else
		return "<i>" .. item .. "</i>"
	end
end

-- Collect params
local function getLabelFormParams(args)
	local params = {}
	for i = 2, 20 do
		local v = args[tostring(i)]
		if v then table.insert(params, v) end
	end
	return params
end

-- Build label/form string
local function buildLabelForm(params, lang, nolink)
	if not params or #params == 0 then return "" end

	local out = {}
	local currentType = "label"
	local prevWasSep = true

	local function render(raw, typeOverride)
		if specialLabels[raw] then
			return "<i>" .. raw .. "</i>", "word-sep"
		elseif raw == "_" then
			return "", "space-sep"
		elseif raw == "" or raw == "," then
			return "", "blank"
		else
			local isForm = (typeOverride == "form")
			return formatItem(raw, isForm, lang, nolink), "normal"
		end
	end

	for i, raw in ipairs(params) do
		local text, kind = render(raw, currentType)

		if kind == "normal" and text ~= "" then
			if #out > 0 and not prevWasSep and currentType ~= "form" then
				table.insert(out, ", ")
			elseif #out > 0 then
				table.insert(out, " ")
			end
			table.insert(out, text)

			if not (params[i+1] and (specialLabels[params[i+1]] or params[i+1] == "_" or params[i+1] == "" or params[i+1] == ",")) then
				currentType = (currentType == "label") and "form" or "label"
			end

			prevWasSep = false

		elseif kind == "word-sep" then
			table.insert(out, " " .. text)
			prevWasSep = true

		elseif kind == "space-sep" then
			if #out > 0 and string.sub(out[#out], -1) ~= " " then
				table.insert(out, " ")
			end
			prevWasSep = true

		elseif kind == "blank" then
			prevWasSep = false
		end
	end

	local result = table.concat(out, "")
	if result == "" then return "" end
	return '<span style="font-size:0.95em;">[' .. result .. ']</span>'
end

-- Determine if categories should be added
local function shouldAddCat(args)
	local nocat = args and args.nocat or ""
	local title = mw.title.getCurrentTitle()
	if nocat == "1" then return false end
	if title.namespace ~= 0 and title.nsText ~= "Lampiran" then return false end
	return true
end

-- Build POS
local function buildPOS(frame, pos)
	local args = frame.args or {}
	local lang = args[1] or ""
	local class = args.class or ""
	local sublemma = args.sub == "1"
	local nolink = args.nolink == "1"

	local labelFormStr = buildLabelForm(getLabelFormParams(args), lang, nolink)

	-- Resolve POS name (for categorization only)
	local posName = posTypes[pos] or pos or "Kelas kato"

	-- Categories
	local catString = ""
	if shouldAddCat(args) then
		local cats = {}
		if not lang or lang == "" then
			table.insert(cats, utils.errorcat("sablonan"))
		else
			local langName = langModule.getLangName{ args = { lang } }
			if not langName then
				table.insert(cats, utils.errorcat("basa"))
			else
				local sortkey = utils.getSortkey()
				if sublemma then
					table.insert(cats, utils.langcat(lang, "Sublema", sortkey))
					table.insert(cats, utils.langcat(lang, posName .. "(bantuak)", sortkey))
				else
					table.insert(cats, utils.langcat(lang, "Lema", sortkey))
					table.insert(cats, utils.langcat(lang, posName, sortkey))
				end
				if class and class ~= "" then
					table.insert(cats, utils.langcat(lang, posName .. " " .. class, sortkey))
				end
			end
		end
		catString = table.concat(cats, "")
	end

	-- Output only class label + forms
	local classDisplay = (class ~= "" and
		'<span style="background:var(--light-blue-bg, #F3F6FF); color:var(--faded-font, #333); font-size:0.95em; font-variant:small-caps;">[' .. mw.ustring.lower(class) .. ']</span>') or ""
	local space = (classDisplay ~= "" and labelFormStr ~= "" and " " or "")

	local displayBlock = ""
	if classDisplay ~= "" or labelFormStr ~= "" then
		displayBlock = ': ' .. classDisplay .. space .. labelFormStr
	end

	return displayBlock .. catString
end

-- POS entry points
for code, _ in pairs(posTypes) do
	p[code] = function(frame) return buildPOS(frame, code) end
end

-- Generic main entry point
p.main = function(frame)
	local args = frame.args or {}
	local pos = args.pos or ""
	if pos == "" then
		return error("Galat: Parameter pos diperlukan")
	end
	return buildPOS(frame, pos)
end

-- Return the display name for a POS code
function p.posname(frame)
	local args = frame.args or {}
	local code = args[1] or args.pos or ""
	if code == "" then
		return error("Galat: Kelas kata tidak ada")
	end
	return posTypes[code] or code
end

return p