پودمان:ModernInfobox
ظاهر
local p = {}
local listStyles = {
flatlist = { patterns = {'^flatlist$', '%sflatlist$', '^flatlist%s', '%sflatlist%s'}, styles = 'Flatlist/styles.css' }
}
local nonNumericParams = {
'language', 'زبان',
'above', 'بالا',
'heading', 'عنوان',
'subheader', 'زیرعنوان',
'description', 'توضیح تصویر',
'header', 'سربرگ',
'label', 'برچسب',
'data', 'اطلاعات',
'icon', 'آیکون',
'below', 'پایین',
'footer', 'فوتر',
'layout', 'طرحبندی'
}
local forceEnglishParams = {
'width', 'عرض',
'size', 'اندازه تصویر',
'id', 'شناسه',
'unit', 'واحد اندازه',
'table_background_color', 'رنگ پس زمینه جدول',
'heading_background_color', 'رنگ پس زمینه عنوان',
'above_background_color', 'رنگ پس زمینه بالا',
'subheader_background_color', 'رنگ پس زمینه زیرعنوان',
'picture_background_color', 'رنگ پس زمینه تصویر',
'description_picture_background_color', 'رنگ پس زمینه توضیح تصویر',
'below_background_color', 'رنگ پس زمینه پایین',
'footer_background_color', 'رنگ پس زمینه فوتر',
'header_background_color', 'رنگ پس زمینه سربرگ',
'label_background_color', 'رنگ پس زمینه برچسب',
'data_background_color', 'رنگ پس زمینه اطلاعات',
'custom_class', 'کلاس دلخواه',
'custom_style', 'استایل دلخواه',
'table_color', 'رنگ جدول',
'heading_color', 'رنگ عنوان',
'above_color', 'رنگ بالا',
'subheader_color', 'رنگ زیرعنوان',
'picture_color', 'رنگ تصویر',
'description_color', 'رنگ توضیح تصویر',
'below_color', 'رنگ پایین',
'footer_color', 'رنگ فوتر',
'header_color', 'رنگ سربرگ',
'label_color', 'رنگ برچسب',
'data_color', 'رنگ اطلاعات'
}
local globalDynamicParams = {
header = { names = {'header', 'سربرگ'}, hasSubParams = true, subParams = {'label', 'data', 'icon'} },
subheader = { names = {'subheader', 'زیرعنوان'}, hasSubParams = false },
picture = { names = {'picture', 'image', 'تصویر'}, hasSubParams = true, subParams = {'size', 'description'} }
}
local headerDependencies = {
header = { names = {'header', 'سربرگ'}, subParams = {'label', 'data', 'icon', 'برچسب', 'اطلاعات', 'آیکون'} }
}
local layoutOptions = {
{'carousel', 'چرخشی'},
{'2up-2down', 'دوتا-بالا-دوتا-پایین'},
{'3up-2down', 'سهتا-بالا-دوتا-پایین'},
{'2up-3down', 'دوتا-بالا-سهتا-پایین'},
{'grid', 'شبکهای'},
{'stacked', 'عمودی'}
}
local function isNonNumericParam(key)
for _, param in ipairs(nonNumericParams) do
if mw.ustring.match(key, '^' .. param .. '%d*$') or key == param then
return true
end
end
return false
end
local function isForceEnglishParam(key)
for _, param in ipairs(forceEnglishParams) do
if mw.ustring.match(key, '^' .. param .. '%d*$') or key == param then
return true
end
end
return false
end
local function convertHexToEnglish(value)
local numberMap = {
['۰'] = '0', ['۱'] = '1', ['۲'] = '2', ['۳'] = '3', ['۴'] = '4',
['۵'] = '5', ['۶'] = '6', ['۷'] = '7', ['۸'] = '8', ['۹'] = '9',
['٠'] = '0', ['١'] = '1', ['٢'] = '2', ['٣'] = '3', ['٤'] = '4',
['٥'] = '5', ['٦'] = '6', ['٧'] = '7', ['٨'] = '8', ['٩'] = '9'
}
return mw.ustring.gsub(value, '#([0-9A-Fa-f۰-۹٠-٩]+)', function(hex)
return '#' .. mw.ustring.gsub(hex, '[۰-۹٠-٩]', function(digit)
return numberMap[digit] or digit
end)
end)
end
local function getArg(args, keys, lang)
for _, key in ipairs(keys) do
if args[key] and mw.text.trim(args[key]) ~= '' then
local value = mw.text.trim(args[key])
if isForceEnglishParam(key) then
local num = lang:parseFormattedNumber(value)
if num then
return tostring(num)
else
local numOnly = tonumber(value)
if numOnly then
return lang:formatNum(numOnly)
else
return convertHexToEnglish(value)
end
end
elseif isNonNumericParam(key) then
return value
else
local num = lang:parseFormattedNumber(value)
if num then
return tostring(num)
else
return value
end
end
end
end
return nil
end
local function hasSubParams(args, headerNum, lang)
for i = 1, 50 do
local label = getArg(args, {'label' .. headerNum .. '_' .. i, 'برچسب' .. headerNum .. '_' .. i}, lang)
local data = getArg(args, {'data' .. headerNum .. '_' .. i, 'اطلاعات' .. headerNum .. '_' .. i}, lang)
if label and data then
return true
end
end
return false
end
local function isValidLayout(layout)
for _, option in ipairs(layoutOptions) do
if layout == option[1] or layout == option[2] then
return true
end
end
return false
end
local function checkListStyle(class)
for name, list in pairs(listStyles) do
for _, pattern in ipairs(list.patterns) do
if class and mw.ustring.match(class, pattern) then
return name
end
end
end
return nil
end
local function processRowContent(content, tag)
if not content or mw.text.trim(content) == '' then return content end
local marker = '<span class="modern-infobox-marker"></span>'
local processed = mw.ustring.gsub(content, '(</[Tt][Rr]%s*>)((?:%[%[%s*[^%]]*%]%]|%b{})%s*)', '%2%1')
processed = mw.ustring.gsub(processed, '<[Tt][Rr]', marker .. '<tr')
processed = mw.ustring.gsub(processed, '</[Tt][Rr]%s*>', '</tr>' .. marker)
if mw.ustring.match(processed, marker) then
local parts = mw.text.split(processed, marker)
local result = ''
for i, part in ipairs(parts) do
if i == 1 then
result = result .. part .. '</' .. tag .. '></tr>'
elseif i == #parts then
result = result .. '<tr><' .. tag .. ' colspan="2">' .. part
elseif mw.text.trim(part) ~= '' then
result = result .. '<tr><' .. tag .. ' colspan="2">' .. part .. '</' .. tag .. '></tr>'
end
end
return result
end
return content
end
local function getDynamicArgNums(args, paramDef)
local nums = {}
for k in pairs(args) do
for _, name in ipairs(paramDef.names) do
local num = mw.ustring.match(k, '^' .. name .. '([0-9]+)$')
if num then
table.insert(nums, tonumber(num))
end
end
end
table.sort(nums)
local uniqueNums = {}
for i, num in ipairs(nums) do
if i == 1 or num ~= nums[i-1] then
table.insert(uniqueNums, num)
end
end
return uniqueNums
end
function p.modernInfobox(frame)
local parentArgs = frame:getParent() and frame:getParent().args or {}
local frameArgs = frame.args or {}
local args = {}
for k, v in pairs(parentArgs) do
if v and mw.text.trim(v) ~= '' then args[k] = mw.text.trim(v) end
end
for k, v in pairs(frameArgs) do
if v and mw.text.trim(v) ~= '' then args[k] = mw.text.trim(v) end
end
if not next(args) then
return "Error: No arguments received\nRaw arguments: " .. mw.dumpObject(args)
end
local langCode = getArg(args, {'language', 'زبان'}, mw.language.getContentLanguage()) or mw.language.getContentLanguage():getCode()
local lang = mw.language.new(langCode)
local isRTL = lang:isRTL()
local templatestyles = frame:extensionTag{
name = 'templatestyles',
args = { src = 'Module:ModernInfobox/styles.css', lang = langCode }
}
local defaultWidth = '400px'
local width = getArg(args, {'width', 'عرض'}, lang) or defaultWidth
local unit = getArg(args, {'unit', 'واحد اندازه'}, lang) or 'px'
if not mw.ustring.match(width, unit .. '$') then width = width .. unit end
local infoboxId = getArg(args, {'id', 'شناسه'}, lang) or 'modern-infobox-default'
local carouselId = 'carousel-' .. infoboxId
local root = mw.html.create('table')
:addClass('modern-infobox')
:addClass(getArg(args, {'custom_class', 'کلاس دلخواه'}, lang))
:cssText(getArg(args, {'custom_style', 'استایل دلخواه'}, lang))
:css('width', width)
:css('direction', isRTL and 'rtl' or 'ltr')
:css('background', getArg(args, {'table_background_color', 'رنگ پس زمینه جدول'}, lang) and (getArg(args, {'table_background_color', 'رنگ پس زمینه جدول'}, lang) .. ' !important') or nil)
:css('color', getArg(args, {'table_color', 'رنگ جدول'}, lang) and (getArg(args, {'table_color', 'رنگ جدول'}, lang) .. ' !important') or nil)
:attr('id', infoboxId)
local heading = getArg(args, {'heading', 'عنوان'}, lang)
if heading then
root:tag('caption')
:addClass('modern-infobox-heading')
:cssText(getArg(args, {'custom_style', 'استایل دلخواه'}, lang))
:css('background', getArg(args, {'heading_background_color', 'رنگ پس زمینه عنوان'}, lang) and (getArg(args, {'heading_background_color', 'رنگ پس زمینه عنوان'}, lang) .. ' !important') or nil)
:css('color', getArg(args, {'heading_color', 'رنگ عنوان'}, lang) and (getArg(args, {'heading_color', 'رنگ عنوان'}, lang) .. ' !important') or nil)
:wikitext(heading)
end
local tbody = root
local above = getArg(args, {'above', 'بالا'}, lang)
if above then
tbody:tag('tr')
:tag('th')
:attr('colspan', '2')
:addClass('modern-infobox-above')
:cssText(getArg(args, {'custom_style', 'استایل دلخواه'}, lang))
:css('background', getArg(args, {'above_background_color', 'رنگ پس زمینه بالا'}, lang) and (getArg(args, {'above_background_color', 'رنگ پس زمینه بالا'}, lang) .. ' !important') or nil)
:css('color', getArg(args, {'above_color', 'رنگ بالا'}, lang) and (getArg(args, {'above_color', 'رنگ بالا'}, lang) .. ' !important') or nil)
:wikitext(processRowContent(above, 'th'))
end
local subheaderNums = getDynamicArgNums(args, globalDynamicParams.subheader)
for _, num in ipairs(subheaderNums) do
local subheader = getArg(args, {'subheader' .. num, 'زیرعنوان' .. num}, lang)
if subheader then
tbody:tag('tr')
:tag('td')
:attr('colspan', '2')
:addClass('modern-infobox-subheader')
:cssText(getArg(args, {'custom_style', 'استایل دلخواه'}, lang))
:css('background', getArg(args, {'subheader_background_color', 'رنگ پس زمینه زیرعنوان'}, lang) and (getArg(args, {'subheader_background_color', 'رنگ پس زمینه زیرعنوان'}, lang) .. ' !important') or nil)
:css('color', getArg(args, {'subheader_color', 'رنگ زیرعنوان'}, lang) and (getArg(args, {'subheader_color', 'رنگ زیرعنوان'}, lang) .. ' !important') or nil)
:wikitext(processRowContent(subheader, 'td'))
end
end
local pictureNums = getDynamicArgNums(args, globalDynamicParams.picture)
local carouselHtml = ''
if #pictureNums > 0 then
local layout = getArg(args, {'layout', 'طرحبندی'}, lang) or 'stacked'
if not isValidLayout(layout) then layout = 'stacked' end
for _, option in ipairs(layoutOptions) do
if layout == option[2] then
layout = option[1]
break
end
end
-- تعریف اولیه layout کلاس
local layoutClass = 'layout-' .. layout
-- بررسی تعداد تصاویر برای چیدمانهای خاص
if layout == '2up-2down' and #pictureNums ~= 4 then
layout = 'stacked'
layoutClass = 'layout-stacked'
elseif (layout == '3up-2down' or layout == '2up-3down') and #pictureNums ~= 5 then
layout = 'stacked'
layoutClass = 'layout-stacked'
end
if layout == 'carousel' then
local carouselDiv = mw.html.create('div')
:addClass('modern-infobox-carousel-container')
:addClass('layout-' .. layout)
:attr('id', carouselId)
:css('display', 'none')
:css('width', width)
:css('margin', '0 auto')
:css('background', getArg(args, {'picture_background_color', 'رنگ پس زمینه تصویر'}, lang) and (getArg(args, {'picture_background_color', 'رنگ پس زمینه تصویر'}, lang) .. ' !important') or nil)
:css('color', getArg(args, {'picture_color', 'رنگ تصویر'}, lang) and (getArg(args, {'picture_color', 'رنگ تصویر'}, lang) .. ' !important') or nil)
local hasContent = false
for _, num in ipairs(pictureNums) do
local picture = getArg(args, {'picture' .. num, 'image' .. num, 'تصویر' .. num}, lang)
if picture then
local pictureDiv = carouselDiv:tag('div')
:addClass('modern-infobox-picture')
local pictureSize = getArg(args, {'size' .. num, 'اندازه تصویر' .. num}, lang) or '250'
if pictureSize ~= 'full' then
if tonumber(pictureSize) then pictureSize = pictureSize .. unit else pictureSize = '250' .. unit end
else
pictureSize = '250' .. unit
end
local pictureWikitext = string.format('[[File:%s|%s|center]]', picture, pictureSize)
pictureDiv:wikitext(pictureWikitext)
local description = getArg(args, {'description' .. num, 'توضیح تصویر' .. num}, lang)
if description then
pictureDiv:tag('div')
:addClass('modern-infobox-description')
:cssText(getArg(args, {'custom_style', 'استایل دلخواه'}, lang))
:css('background', getArg(args, {'description_picture_background_color', 'رنگ پس زمینه توضیح تصویر'}, lang) and (getArg(args, {'description_picture_background_color', 'رنگ پس زمینه توضیح تصویر'}, lang) .. ' !important') or nil)
:css('color', getArg(args, {'description_color', 'رنگ توضیح تصویر'}, lang) and (getArg(args, {'description_color', 'رنگ توضیح تصویر'}, lang) .. ' !important') or nil)
:wikitext(description)
end
hasContent = true
end
end
if hasContent then
carouselHtml = tostring(carouselDiv)
local placeholderTd = tbody:tag('tr')
:tag('td')
:attr('colspan', '2')
:addClass('modern-infobox-picture-placeholder')
:attr('data-carousel-id', carouselId)
:css('height', '300px')
local staticPictures = mw.html.create('div')
:addClass('modern-infobox-static-pictures')
:css('display', 'block')
for _, num in ipairs(pictureNums) do
local picture = getArg(args, {'picture' .. num, 'image' .. num, 'تصویر' .. num}, lang)
if picture then
local pictureSize = getArg(args, {'size' .. num, 'اندازه تصویر' .. num}, lang) or '250'
if pictureSize ~= 'full' then
if tonumber(pictureSize) then pictureSize = pictureSize .. unit else pictureSize = '250' .. unit end
else
pictureSize = '250' .. unit
end
local pictureWikitext = string.format('[[File:%s|%s|center]]', picture, pictureSize)
staticPictures:tag('div')
:addClass('modern-infobox-picture')
:wikitext(pictureWikitext)
end
end
placeholderTd:wikitext(tostring(staticPictures))
end
else
local pictureContainer = tbody:tag('tr')
:tag('td')
:attr('colspan', '2')
:addClass('modern-infobox-picture-container')
:addClass(layoutClass)
:cssText(getArg(args, {'custom_style', 'استایل دلخواه'}, lang))
:css('background', getArg(args, {'picture_background_color', 'رنگ پس زمینه تصویر'}, lang) and (getArg(args, {'picture_background_color', 'رنگ پس زمینه تصویر'}, lang) .. ' !important') or nil)
:css('color', getArg(args, {'picture_color', 'رنگ تصویر'}, lang) and (getArg(args, {'picture_color', 'رنگ تصویر'}, lang) .. ' !important') or nil)
for _, num in ipairs(pictureNums) do
local picture = getArg(args, {'picture' .. num, 'image' .. num, 'تصویر' .. num}, lang)
if picture then
local pictureDiv = pictureContainer:tag('div')
:addClass('modern-infobox-picture')
local pictureSize = getArg(args, {'size' .. num, 'اندازه تصویر' .. num}, lang) or '250'
if pictureSize ~= 'full' then
if tonumber(pictureSize) then pictureSize = pictureSize .. unit else pictureSize = '250' .. unit end
else
pictureSize = '250' .. unit
end
local pictureWikitext = string.format('[[File:%s|%s|center]]', picture, pictureSize)
pictureDiv:wikitext(pictureWikitext)
local description = getArg(args, {'description' .. num, 'توضیح تصویر' .. num}, lang)
if description then
pictureDiv:tag('div')
:addClass('modern-infobox-description')
:cssText(getArg(args, {'custom_style', 'استایل دلخواه'}, lang))
:css('background', getArg(args, {'description_picture_background_color', 'رنگ پس زمینه توضیح تصویر'}, lang) and (getArg(args, {'description_picture_background_color', 'رنگ پس زمینه توضیح تصویر'}, lang) .. ' !important') or nil)
:css('color', getArg(args, {'description_color', 'رنگ توضیح تصویر'}, lang) and (getArg(args, {'description_color', 'رنگ توضیح تصویر'}, lang) .. ' !important') or nil)
:wikitext(description)
end
end
end
end
end
local headerNums = getDynamicArgNums(args, globalDynamicParams.header)
for _, headerNum in ipairs(headerNums) do
local header = getArg(args, {'header' .. headerNum, 'سربرگ' .. headerNum}, lang)
if header and hasSubParams(args, headerNum, lang) then
local isExpanded = getArg(args, {'header' .. headerNum .. '_open', 'باز سربرگ' .. headerNum}, lang)
isExpanded = (isExpanded == 'yes' or isExpanded == 'بله')
tbody:tag('tr')
:tag('th')
:attr('colspan', '2')
:addClass('modern-infobox-header')
:cssText(getArg(args, {'custom_style', 'استایل دلخواه'}, lang))
:css('background', getArg(args, {'header_background_color', 'رنگ پس زمینه سربرگ'}, lang) and (getArg(args, {'header_background_color', 'رنگ پس زمینه سربرگ'}, lang) .. ' !important') or nil)
:css('color', getArg(args, {'header_color', 'رنگ سربرگ'}, lang) and (getArg(args, {'header_color', 'رنگ سربرگ'}, lang) .. ' !important') or nil)
:wikitext(header .. ' <span class="toggle">' .. (isExpanded and '-' or '+') .. '</span>')
for i = 1, 50 do
local label = getArg(args, {'label' .. headerNum .. '_' .. i, 'برچسب' .. headerNum .. '_' .. i}, lang)
local data = getArg(args, {'data' .. headerNum .. '_' .. i, 'اطلاعات' .. headerNum .. '_' .. i}, lang)
local icon = getArg(args, {'icon' .. headerNum .. '_' .. i, 'آیکون' .. headerNum .. '_' .. i}, lang)
if label and data then
local row = tbody:tag('tr')
:addClass('modern-infobox-content')
:css('display', isExpanded and '' or 'none')
:addClass(getArg(args, {'custom_class', 'کلاس دلخواه'}, lang))
:cssText(getArg(args, {'custom_style', 'استایل دلخواه'}, lang))
local labelCell = row:tag('th')
:attr('scope', 'row')
:addClass('modern-infobox-label')
:cssText(getArg(args, {'custom_style', 'استایل دلخواه'}, lang))
:css('background', getArg(args, {'label_background_color', 'رنگ پس زمینه برچسب'}, lang) and (getArg(args, {'label_background_color', 'رنگ پس زمینه برچسب'}, lang) .. ' !important') or nil)
:css('color', getArg(args, {'label_color', 'رنگ برچسب'}, lang) and (getArg(args, {'label_color', 'رنگ برچسب'}, lang) .. ' !important') or nil)
if icon then
labelCell:wikitext(string.format('[[File:%s|20px]] %s', icon, label))
else
labelCell:wikitext(label)
end
row:tag('td')
:attr('colspan', '1')
:addClass('modern-infobox-data')
:cssText(getArg(args, {'custom_style', 'استایل دلخواه'}, lang))
:css('background', getArg(args, {'data_background_color', 'رنگ پس زمینه اطلاعات'}, lang) and (getArg(args, {'data_background_color', 'رنگ پس زمینه اطلاعات'}, lang) .. ' !important') or nil)
:css('color', getArg(args, {'data_color', 'رنگ اطلاعات'}, lang) and (getArg(args, {'data_color', 'رنگ اطلاعات'}, lang) .. ' !important') or nil)
:wikitext(processRowContent(data, 'td'))
end
end
end
end
local below = getArg(args, {'below', 'پایین'}, lang)
if below then
tbody:tag('tr')
:tag('td')
:attr('colspan', '2')
:addClass('modern-infobox-below')
:cssText(getArg(args, {'custom_style', 'استایل دلخواه'}, lang))
:css('background', getArg(args, {'below_background_color', 'رنگ پس زمینه پایین'}, lang) and (getArg(args, {'below_background_color', 'رنگ پس زمینه پایین'}, lang) .. ' !important') or nil)
:css('color', getArg(args, {'below_color', 'رنگ پایین'}, lang) and (getArg(args, {'below_color', 'رنگ پایین'}, lang) .. ' !important') or nil)
:wikitext(processRowContent(below, 'td'))
end
local footer = getArg(args, {'footer', 'فوتر'}, lang)
if footer then
tbody:tag('tr')
:tag('td')
:attr('colspan', '2')
:addClass('modern-infobox-footer')
:cssText(getArg(args, {'custom_style', 'استایل دلخواه'}, lang))
:css('background', getArg(args, {'footer_background_color', 'رنگ پس زمینه فوتر'}, lang) and (getArg(args, {'footer_background_color', 'رنگ پس زمینه فوتر'}, lang) .. ' !important') or nil)
:css('color', getArg(args, {'footer_color', 'رنگ فوتر'}, lang) and (getArg(args, {'footer_color', 'رنگ فوتر'}, lang) .. ' !important') or nil)
:wikitext(processRowContent(footer, 'td'))
end
local listClass = checkListStyle(getArg(args, {'custom_class', 'کلاس دلخواه'}, lang))
if listClass then
local currentClasses = getArg(args, {'custom_class', 'کلاس دلخواه'}, lang) or ''
if not mw.ustring.match(currentClasses, '%s' .. listClass .. '%s') and
not mw.ustring.match(currentClasses, '^' .. listClass .. '%s') and
not mw.ustring.match(currentClasses, '%s' .. listClass .. '$') and
not mw.ustring.match(currentClasses, '^' .. listClass .. '$') then
root:addClass(listClass)
end
end
return templatestyles .. '\n\n' .. carouselHtml .. '\n\n' .. tostring(root)
end
return p