پرش به محتوا

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

از ویکی البرز
جزبدون خلاصۀ ویرایش
جزبدون خلاصۀ ویرایش
خط ۶: خط ۶:


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


------------------------------------------------------------------------
------------------------------------------------------------------------
خط ۲۲: خط ۲۳:


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


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


-- حروف عربی → فارسی
-- حروف عربی → فارسی
خط ۵۵: خط ۶۴:
if value ~= nil then
if value ~= nil then


local normalizedKey = norm(key)
local normalizedKey =
local normalizedValue = mw.text.trim(tostring(value))
norm(key)
 
local normalizedValue =
mw.text.trim(tostring(value))
 
if normalizedKey ~= ""
and normalizedValue ~= ""
then
 
args[normalizedKey] =
normalizedValue


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


خط ۷۲: خط ۸۹:


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


if parent then
if parent then
خط ۱۱۲: خط ۱۳۰:
for _, name in ipairs(names) do
for _, name in ipairs(names) do


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


if value and value ~= "" then
if value and value ~= "" then
خط ۱۳۲: خط ۱۵۳:


------------------------------------------------------------------------
------------------------------------------------------------------------
-- SAFE WIKITEXT
-- SAFE TEXT
------------------------------------------------------------------------
------------------------------------------------------------------------


خط ۱۶۰: خط ۱۸۱:
local function addRow(root, label, value, raw)
local function addRow(root, label, value, raw)


value = cleanText(value)
value =
cleanText(value)


if not value then
if not value then
خط ۱۶۶: خط ۱۸۸:
end
end


local tr = root:tag("tr")
local tr =
root:tag("tr")


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


th
th
خط ۱۷۶: خط ۲۰۳:
:wikitext(label)
:wikitext(label)


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


td:addClass("infobox-value")
td:addClass("infobox-value")


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


خط ۲۱۷: خط ۲۵۴:
local function addBadge(root, typeKey)
local function addBadge(root, typeKey)


local label = badgeMap[typeKey]
--------------------------------------------------------------------
-- نوع شناخته‌شده
--------------------------------------------------------------------
 
local label =
badgeMap[typeKey]
 
--------------------------------------------------------------------
-- نوع ناشناخته
--------------------------------------------------------------------


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


local tr = root:tag("tr")
--------------------------------------------------------------------
-- Row
--------------------------------------------------------------------


local td = tr:tag("td")
local tr =
root:tag("tr")
 
local td =
tr:tag("td")


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


local span = td:tag("span")
local span =
td:tag("span")


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


خط ۲۵۱: خط ۳۰۷:
end
end


value = mw.text.trim(value)
value =
mw.text.trim(value)


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


خط ۲۷۸: خط ۳۳۷:
or args[norm("image")]
or args[norm("image")]


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


content = mw.text.trim(content)
content =
mw.text.trim(content)


local tr = root:tag("tr")
local tr =
root:tag("tr")


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


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


if isSimpleFilename(content) then
if isSimpleFilename(content) then


local filename = content
local filename =
content


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


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


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


else
else
خط ۳۳۳: خط ۴۱۰:
or args[norm("برچسب تصویر")]
or args[norm("برچسب تصویر")]


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


local tr = root:tag("tr")
local tr =
root:tag("tr")


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


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


end
end
خط ۳۶۶: خط ۴۴۹:
local function addTitle(root, args)
local function addTitle(root, args)


local title = getTitle(args)
local title =
getTitle(args)


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


local tr = root:tag("tr")
local tr =
root:tag("tr")


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


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


end
end
خط ۳۹۰: خط ۴۸۰:
local function newTable(typeKey)
local function newTable(typeKey)


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


root
root
خط ۴۰۷: خط ۴۹۸:
-- TYPE ALIASES
-- TYPE ALIASES
------------------------------------------------------------------------
------------------------------------------------------------------------
-- نکته:
-- کلیدها در این جدول باید با خروجی norm() هماهنگ باشند.
-- چون norm نیم‌فاصله را حذف می‌کند، «منطقه‌شهری» به «منطقهشهری»
-- تبدیل می‌شود.


local typeAliases = {
local typeAliases = {


["شهرستان"]       = "county",
--------------------------------------------------------------------
["county"]         = "county",
-- شهرستان
--------------------------------------------------------------------
 
["شهرستان"] = "county",
["county"] = "county",
 
--------------------------------------------------------------------
-- شهر
--------------------------------------------------------------------
 
["شهر"] = "city",
["city"] = "city",
 
--------------------------------------------------------------------
-- روستا
--------------------------------------------------------------------
 
["روستا"] = "village",
["village"] = "village",
 
--------------------------------------------------------------------
-- بخش
--------------------------------------------------------------------


["شهر"]           = "city",
["بخش"] = "district",
["city"]           = "city",
["district"] = "district",


["روستا"]          = "village",
--------------------------------------------------------------------
["village"]        = "village",
-- دهستان
--------------------------------------------------------------------


["بخش"]           = "district",
["دهستان"] = "ruraldistrict",
["district"]       = "district",
["ruraldistrict"] = "ruraldistrict",


["دهستان"]        = "ruraldistrict",
--------------------------------------------------------------------
["ruraldistrict"]  = "ruraldistrict",
-- محله
--------------------------------------------------------------------


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


["منطقه شهری"]     = "urbanarea",
--------------------------------------------------------------------
["منطقه‌شهری"]     = "urbanarea",
-- منطقه شهری
--------------------------------------------------------------------
 
["منطقه شهری"] = "urbanarea",
["منطقهشهری"] = "urbanarea",
["منطقه شهری کرج"] = "urbanarea",
["منطقه شهری کرج"] = "urbanarea",
["منطقه"]         = "urbanarea",
["منطقهشهری کرج"] = "urbanarea",
["urbanarea"]     = "urbanarea",
["منطقه"] = "urbanarea",
["urban area"]     = "urbanarea",
 
["urbanarea"] = "urbanarea",
["urban area"] = "urbanarea",
 
--------------------------------------------------------------------
-- کوه
--------------------------------------------------------------------
 
["کوه"] = "mountain",
["mountain"] = "mountain",
 
--------------------------------------------------------------------
-- غار
--------------------------------------------------------------------
 
["غار"] = "cave",
["cave"] = "cave",
 
--------------------------------------------------------------------
-- رودخانه
--------------------------------------------------------------------
 
["رودخانه"] = "river",
["river"] = "river",


["کوه"]            = "mountain",
--------------------------------------------------------------------
["mountain"]      = "mountain",
-- آبشار
--------------------------------------------------------------------


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


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


["آبشار"]         = "waterfall",
["پارک"] = "park",
["waterfall"]     = "waterfall",
["park"] = "park",


["پارک"]          = "park",
--------------------------------------------------------------------
["park"]          = "park",
-- بنای تاریخی
--------------------------------------------------------------------


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


}
}
خط ۴۶۳: خط ۶۱۲:
local function resolveType(value)
local function resolveType(value)


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


value = norm(value)
--------------------------------------------------------------------
-- Normalize
--------------------------------------------------------------------
 
value =
norm(value)


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


if resolved then
if resolved then
خط ۴۷۷: خط ۶۴۲:
end
end


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


resolved = data.typeMap[value]
if data
and data.typeMap
then
 
resolved =
data.typeMap[value]


if resolved then
if resolved then
خط ۴۸۸: خط ۶۵۹:
end
end


-- در نهایت خود مقدار
--------------------------------------------------------------------
return value
-- اگر مقدار خودش یک typeKey معتبر باشد
--------------------------------------------------------------------
 
if data
and data.layouts
and data.layouts[value]
then
 
return value
 
end
 
--------------------------------------------------------------------
-- نوع ناشناخته
--------------------------------------------------------------------
 
return nil


end
end
خط ۵۰۰: خط ۶۸۷:
local function getLayout(typeKey)
local function getLayout(typeKey)


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


return
--------------------------------------------------------------------
data.layouts[typeKey]
-- فقط layout همان نوع
or data.layouts.city
--------------------------------------------------------------------
 
return data.layouts[typeKey]
or {}
or {}


خط ۵۲۴: خط ۷۲۱:
for _, key in ipairs(layout) do
for _, key in ipairs(layout) do


local field = data.fields[key]
local field =
data.fields[key]


if field then
if field then


local value = getValue(args, field)
local value =
getValue(args, field)


if value and value ~= "" then
if value
and value ~= ""
then


addRow(
addRow(
خط ۵۵۳: خط ۷۵۴:


local function render(args)
local function render(args)
--------------------------------------------------------------------
-- Data validation
--------------------------------------------------------------------


if not data then
if not data then
خط ۵۶۲: خط ۷۶۷:
end
end


----------------------------------------------------------------
if not data.layouts then
-- Resolve type
return "Infobox layouts not found"
----------------------------------------------------------------
end
 
--------------------------------------------------------------------
-- Requested type
--------------------------------------------------------------------


local requestedType =
local requestedType =
خط ۵۷۰: خط ۷۷۹:
or args[norm("type")]
or args[norm("type")]


local typeKey =
--------------------------------------------------------------------
-- Resolve type
--------------------------------------------------------------------
 
local internalType =
resolveType(requestedType)
resolveType(requestedType)


----------------------------------------------------------------
--------------------------------------------------------------------
-- Data type map
-- اگر نوع مشخص نشده بود
----------------------------------------------------------------
--------------------------------------------------------------------
 
if not internalType then
 
-- فقط زمانی شهر به عنوان پیش‌فرض استفاده می‌شود
-- که اصلاً نوع وارد نشده باشد.
 
if not requestedType
or requestedType == ""
then
 
internalType = "city"
 
else
 
-- نوع ناشناخته را همان‌طور نگه می‌داریم
-- تا به اشتباه شهر یا مکان نمایش داده نشود.
 
internalType =
norm(requestedType)


local internalType = typeKey
end


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


----------------------------------------------------------------
--------------------------------------------------------------------
-- اطمینان از وجود layout
-- Data type map
----------------------------------------------------------------
--------------------------------------------------------------------


if not data.layouts[internalType] then
if data.typeMap
and data.typeMap[internalType]
then


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


end
end


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


local layout =
local layout =
getLayout(internalType)
getLayout(internalType)


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


local root =
local root =
newTable(internalType)
newTable(internalType)


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


addTitle(root, args)
addTitle(
root,
args
)


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


addBadge(root, internalType)
addBadge(
root,
internalType
)


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


addImage(root, args)
addImage(
root,
args
)


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


addCaption(root, args)
addCaption(
root,
args
)


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


renderRows(
renderRows(
خط ۶۴۳: خط ۸۸۵:
layout
layout
)
)
--------------------------------------------------------------------
-- Output
--------------------------------------------------------------------


return tostring(root)
return tostring(root)

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

توضیحات این پودمان می‌تواند در پودمان: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 TEXT
------------------------------------------------------------------------

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

	--------------------------------------------------------------------
	-- Row
	--------------------------------------------------------------------

	local tr =
		root:tag("tr")

	local td =
		tr:tag("td")

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

	--------------------------------------------------------------------
	-- Badge
	--------------------------------------------------------------------

	local span =
		td:tag("span")

	span
		:addClass("alborz-infobox-type")
		: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")

	--------------------------------------------------------------------
	-- Simple filename
	--------------------------------------------------------------------

	if isSimpleFilename(content) then

		local filename =
			content

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

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

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

	--------------------------------------------------------------------
	-- Existing wikitext
	--------------------------------------------------------------------

	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
------------------------------------------------------------------------
-- نکته:
-- کلیدها در این جدول باید با خروجی norm() هماهنگ باشند.
-- چون norm نیم‌فاصله را حذف می‌کند، «منطقه‌شهری» به «منطقهشهری»
-- تبدیل می‌شود.

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"] = "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

	--------------------------------------------------------------------
	-- Normalize
	--------------------------------------------------------------------

	value =
		norm(value)

	--------------------------------------------------------------------
	-- Alias داخلی
	--------------------------------------------------------------------

	local resolved =
		typeAliases[value]

	if resolved then
		return resolved
	end

	--------------------------------------------------------------------
	-- Data typeMap
	--------------------------------------------------------------------

	if data
		and data.typeMap
	then

		resolved =
			data.typeMap[value]

		if resolved then
			return resolved
		end

	end

	--------------------------------------------------------------------
	-- اگر مقدار خودش یک typeKey معتبر باشد
	--------------------------------------------------------------------

	if data
		and data.layouts
		and data.layouts[value]
	then

		return value

	end

	--------------------------------------------------------------------
	-- نوع ناشناخته
	--------------------------------------------------------------------

	return nil

end


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

local function getLayout(typeKey)

	if not data
		or not data.layouts
	then

		return {}

	end

	if not typeKey then
		return {}
	end

	--------------------------------------------------------------------
	-- فقط layout همان نوع
	--------------------------------------------------------------------

	return data.layouts[typeKey]
		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)

	--------------------------------------------------------------------
	-- Data validation
	--------------------------------------------------------------------

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

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

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

	--------------------------------------------------------------------
	-- Requested type
	--------------------------------------------------------------------

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

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

	local internalType =
		resolveType(requestedType)

	--------------------------------------------------------------------
	-- اگر نوع مشخص نشده بود
	--------------------------------------------------------------------

	if not internalType then

		-- فقط زمانی شهر به عنوان پیش‌فرض استفاده می‌شود
		-- که اصلاً نوع وارد نشده باشد.

		if not requestedType
			or requestedType == ""
		then

			internalType = "city"

		else

			-- نوع ناشناخته را همان‌طور نگه می‌داریم
			-- تا به اشتباه شهر یا مکان نمایش داده نشود.

			internalType =
				norm(requestedType)

		end

	end

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

	if data.typeMap
		and data.typeMap[internalType]
	then

		internalType =
			data.typeMap[internalType]

	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
	)

	--------------------------------------------------------------------
	-- Output
	--------------------------------------------------------------------

	return tostring(root)

end


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

function p.main(frame)

	local args =
		collectArgs(frame)

	return render(args)

end


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

return p