پرش به محتوا

پودمان:AlborzInfoBox: تفاوت میان نسخه‌ها

از ویکی البرز
جزبدون خلاصۀ ویرایش
جزبدون خلاصۀ ویرایش
 
(۱۲ نسخهٔ میانیِ ایجادشده توسط همین کاربر نشان داده نشد)
خط ۱: خط ۱:
local p = {}
local p = {}


local data = mw.loadData('Module:AlborzInfoBox/Data/Geography')
------------------------------------------------------------------------
-- DATA
------------------------------------------------------------------------


-------------------------------------------------------
local data = mw.loadData("Module:AlborzInfoBox/Data/Geography")
 
------------------------------------------------------------------------
-- NORMALIZE
-- NORMALIZE
-------------------------------------------------------
------------------------------------------------------------------------
local function norm(s)
 
    if not s then return nil end
local function norm(value)
    s = mw.text.trim(s)
 
    s = mw.ustring.gsub(s, "[\u200C\u200D]", "") -- حذف ZWNJ و ZWJ
if value == nil then
    s = mw.text.trim(s)
return nil
    return s
end
 
value = tostring(value)
 
value = mw.text.trim(value)
 
-- حذف نیم‌فاصله و کاراکترهای نامرئی
value = mw.ustring.gsub(value, "[\u200C\u200D\uFEFF]", "")
 
-- یکسان‌سازی فاصله‌ها
value = mw.ustring.gsub(value, "%s+", " ")
 
-- حروف عربی → فارسی
value = mw.ustring.gsub(value, "ي", "ی")
value = mw.ustring.gsub(value, "ى", "ی")
value = mw.ustring.gsub(value, "ك", "ک")
 
return mw.text.trim(value)
 
end
 
 
------------------------------------------------------------------------
-- ARGUMENT HANDLING
------------------------------------------------------------------------
 
local function collectArgs(frame)
 
local args = {}
 
local function push(source)
 
if not source then
return
end
 
for key, value in pairs(source) do
 
if value ~= nil then
 
local normalizedKey = norm(key)
local normalizedValue = mw.text.trim(tostring(value))
 
if normalizedKey ~= "" and normalizedValue ~= "" then
args[normalizedKey] = normalizedValue
end
 
end
 
    end
 
end
 
-- آرگومان‌های مستقیم invoke
push(frame.args)
 
-- آرگومان‌های الگوی مادر
local parent = frame:getParent()
 
if parent then
push(parent.args)
end
 
return args
 
end
end


-------------------------------------------------------
-- GET ARG (قوی)
-------------------------------------------------------
local function getArg(args, field)
    if not field then return nil end


    local candidates = {}
------------------------------------------------------------------------
   
-- FIELD VALUE
    -- arg تکی
------------------------------------------------------------------------
    if field.arg then  
 
        table.insert(candidates, field.arg)  
local function getValue(args, field)
    end
 
   
if not field then
    -- args چندگانه
return nil
    if field.args then
end
        for _, a in ipairs(field.args) do  
 
            table.insert(candidates, a)  
local names = {}
        end
 
    end
-- نام اصلی
if field.arg then
table.insert(names, field.arg)
end
 
-- نام‌های جایگزین
if field.args then
 
for _, name in ipairs(field.args) do
table.insert(names, name)
end
 
end
 
-- جست‌وجوی مقدار
for _, name in ipairs(names) do
 
local key = norm(name)
local value = args[key]
 
if value and value ~= "" then
return value
end
 
end
 
-- مقدار پیش‌فرض
if field.default ~= nil then
return field.default
end
 
return nil


    for _, name in ipairs(candidates) do
        local normalized = norm(name)
        local val = args[normalized]
        if val and val ~= "" then
            return val
        end
    end
    return nil
end
end


-------------------------------------------------------
 
-- GET ARGS
------------------------------------------------------------------------
-------------------------------------------------------
-- SAFE WIKITEXT
local function getArgs(frame)
------------------------------------------------------------------------
    local args = {}
 
    local function add(tbl)
local function cleanText(value)
        if not tbl then return end
 
        for k, v in pairs(tbl) do
if value == nil then
            if v and v ~= "" then
return nil
                local normKey = norm(k)
end
                args[normKey] = mw.text.trim(v)
 
            end
value = tostring(value)
        end
 
    end
value = mw.text.trim(value)
    add(frame.args)
 
    local parent = frame:getParent()
if value == "" then
    if parent then add(parent.args) end
return nil
    return args
end
 
return value
 
end
end


-------------------------------------------------------
 
------------------------------------------------------------------------
-- ADD ROW
-- ADD ROW
-------------------------------------------------------
------------------------------------------------------------------------
local function addRow(root, label, value)
 
    if not value or value == "" then return end
local function addRow(root, label, value, raw)
    local tr = root:tag("tr")
 
    tr:tag("th"):wikitext(label)
value = cleanText(value)
    if value:find("%[%[") or value:find("{{") or value:find("|") then
 
        tr:tag("td"):wikitext(value)
if not value then
    else
return
        tr:tag("td"):wikitext(mw.text.encode(value))
end
    end
 
local tr = root:tag("tr")
 
-- Label
local th = tr:tag("th")
 
th
:attr("scope", "row")
:addClass("infobox-label")
:wikitext(label)
 
-- Value
local td = tr:tag("td")
 
td:addClass("infobox-value")
 
if raw then
td:wikitext(value)
else
td:wikitext(mw.text.encode(value))
end
 
end
end


-------------------------------------------------------
 
-- BADGE
------------------------------------------------------------------------
-------------------------------------------------------
-- TYPE BADGE
------------------------------------------------------------------------
 
local badgeMap = {
local badgeMap = {
    city = "شهر",
 
    village = "روستا",
city         = "شهر",
    county = "شهرستان",
village       = "روستا",
    district = "بخش",
county       = "شهرستان",
    ruraldistrict = "دهستان",
district     = "بخش",
     mountain = "کوه",
ruraldistrict = "دهستان",
    cave = "غار",
 
    river = "رودخانه",
neighborhood  = "محله",
     waterfall = "آبشار",
urbanarea     = "منطقه شهری",
    park = "پارک",
 
    historic = "بنای تاریخی",
mountain     = "کوه",
    ["بنای تاریخی"] = "بنای تاریخی"
cave         = "غار",
river         = "رودخانه",
waterfall     = "آبشار",
park         = "پارک",
historic     = "بنای تاریخی"
 
}
}


local function addBadge(root, rawType)
    if not rawType or rawType == "" then return end
    rawType = norm(rawType)
    local label = badgeMap[rawType] or "بنای تاریخی"


    root:tag("tr")
local function addBadge(root, typeKey)
        :tag("td")
 
            :attr("colspan", "2")
local label = badgeMap[typeKey]
            :css("text-align", "center")
 
            :css("padding", "6px 0 8px 0")
-- اگر نوع ناشناخته باشد
            :tag("span")
if not label then
                :css("display", "inline-block")
label = "مکان"
                :css("background", "#e8f0f8")
end
                :css("color", "#1e4b7a")
 
                :css("font-size", "87%")
local tr = root:tag("tr")
                :css("font-weight", "bold")
 
                :css("padding", "3px 12px")
local td = tr:tag("td")
                :css("border-radius", "5px")
 
                :css("border", "1px solid #b0c8e0")
td
                :wikitext(label)
:attr("colspan", "2")
:addClass("infobox-badge-row")
 
local span = td:tag("span")
 
span
:addClass("infobox-badge")
:wikitext(label)
 
end
end


-------------------------------------------------------
 
-- Image & Caption
------------------------------------------------------------------------
-------------------------------------------------------
-- IMAGE
------------------------------------------------------------------------
 
local function isSimpleFilename(value)
 
if not value or value == "" then
return false
end
 
value = mw.text.trim(value)
 
-- اگر خود مقدار شامل ویکی‌متن یا HTML باشد
if value:find("{", 1, true)
or value:find("<", 1, true)
or value:find("|", 1, true)
or value:find("[[", 1, true)
then
return false
end
 
return true
 
end
 
 
------------------------------------------------------------------------
-- IMAGE RENDERER
------------------------------------------------------------------------
 
local function addImage(root, args)
local function addImage(root, args)
    local image = args[norm("تصویر")] or args[norm("پرونده")]
 
    if not image or image == "" then return end
local content =
    image = mw.text.trim(image)
args[norm("تصویر")]
    root:tag("tr")
or args[norm("پرونده")]
        :tag("td")
or args[norm("image")]
            :attr("colspan", "2")
 
            :css("text-align", "center")
if not content or content == "" then
            :wikitext("[[پرونده:" .. mw.uri.encode(image, "WIKI") .. "|250px]]")
return
end
 
content = mw.text.trim(content)
 
local tr = root:tag("tr")
 
local td = tr:tag("td")
 
td
:attr("colspan", "2")
:addClass("infobox-image")
 
if isSimpleFilename(content) then
 
local filename = content
 
filename = mw.ustring.gsub(
filename,
"^[Ff]ile:",
""
)
 
filename = mw.ustring.gsub(
filename,
"^پرونده:",
""
)
 
td:wikitext(
"[[File:" .. filename .. "|250px]]"
)
 
else
 
td:wikitext(content)
 
end
 
end
end
------------------------------------------------------------------------
-- IMAGE CAPTION
------------------------------------------------------------------------


local function addCaption(root, args)
local function addCaption(root, args)
    local caption = args[norm("توضیح تصویر")] or args[norm("عنوان تصویر")] or args[norm("زیرنویس")]
 
    if not caption or caption == "" then return end
local caption =
    root:tag("tr")
args[norm("توضیح تصویر")]
        :tag("td")
or args[norm("عنوان تصویر")]
            :attr("colspan", "2")
or args[norm("زیرنویس")]
            :css("text-align", "center")
or args[norm("برچسب تصویر")]
            :css("font-size", "90%")
 
            :css("padding", "3px 0 8px 0")
if not caption or caption == "" then
            :wikitext(mw.text.encode(caption))
return
end
 
local tr = root:tag("tr")
 
local td = tr:tag("td")
 
td
:attr("colspan", "2")
:addClass("infobox-caption")
:wikitext(mw.text.encode(caption))
 
end
end


-------------------------------------------------------
 
-- Table
------------------------------------------------------------------------
-------------------------------------------------------
-- TITLE
local function newTable(rawType)
------------------------------------------------------------------------
    rawType = rawType or "city"
 
    return mw.html.create("table")
local function getTitle(args)
        :addClass("infobox")
 
        :addClass("alborz-infobox")
return
        :addClass("infobox-type-" .. norm(rawType))
args[norm("نام‌رسمی")]
or args[norm("نام رسمی")]
or args[norm("نام")]
or mw.title.getCurrentTitle().text
 
end
end


local function addTitle(root, args)
local function addTitle(root, args)
    local title = args[norm("نام")]
              or args[norm("نام رسمی")]
              or args[norm("نام‌رسمی")]
              or mw.title.getCurrentTitle().text


    root:tag("tr")
local title = getTitle(args)
        :tag("th")
 
            :attr("colspan", "2")
if not title or title == "" then
            :css("text-align", "center")
return
            :css("font-size", "118%")
end
            :css("padding", "8px 4px")
 
            :wikitext(mw.text.encode(title))
local tr = root:tag("tr")
 
local th = tr:tag("th")
 
th
:attr("colspan", "2")
:addClass("infobox-title")
:wikitext(mw.text.encode(title))
 
end
 
 
------------------------------------------------------------------------
-- TABLE
------------------------------------------------------------------------
 
local function newTable(typeKey)
 
local root = mw.html.create("table")
 
root
:addClass("infobox")
:addClass("alborz-infobox")
:addClass("infobox-geography")
:addClass("infobox-type-" .. typeKey)
:attr("role", "presentation")
 
return root
 
end
 
 
------------------------------------------------------------------------
-- TYPE ALIASES
------------------------------------------------------------------------
 
local typeAliases = {
 
["شهرستان"]      = "county",
["county"]        = "county",
 
["شهر"]            = "city",
["city"]            = "city",
 
["روستا"]          = "village",
["village"]        = "village",
 
["بخش"]            = "district",
["district"]      = "district",
 
["دهستان"]        = "ruraldistrict",
["ruraldistrict"]  = "ruraldistrict",
 
["محله"]          = "neighborhood",
["neighborhood"]  = "neighborhood",
 
["منطقه شهری"]    = "urbanarea",
["منطقه‌شهری"]    = "urbanarea",
["منطقه شهری کرج"] = "urbanarea",
["منطقه"]          = "urbanarea",
["urbanarea"]      = "urbanarea",
["urban area"]    = "urbanarea",
 
["کوه"]            = "mountain",
["mountain"]      = "mountain",
 
["غار"]            = "cave",
["cave"]          = "cave",
 
["رودخانه"]        = "river",
["river"]          = "river",
 
["آبشار"]          = "waterfall",
["waterfall"]      = "waterfall",
 
["پارک"]          = "park",
["park"]          = "park",
 
["بنای تاریخی"]    = "historic",
["بنای‌تاریخی"]    = "historic",
["historic"]      = "historic"
 
}
 
 
------------------------------------------------------------------------
-- TYPE RESOLUTION
------------------------------------------------------------------------
 
local function resolveType(value)
 
-- اگر نوع مشخص نشده باشد
if not value or value == "" then
return "city"
end
 
value = norm(value)
 
-- ابتدا از aliasهای ماژول استفاده می‌کنیم
local resolved = typeAliases[value]
 
if resolved then
return resolved
end
 
-- سپس از typeMap موجود در Data
if data.typeMap then
 
resolved = data.typeMap[value]
 
if resolved then
return resolved
end
 
end
 
-- در نهایت خود مقدار
return value
 
end
 
 
------------------------------------------------------------------------
-- LAYOUT
------------------------------------------------------------------------
 
local function getLayout(typeKey)
 
if not data or not data.layouts then
return {}
end
 
return
data.layouts[typeKey]
or data.layouts.city
or {}
 
end
end


-------------------------------------------------------
 
-- ADD ROWS
------------------------------------------------------------------------
-------------------------------------------------------
-- RENDER ROWS
local function addRows(root, args, layout)
------------------------------------------------------------------------
    for _, key in ipairs(layout) do
 
        local field = data.fields[key]
local function renderRows(root, args, layout)
        if field then
 
            local value = getArg(args, field)
if not layout then
            if (not value or value == "") and field.default then
return
                value = field.default
end
            end
 
            if value and value ~= "" then
for _, key in ipairs(layout) do
                addRow(root, field.label, value)
 
            end
local field = data.fields[key]
        end
 
    end
if field then
 
local value = getValue(args, field)
 
if value and value ~= "" then
 
addRow(
root,
field.label,
value,
field.raw
)
 
end
 
end
 
end
 
end
end


-------------------------------------------------------
 
-- RENDER (اصلاح شده)
------------------------------------------------------------------------
-------------------------------------------------------
-- MAIN RENDER
------------------------------------------------------------------------
 
local function render(args)
local function render(args)
    local rawTypeInput = norm(args["نوع"]) or "city"
   
    -- تبدیل به کلید داخلی
    local internalType = data.typeMap[rawTypeInput] or rawTypeInput
   
    local layout = data.layouts[internalType] or data.layouts.city


    local root = newTable(rawTypeInput)  -- rawTypeInput برای نمایش و کلاس
if not data then
return "Infobox data not found"
end


    addTitle(root, args)
if not data.fields then
    addBadge(root, rawTypeInput)
return "Infobox fields not found"
    addImage(root, args)
end
    addCaption(root, args)
 
    addRows(root, args, layout)
----------------------------------------------------------------
-- Resolve type
----------------------------------------------------------------
 
local requestedType =
args[norm("نوع")]
or args[norm("type")]
 
local typeKey =
resolveType(requestedType)
 
----------------------------------------------------------------
-- Data type map
----------------------------------------------------------------
 
local internalType = typeKey
 
if data.typeMap and data.typeMap[typeKey] then
internalType = data.typeMap[typeKey]
end
 
----------------------------------------------------------------
-- اطمینان از وجود layout
----------------------------------------------------------------
 
if not data.layouts[internalType] then
 
-- اگر نوع ناشناخته بود، شهر را پیش‌فرض نکنیم
-- بلکه از نوع مشخص‌شده استفاده کنیم.
-- در صورت نبود layout، از layout شهر استفاده می‌شود.
internalType = typeKey
 
end
 
----------------------------------------------------------------
-- Layout
----------------------------------------------------------------
 
local layout =
getLayout(internalType)
 
----------------------------------------------------------------
-- Table
----------------------------------------------------------------
 
local root =
newTable(internalType)
 
----------------------------------------------------------------
-- Title
----------------------------------------------------------------
 
addTitle(root, args)
 
----------------------------------------------------------------
-- Type badge
----------------------------------------------------------------
 
addBadge(root, internalType)
 
----------------------------------------------------------------
-- Image
----------------------------------------------------------------
 
addImage(root, args)
 
----------------------------------------------------------------
-- Caption
----------------------------------------------------------------
 
addCaption(root, args)
 
----------------------------------------------------------------
-- Rows
----------------------------------------------------------------
 
renderRows(
root,
args,
layout
)
 
return tostring(root)


    return tostring(root)
end
end
------------------------------------------------------------------------
-- PUBLIC ENTRY POINT
------------------------------------------------------------------------


function p.main(frame)
function p.main(frame)
    local args = getArgs(frame)
 
    return render(args)
local args =
collectArgs(frame)
 
return render(args)
 
end
end
------------------------------------------------------------------------
-- RETURN
------------------------------------------------------------------------


return p
return p

نسخهٔ کنونی تا ‏۷ اوت ۲۰۲۶، ساعت ۲۲:۵۶

توضیحات این پودمان می‌تواند در پودمان:AlborzInfoBox/توضیحات قرار گیرد.

local p = {}

------------------------------------------------------------------------
-- DATA
------------------------------------------------------------------------

local data = mw.loadData("Module:AlborzInfoBox/Data/Geography")

------------------------------------------------------------------------
-- NORMALIZE
------------------------------------------------------------------------

local function norm(value)

	if value == nil then
		return nil
	end

	value = tostring(value)

	value = mw.text.trim(value)

	-- حذف نیم‌فاصله و کاراکترهای نامرئی
	value = mw.ustring.gsub(value, "[\u200C\u200D\uFEFF]", "")

	-- یکسان‌سازی فاصله‌ها
	value = mw.ustring.gsub(value, "%s+", " ")

	-- حروف عربی → فارسی
	value = mw.ustring.gsub(value, "ي", "ی")
	value = mw.ustring.gsub(value, "ى", "ی")
	value = mw.ustring.gsub(value, "ك", "ک")

	return mw.text.trim(value)

end


------------------------------------------------------------------------
-- ARGUMENT HANDLING
------------------------------------------------------------------------

local function collectArgs(frame)

	local args = {}

	local function push(source)

		if not source then
			return
		end

		for key, value in pairs(source) do

			if value ~= nil then

				local normalizedKey = norm(key)
				local normalizedValue = mw.text.trim(tostring(value))

				if normalizedKey ~= "" and normalizedValue ~= "" then
					args[normalizedKey] = normalizedValue
				end

			end

	    	end

	end

	-- آرگومان‌های مستقیم invoke
	push(frame.args)

	-- آرگومان‌های الگوی مادر
	local parent = frame:getParent()

	if parent then
		push(parent.args)
	end

	return args

end


------------------------------------------------------------------------
-- FIELD VALUE
------------------------------------------------------------------------

local function getValue(args, field)

	if not field then
		return nil
	end

	local names = {}

	-- نام اصلی
	if field.arg then
		table.insert(names, field.arg)
	end

	-- نام‌های جایگزین
	if field.args then

		for _, name in ipairs(field.args) do
			table.insert(names, name)
		end

	end

	-- جست‌وجوی مقدار
	for _, name in ipairs(names) do

		local key = norm(name)
		local value = args[key]

		if value and value ~= "" then
			return value
		end

	end

	-- مقدار پیش‌فرض
	if field.default ~= nil then
		return field.default
	end

	return nil

end


------------------------------------------------------------------------
-- SAFE WIKITEXT
------------------------------------------------------------------------

local function cleanText(value)

	if value == nil then
		return nil
	end

	value = tostring(value)

	value = mw.text.trim(value)

	if value == "" then
		return nil
	end

	return value

end


------------------------------------------------------------------------
-- ADD ROW
------------------------------------------------------------------------

local function addRow(root, label, value, raw)

	value = cleanText(value)

	if not value then
		return
	end

	local tr = root:tag("tr")

	-- Label
	local th = tr:tag("th")

	th
		:attr("scope", "row")
		:addClass("infobox-label")
		:wikitext(label)

	-- Value
	local td = tr:tag("td")

	td:addClass("infobox-value")

	if raw then
		td:wikitext(value)
	else
		td:wikitext(mw.text.encode(value))
	end

end


------------------------------------------------------------------------
-- TYPE BADGE
------------------------------------------------------------------------

local badgeMap = {

	city          = "شهر",
	village       = "روستا",
	county        = "شهرستان",
	district      = "بخش",
	ruraldistrict = "دهستان",

	neighborhood  = "محله",
	urbanarea     = "منطقه شهری",

	mountain      = "کوه",
	cave          = "غار",
	river         = "رودخانه",
	waterfall     = "آبشار",
	park          = "پارک",
	historic      = "بنای تاریخی"

}


local function addBadge(root, typeKey)

	local label = badgeMap[typeKey]

	-- اگر نوع ناشناخته باشد
	if not label then
		label = "مکان"
	end

	local tr = root:tag("tr")

	local td = tr:tag("td")

	td
		:attr("colspan", "2")
		:addClass("infobox-badge-row")

	local span = td:tag("span")

	span
		:addClass("infobox-badge")
		:wikitext(label)

end


------------------------------------------------------------------------
-- IMAGE
------------------------------------------------------------------------

local function isSimpleFilename(value)

	if not value or value == "" then
		return false
	end

	value = mw.text.trim(value)

	-- اگر خود مقدار شامل ویکی‌متن یا HTML باشد
	if value:find("{", 1, true)
		or value:find("<", 1, true)
		or value:find("|", 1, true)
		or value:find("[[", 1, true)
	then
		return false
	end

	return true

end


------------------------------------------------------------------------
-- IMAGE RENDERER
------------------------------------------------------------------------

local function addImage(root, args)

	local content =
		args[norm("تصویر")]
		or args[norm("پرونده")]
		or args[norm("image")]

	if not content or content == "" then
		return
	end

	content = mw.text.trim(content)

	local tr = root:tag("tr")

	local td = tr:tag("td")

	td
		:attr("colspan", "2")
		:addClass("infobox-image")

	if isSimpleFilename(content) then

		local filename = content

		filename = mw.ustring.gsub(
			filename,
			"^[Ff]ile:",
			""
		)

		filename = mw.ustring.gsub(
			filename,
			"^پرونده:",
			""
		)

		td:wikitext(
			"[[File:" .. filename .. "|250px]]"
		)

	else

		td:wikitext(content)

	end

end


------------------------------------------------------------------------
-- IMAGE CAPTION
------------------------------------------------------------------------

local function addCaption(root, args)

	local caption =
		args[norm("توضیح تصویر")]
		or args[norm("عنوان تصویر")]
		or args[norm("زیرنویس")]
		or args[norm("برچسب تصویر")]

	if not caption or caption == "" then
		return
	end

	local tr = root:tag("tr")

	local td = tr:tag("td")

	td
		:attr("colspan", "2")
		:addClass("infobox-caption")
		:wikitext(mw.text.encode(caption))

end


------------------------------------------------------------------------
-- TITLE
------------------------------------------------------------------------

local function getTitle(args)

	return
		args[norm("نام‌رسمی")]
		or args[norm("نام رسمی")]
		or args[norm("نام")]
		or mw.title.getCurrentTitle().text

end


local function addTitle(root, args)

	local title = getTitle(args)

	if not title or title == "" then
		return
	end

	local tr = root:tag("tr")

	local th = tr:tag("th")

	th
		:attr("colspan", "2")
		:addClass("infobox-title")
		:wikitext(mw.text.encode(title))

end


------------------------------------------------------------------------
-- TABLE
------------------------------------------------------------------------

local function newTable(typeKey)

	local root = mw.html.create("table")

	root
		:addClass("infobox")
		:addClass("alborz-infobox")
		:addClass("infobox-geography")
		:addClass("infobox-type-" .. typeKey)
		:attr("role", "presentation")

	return root

end


------------------------------------------------------------------------
-- TYPE ALIASES
------------------------------------------------------------------------

local typeAliases = {

	["شهرستان"]       = "county",
	["county"]         = "county",

	["شهر"]            = "city",
	["city"]            = "city",

	["روستا"]          = "village",
	["village"]        = "village",

	["بخش"]            = "district",
	["district"]       = "district",

	["دهستان"]         = "ruraldistrict",
	["ruraldistrict"]  = "ruraldistrict",

	["محله"]           = "neighborhood",
	["neighborhood"]   = "neighborhood",

	["منطقه شهری"]     = "urbanarea",
	["منطقه‌شهری"]     = "urbanarea",
	["منطقه شهری کرج"] = "urbanarea",
	["منطقه"]          = "urbanarea",
	["urbanarea"]      = "urbanarea",
	["urban area"]     = "urbanarea",

	["کوه"]            = "mountain",
	["mountain"]       = "mountain",

	["غار"]            = "cave",
	["cave"]           = "cave",

	["رودخانه"]        = "river",
	["river"]          = "river",

	["آبشار"]          = "waterfall",
	["waterfall"]      = "waterfall",

	["پارک"]           = "park",
	["park"]           = "park",

	["بنای تاریخی"]    = "historic",
	["بنای‌تاریخی"]    = "historic",
	["historic"]       = "historic"

}


------------------------------------------------------------------------
-- TYPE RESOLUTION
------------------------------------------------------------------------

local function resolveType(value)

	-- اگر نوع مشخص نشده باشد
	if not value or value == "" then
		return "city"
	end

	value = norm(value)

	-- ابتدا از aliasهای ماژول استفاده می‌کنیم
	local resolved = typeAliases[value]

	if resolved then
		return resolved
	end

	-- سپس از typeMap موجود در Data
	if data.typeMap then

		resolved = data.typeMap[value]

		if resolved then
			return resolved
		end

	end

	-- در نهایت خود مقدار
	return value

end


------------------------------------------------------------------------
-- LAYOUT
------------------------------------------------------------------------

local function getLayout(typeKey)

	if not data or not data.layouts then
		return {}
	end

	return
		data.layouts[typeKey]
		or data.layouts.city
		or {}

end


------------------------------------------------------------------------
-- RENDER ROWS
------------------------------------------------------------------------

local function renderRows(root, args, layout)

	if not layout then
		return
	end

	for _, key in ipairs(layout) do

		local field = data.fields[key]

		if field then

			local value = getValue(args, field)

			if value and value ~= "" then

				addRow(
					root,
					field.label,
					value,
					field.raw
				)

			end

		end

	end

end


------------------------------------------------------------------------
-- MAIN RENDER
------------------------------------------------------------------------

local function render(args)

	if not data then
		return "Infobox data not found"
	end

	if not data.fields then
		return "Infobox fields not found"
	end

	----------------------------------------------------------------
	-- Resolve type
	----------------------------------------------------------------

	local requestedType =
		args[norm("نوع")]
		or args[norm("type")]

	local typeKey =
		resolveType(requestedType)

	----------------------------------------------------------------
	-- Data type map
	----------------------------------------------------------------

	local internalType = typeKey

	if data.typeMap and data.typeMap[typeKey] then
		internalType = data.typeMap[typeKey]
	end

	----------------------------------------------------------------
	-- اطمینان از وجود layout
	----------------------------------------------------------------

	if not data.layouts[internalType] then

		-- اگر نوع ناشناخته بود، شهر را پیش‌فرض نکنیم
		-- بلکه از نوع مشخص‌شده استفاده کنیم.
		-- در صورت نبود layout، از layout شهر استفاده می‌شود.
		internalType = typeKey

	end

	----------------------------------------------------------------
	-- Layout
	----------------------------------------------------------------

	local layout =
		getLayout(internalType)

	----------------------------------------------------------------
	-- Table
	----------------------------------------------------------------

	local root =
		newTable(internalType)

	----------------------------------------------------------------
	-- Title
	----------------------------------------------------------------

	addTitle(root, args)

	----------------------------------------------------------------
	-- Type badge
	----------------------------------------------------------------

	addBadge(root, internalType)

	----------------------------------------------------------------
	-- Image
	----------------------------------------------------------------

	addImage(root, args)

	----------------------------------------------------------------
	-- Caption
	----------------------------------------------------------------

	addCaption(root, args)

	----------------------------------------------------------------
	-- Rows
	----------------------------------------------------------------

	renderRows(
		root,
		args,
		layout
	)

	return tostring(root)

end


------------------------------------------------------------------------
-- PUBLIC ENTRY POINT
------------------------------------------------------------------------

function p.main(frame)

	local args =
		collectArgs(frame)

	return render(args)

end


------------------------------------------------------------------------
-- RETURN
------------------------------------------------------------------------

return p