وحدة:بطاقة

الاستخدامعدل

هذه الوحدة تستعمل لعرض قالب معلومات (Infobox) أو بطاقة بالاعتماد على وحدة فرعية تحتوي على بيانات حول مضمون هذا القالب. تسمح هذه الوحدة بإجراء استجوابات بصورة مبسطة لويكي بيانات لجلب ما توفر من البيانات.

استحداث قالب معلومة (أو بطاقة) يمر بخطوتين :

  1. إنشاء وحدة فرعية بعنوان من الشاكلة : وحدة:بطاقة/قالب/اسم_قالب
    • مثال : وحدة:بطاقة/قالب/لعبة
  2. إنشاء قالب يستعمل لاحقا في المقالات. محتوى هذا القالب سيكون : {{#استدعاء:بطاقة|تركيب|وحدة=اسم_الوحدة_الفرعية}}
    • مثال :{{#استدعاء:بطاقة|تركيب|وحدة=لعبة}}

محتوى الوحدة الفرعيةعدل

محتوى فارغ
return 	{
 maincolor = '#DDDDDD' -- اللون المستعمل لعنوان البطاقة
 ,parts = {} -- محتويات البطاقة
}
محتوى نموذجي
local generic = require( 'وحدة:بطاقة/أدوات' )

return 	{
 maincolor = '#DDDDDD' -- اللون المستعمل لعنوان البطاقة
 ,parts = { -- محتويات البطاقة
	  generic.title(),
	  {type = 'subtitle', value = {'الاسم_الاصلي'}},
	  generic.logo(),
	  generic.mainimage(),
	  {type = 'table', title = 'معلومات عامة', rows = {
		{type = 'row' 
			,label = 'الصانع'
			,value ={'manufacturer','صانع'}
			,wikidata = {property='P176'}},
		{type = 'row'            
			,label = 'أسماء أخرى'
			,value ={'أسماء_أخرى','aka'}},
		{type = 'row' 
			,label = '[[شركة قابضة]]'
			,value ={'parent_company','شركة قابضة'}},
	  }},
	}
}
-- Credits:
-- Original from fr:Module:Infobox
-- Adapted & Developed for Arabic Wikipedia by وهراني @arwiki
-- Version: 20210831

local p = {}
local wikiLang = 'ar' -- اللغة

local item = nil -- عنصر مرتبط بويكي بيانات
local localdata = {}-- بيانات مضمنة في القالب

local page = { -- بيانات حول الصفحة التي ستعرض عليها البطاقة 
	name = mw.title.getCurrentTitle().prefixedText,
	namespace =  mw.title.getCurrentTitle().namespace
}
local maincolor, secondcolor, thirdcolor = '#E1E1E1', '#E1E1E1', '#000000'

-- نتائج ثانوية
local maintenance = '' -- نص مضاف للنتيجة يستعمل لإدراج التصنيفات عادة
local externaltext = '' -- نص مضاف عام يستعمل لعرض إضافات مثل القوالب خارج قالب المعلومات

-- وحدات مستعملة

local i18n = {
	['see doc'] = 'حول القالب',
	['edit'] = 'تعديل',
	['edit code'] = 'تعديل مصدري',
	['edit item'] = 'تعديل ويكي بيانات',
	['tracking cat'] = "صفحات بها بيانات ويكي بيانات",
	['invalid block type'] = "لبنة بيانات غير صحيحة في القالب", 
	['default cat'] = "صيانة بطاقات",
}

local function addWikidataCat(prop)
	if type(prop) == 'table' then prop = prop[1] end
	if page.namespace == 0 then
	maintenance = maintenance .. '[[تصنيف:صفحات_تستخدم_خاصية_' .. prop .. ']]'
	end
end

local function addMaintenanceCat(cat, sortkey)
	if page.namespace ~= 0 then
		return ''
	end
	if cat then
		maintenance = maintenance .. '[[Category:' .. cat .. '|' .. (sortkey or page.name) .. ']]'
	end
end

local function expandQuery(query)
	local value, number -- نتيجة ، عدد النتائج للضبط الصرفي للعنوان

	if(type(query) ~= 'table') then return nil end
-- الوحدات المستعملة
	local wikimod = query.wikimod or localdata.wikimod or 'Wikidata2' --'Wikidata/fr'
	
	local wdexpandQuery = require("وحدة:بطاقة/ويكي.بيانات").expandQuery
	
	local noerr,data, nb
	noerr,data, nb = pcall(wdexpandQuery,localdata.item ,wikimod,query)	
	if noerr 
		then return data, nb 
		else 
			addMaintenanceCat('مقالات بها أخطاء مصدرها وحدة بطاقة')
			mw.log("WD Query Error : "..mw.dumpObject(data))
			return '<span class="error">' .. (data) .. '</span>' 
	end
end

local function getWikidataValue(params, wikidataparam)
	if not localdata.item then
		return nil
	end

	if params.blockers then -- blockers are local parameters that disable the wikidata query
		local blockers = params.blockers
		if (type(blockers) == 'string') then
			blockers = {blockers}
		end
		for i, blocker in ipairs(blockers) do
			if localdata[blocker] then
				return nil
			end
		end
	end

	local v, valnum -- قيم النتائج وعددها (لعرض مناسب في حالة الجمع)
	
	if not wikidataparam then -- par défaut la valeur wikidata est dans le paramètre "wikidata" mais dans les structures composées comme "title", il y a plusieurs paramètres wikidata
		wikidataparam = 'wikidata'
	end

	if params[wikidataparam] then
		if type(params[wikidataparam]) == 'function' then
			v, valnum = params[wikidataparam](localdata.item)
		elseif type(params[wikidataparam]) == 'table' then
			v, valnum = expandQuery(params[wikidataparam])
		else
			v, valnum = params[wikidataparam]
		end
	end
	if not v or valnum==0 then 
		return nil
	end
	--v = linguistic.ucfirst(v)
	return v, valnum
end

local function getValue(val, params)
	if type(val) == 'string' then
		return localdata[val]
	elseif type(val) == 'function' then
		return val(localdata, localdata.item, params)
	elseif type(val) == 'table' then
		for i, j in pairs(val) do -- في حال وجود قيم لأكثر من وسيط : أخذ بعين الاعتبار أول قيمة
			if localdata[j] then
				return localdata[j]
			end
		end
	end
end

function p.separator(params)
	local style = params['separator style'] or {}
	style.height = style.height or '2px'
	style['background-color'] = style['background-color'] or maincolor
	
	return mw.html.create('hr'):css( style )	
end

--[=[
تحضير لبنة العنوان في البطاقة

البيانات:قائمة جزئية) :
- value : Moyen d'obtenir le titre via getValue (nom de paramètre de modèle ou fonction).
- textdefaultvalue : النص الافتراضي للعنوان.
- icon : Pictogramme d'infobox (voir [[Projet:Infobox/Pictogramme]]).
]=]
function p.buildtitle(params)
	local text = getValue(params.value, params) or params.textdefaultvalue or  getWikidataValue(params) or mw.title.getCurrentTitle().text

	local subtext = getValue(params.subtitle) or  getWikidataValue(params, 'wikidatasubtitle') or params.subtitledefaultvalue
	if subtext and (subtext ~= text) then
		text = text .. '<br /><small>' .. subtext .. '</small>'
	end

	local class = 'entete ' .. (params.icon or '')
	
	-- overwrites with those provided in the module
	local style = {}
	style['background-color'] = maincolor
	style['color'] = thirdcolor
	if params.style then
		for i, j in pairs(params.style) do
			style[i] = j
		end
	end
	local title = mw.html.create('div')
		:addClass(class)
		:css(style)
		:tag('div')
			:wikitext(text)
		:allDone()
	return title
end
p.buildTitle = p.buildtitle



function p.buildimages(params)
    local function getwdImage(Q, property)

        property = property 
        local QID

        if type(Q) == 'table' and Q.id and Q.id ~= '-' 
            then QID = Q.id
            else return
        end	

        local wdata 

        if (type(property) == 'string') 
            then wdata = mw.wikibase.getBestStatements(QID, property) 
            elseif(type(property) == 'table')
            then for _,prop in ipairs(property) do
                    wdata = mw.wikibase.getBestStatements(QID,prop)
                    if(wdata) then break end
                end
            else return
        end

        local first

        for _, image in pairs(wdata) do
            if image.mainsnak.snaktype == 'value' then
                if not first then
                    first = image.mainsnak.datavalue.value
                end

                local q = image.qualifiers
                if q and q.P2096 then
                    for _, caption in pairs(q.P2096) do -- P2096 is 'caption'
                        if caption.snaktype == 'value' and caption.datavalue.value.language == wikiLang then
                            return image.mainsnak.datavalue.value, caption.datavalue.value.text
                        end
                    end
                end
            end
        end
        return first,''
    end

	local images = {}

	local upright, link, caption, captionfromwd, alt, size  -- size is deprecated

	if type(params.imageparameters) == 'string' then
		params.imageparameters = {params.imageparameters}
	end

	if not params.imageparameters then -- في حالة غياب أي مدخل لصورة
		params.imageparameters = {}
	end

	for j, k in ipairs(params.imageparameters) do
		table.insert(images, localdata[k])
	end
    
	-- Images from Wikidata 
	if #images == 0 and localdata.item then
		if params.property then
			params.wikidata = {entity = localdata.item, property = params.property}
		end

		if params.wikidata then
			local wdq = params.wikidata
			if type(params.wikidata.property) == 'table' then  params.wikidata.property = mw.text.listToText(params.wikidata.property, '**', '**') end
			
			if type(wdq) == 'table' then
				for p in string.gmatch(params.wikidata.property, 'P%d+') do				
					images,captionfromwd = getwdImage(localdata.item, p)
					if images then
						params.wikidata.property = p
						break
					end
				end				

				if captionfromwd then
					addMaintenanceCat("صفحات تستخدم خاصية P2096")
				end
				if images then
					addWikidataCat(params.wikidata.property)
				end
			end

			if type(wdq) == 'function' then
				images = params.wikidata()
				if type(images) == 'string' then
					return images
				end 
			end

			if type(images) == 'string' then
				images = {images}
			end

			if (not images) then
				images = {}
			end
		end
	end

	-- استعمال صور افتراضبة في حال عرفت
	if #images == 0 then
		if params.maintenancecat then
			addMaintenanceCat(params.maintenancecat, params.sortkey)
		end

		if params.defaultimages then
			images = params.defaultimages
			if type(images) == 'string' then
				images = {images}
			end
			upright = params.defaultimageupright
			caption = params.defaultimagecaption
			link = params.defaultimagelink
			alt = params.defaultimagealt
			if not alt and ( images[1] == 'DefautAr.svg' or images[1] == 'Defaut 2.svg' ) then
				alt = 'نحتاج صورة تكون من الأفضل حرة'
			end
		end
	end

	if #images == 0 then
		return nil
	end

	upright = upright or getValue(params.uprightparameter) or params.defaultupright or "1.2"
	link = link or getValue(params.linkparameter) or params.defaultlink
	caption = captionfromwd or caption or getValue(params.captionparameter) or params.defaultcaption 
	alt = alt or getValue( params.altparameter) or params.defaultalt

	size = size or getValue(params.sizeparameter) or params.defaultsize

	if size then
		local numsize = size:gsub('px', '')
		numsize = size:gsub('بك', '')
		numsize = mw.ustring.gsub(numsize, 'x.*', '')
		numsize = tonumber(numsize)

		if type(numsize) ~= 'number' or numsize > 280 then
			addMaintenanceCat("مقالات تسيء استعمال حجم الصورة")
		end

		if tonumber(size) then
			size = size .. 'px'
		end
		size = '|' .. size
	else
		size = ''
	end

	if tonumber(upright) then
		upright = tostring(tonumber(upright) ) / #images
	end

	if tonumber(size) then
		size = tostring(tonumber(size) ) / #images
	end

	local style = params.style or {padding ='2px 0',}

	-- تحضير عرض الصورة
	local imagesString = ''
	for i,image in pairs(images) do
		if image == '-' then
			return
		end

		image = string.match(image, '[^:]*:([^|%]]*)') or image
		imagesString = imagesString ..  '[[file:' .. image .. size .. '|frameless'

		-- [[
		if alt then
			imagesString = imagesString .. '|alt=' .. alt
		end

		if link then
			imagesString = imagesString .. '|link=' .. link
		end

		if upright then
			imagesString = imagesString .. '|upright=' .. upright
		elseif #images > 1 then
			imagesString = imagesString .. '|upright=' .. ( 1 / #images )
		end

		imagesString = imagesString .. ']]'
	end

	local image = mw.html.create('div')
		:addClass("images")
		:css(style)
		:wikitext(imagesString)
		:done()

	-- التعليق
	local captionobj
	if caption then
		captionobj = mw.html.create('div')
			:wikitext(caption)
			:css(params.legendstyle or {})
			:addClass("legend")
			:done()
	end

	-- الفاصل
	local separator
	if params.separator then
		separator = separator(params)
	end
	
	local imgout
	if params.inner then -- في حالة التواجد داخل الجدول
		imgout = mw.html.create('tr'):tag('th'):attr('colspan', 2)
	else
		imgout = mw.html.create('div'):css({	border="unset",padding="unset"})
	end
	
	return imgout
		:node(image)
		:node(captionobj)
		:node(separator)
		:done()
end
p.buildImages = p.buildimages

function p.buildtext(params)
	local class = params.class or ''
	local style = {
		['text-align'] = 'center',
		['font-weight'] = 'bold'
	}
	if params.style then
		for i, j in pairs(params.style) do
			style[i] = j
		end
	end
	local text = getValue(params.value, params) or getWikidataValue(params) or params.defaultvalue
	if text == '-' then
		return
	end
	if not text then
		addMaintenanceCat(params.maintenancecat, params.sortkey)
		return nil
	end
	local formattedtext = mw.html.create('p')
		:addClass(class)
		:css(style)
		:wikitext(text)
		:done()
	return formattedtext
end
p.buildText = p.buildtext

function p.buildrow(params)
	local class = params.class or ''
	local style = params.style or {}
	local valueClass = params.valueClass or ''
	local valueStyle = params.valueStyle or {}
	local value, number =  getValue(params.value, params)

	if (not value) then
		value, number =  getWikidataValue(params, 'wikidata')
	end
	if (not value) and (params.property) then
		value, number = expandQuery{ property = params.property } --, ucfirst = params.ucfirst
	end
	if not value then
		value = params.defaultvalue
	end
	if value == '-' then
		return nil
	end
	if not number then
		number = 0 -- == indéfini
	end

	if not value then
		if params.maintenancecat then
			local maintenancecat = getValue(params.maintenancecat, params)
			addMaintenanceCat(maintenancecat, params.sortkey)
		end
		return nil
	end

	local label = params.label

	if type(label) == 'table' then label= getValue(params.label, params) end 
	
	if number > 1 and (params.plurallabel) then
		label = params.plurallabel
	elseif number == 1 and (params.singularlabel) then
		label = params.singularlabel
	end

	if number > 4 then   --- اخفاء النتيجة في حال تجاوز عددها 4
		params.hidden = true
	end

	if type(label) == 'function' then
			label = label(localdata, localdata.item)
	end

	-- format
	local formattedvalue = mw.html.create('div')
		:wikitext('\n' .. value) -- رمز '\n' مطلوب عندما تكون value قائمة تبدأ بـ '*' ou '#'
		
	if (params.hidden == true)then
		local divNavHead = mw.html.create('div')
			:attr({class="nomobile", style="text-align:right;border: none; padding: 0; background:none; font-size: 75%;"})	
			:wikitext("&nbsp;[[file:Incomplete list.svg|20x20px|link=]] القائمة ...") --[عرض]/[إخفاء]
        formattedvalue
			:addClass('mw-collapsible-content')
        divNavHead = mw.html.create('div'):node(divNavHead)

		formattedvalue = mw.html.create('div')
			:attr({class="mw-collapsible mw-collapsed ", style="border: none; padding: 0;"})
			:node(divNavHead)
			:node(formattedvalue)
	end
	formattedvalue =  mw.html.create('td')
			:node(formattedvalue)
			:addClass(valueClass)
			:css(valueStyle)
			:allDone()
	
	local formattedlabel
	if label then
		formattedlabel = mw.html.create('th')
			:attr('scope', 'row')
			:wikitext(label)
			:done()
	end
	local row = mw.html.create('tr')
		:addClass(class)
		:css(style)
		:node(formattedlabel)
		:node(formattedvalue)
		:done()
	
	return row
end
p.buildRow = p.buildrow

function p.buildnavbox(params)
	
	-- définition du style
	local class = "overflow nav " .. (params.class or '')
	local style = params.style or {}

	if params.separated then -- خيار إضافة فاصل مسبق
		class = class .. ' bordered'
		style['border-top'] = '1px solid' .. maincolor
	end

	-- ترتيب البيانات
	params.previousval = params.previousval or params.previousparameter 
	params.nextval = params.nextval or params.nextparameter
	
	if params.previousproperty then
		params.previouswikidata = {property = params.previousproperty, conjtype='<br />'}
	end
	if params.nextproperty then
		params.nextwikidata = {property = params.nextproperty, conjtype='<br />'}
	end

	local previousval = getValue(params.previousval, params) or getWikidataValue(params, 'previouswikidata')
	local nextval = getValue(params.nextval, params) or getWikidataValue(params, 'nextwikidata')
	
	local navbox
	if params.inner then -- في حالة التواجد داخل الجدول
		navbox = mw.html.create('tr'):tag('th'):attr('colspan', 2)
		style['font-weight'] = style['font-weight'] or 'normal'
	else
		navbox = mw.html.create('div')
	end
	
	local prevNode, nextNode
	if previousval then
		prevNode = mw.html.create('div')
				:addClass('prev_bloc')
				:wikitext(previousval)
				:done()		
	end
	if nextval then
		nextNode = mw.html.create('div')
				:addClass('next_bloc')
				:wikitext(nextval)
				:done()	
	end
	if previousval or nextval then
		navbox
			:addClass(class)
			:css(style)
			:node(prevNode)
			:node(nextNode)
			:allDone()
		return navbox
	end
	return nil
end
p.buildNavbox = p.buildnavbox

function p.buildsuccession(params)
	if not params.value then
		return nil
	end
		
	local rowI = mw.html.create('tr')
	
	cellI = mw.html.create('td')
			:attr({colspan = '2'})
			:attr({align = 'center'})
	
	local styleT = {}
	styleT['background-color'] = 'transparent'
	styleT['width'] = '100%'
	tabC = mw.html.create('table')
			:attr({cellspacing = '0'})
			:addClass('navigation-not-searchable')
			:css(styleT)
	
	local row = mw.html.create('tr')

	local color = params.color

	local style = {}
	local arrowLeft
	local arrowRight
	
	if color == 'default' then
		style['background-color'] = '#E6E6E6'
		arrowLeft = '[[file:Fleche-defaut-droite.png|13px|alt=سابق|link=]]'
		arrowRight = '[[file:Fleche-defaut-gauche.png|13px|alt=سابق|link=]]'
	else
		style['background-color'] = color
		arrowLeft = '[[file:Fleche-defaut-droite-gris-32.png|13px|alt=لاحق|link=]]'
		arrowRight = '[[file:Fleche-defaut-gauche-gris-32.png|13px|alt=لاحق|link=]]'
	end
	
	local styleTrans = {}
	styleTrans['background-color'] = '#F9F9F9'

-- ترتيب البيانات
	params.previousval = params.previousval or params.previousparameter 
	params.nextval = params.nextval or params.nextparameter
	
	if params.previousproperty then
		params.previouswikidata = {property = params.previousproperty}
	end
	if params.nextproperty then
		params.nextwikidata = {property = params.nextproperty}
	end

	local before = params.value['before'] or getValue(params.previousval, params) or getWikidataValue(params, 'previouswikidata')
	local after = params.value['after'] or getValue(params.nextval, params) or getWikidataValue(params, 'nextwikidata')

	local center = params.value['center']
--
	
	local widthCell = '44%'
	if center then
		widthCenter = '28%'
		widthCell = '29%'
	end
	
	local formattedbefore
	if before then
		formattedbefore = mw.html.create('td')
			:attr({valign = 'middle'})
			:attr({align = 'right'})
			:attr({width = '5%'})
			:css(style)
			:wikitext(arrowLeft)
			:done()
		row:node(formattedbefore)
		formattedbefore = mw.html.create('td')
			:attr({width = '1%'})
			:css(style)
			:wikitext('')
			:done()
		row:node(formattedbefore)
		formattedbefore = mw.html.create('td')
			:attr({align = 'right'})
			:attr({valign = 'middle'})
			:attr({width = widthCell})
			:css(style)
			:wikitext(before)
			:done()
		row:node(formattedbefore)
	else
		formattedbefore = mw.html.create('td')
			:attr({valign = 'middle'})
			:attr({align = 'right'})
			:attr({width = '5%'})
			:css(styleTrans)
			:wikitext('')
			:done()
		row:node(formattedbefore)
		formattedbefore = mw.html.create('td')
			:attr({width = '1%'})
			:css(styleTrans)
			:wikitext('')
			:done()
		row:node(formattedbefore)
		formattedbefore = mw.html.create('td')
			:attr({align = 'right'})
			:attr({valign = 'middle'})
			:attr({width = widthCell})
			:css(styleTrans)
			:wikitext('')
			:done()
		row:node(formattedbefore)
	end
	
	local formattedcenter
	formattedcenter = mw.html.create('td')
		:attr({width = '1%'})
		:css(styleTrans)
		:wikitext('')
		:done()
	row:node(formattedcenter)
	
	if center then
		formattedcenter = mw.html.create('td')
			:attr({align = 'center'})
			:attr({valign = 'middle'})
			:attr({width = widthCenter})
			:css(style)
			:wikitext(center)
			:done()
		row:node(formattedcenter)
		formattedcenter = mw.html.create('td')
			:attr({width = '1%'})
			:css(styleTrans)
			:wikitext('')
			:done()
		row:node(formattedcenter)
	end
	
	local formattedafter
	if after then
		formattedafter = mw.html.create('td')
			:attr({align = 'left'})
			:attr({valign = 'middle'})
			:attr({width = widthCell})
			:css(style)
			:wikitext(after)
			:done()
		row:node(formattedafter)
		formattedbefore = mw.html.create('td')
			:attr({width = '1%'})
			:css(style)
			:wikitext('')
			:done()
		row:node(formattedbefore)
		formattedafter = mw.html.create('td')
			:attr({align = 'left'})
			:attr({valign = 'middle'})
			:attr({width = '5%'})
			:css(style)
			:wikitext(arrowRight)
			:done()
		row:node(formattedafter)
	else
		formattedafter = mw.html.create('td')
			:attr({align = 'left'})
			:attr({valign = 'middle'})
			:attr({width = widthCell})
			:css(styleTrans)
			:wikitext('')
			:done()
		row:node(formattedafter)
		formattedbefore = mw.html.create('td')
			:attr({width = '1%'})
			:css(styleTrans)
			:wikitext('')
			:done()
		row:node(formattedbefore)
		formattedafter = mw.html.create('td')
			:attr({align = 'left'})
			:attr({valign = 'middle'})
			:attr({width = '5%'})
			:css(styleTrans)
			:wikitext('')
			:done()
		row:node(formattedafter)
	end
	
	row:done()
	tabC:node(row)
	tabC:done()
	cellI:node(tabC)
	cellI:done()
	rowI:node(cellI)
	rowI:allDone()
	
	return rowI
end
p.buildSuccession = p.buildsuccession

function p.buildrow1col(params)

	local value, number =  getValue(params.value, params)

	if (not value) then
		value, number =  getWikidataValue(params, 'wikidata')
	end
	if (not value) and (params.property) then
		value, number = expandQuery{ property = params.property } 
	end
	if not value then
		value = params.defaultvalue
	end
	if value == '-' or type(value)== 'nil' then
		return nil
	end	

	local class = params.class
	local rowcolor
	if params.color == 'secondcolor' then
		rowcolor = secondcolor
	else
		rowcolor = params.color
	end
	
	local style = {}
	style['padding'] = '4px'
	style['text-align'] = 'center'
	style['background-color'] = rowcolor or '#F9F9F9'
	style['color'] = '#000000'

	if number > 4 then   --- اخفاء النتيجة في حال تجاوز عددها 4
		params.hidden = true
	end


	local formattedvalue = mw.html.create('div')
		:wikitext('\n' .. value) -- رمز '\n' مطلوب عندما تكون value قائمة تبدأ بـ '*' ou '#'

	if (params.hidden == true) then
		local divNavHead = mw.html.create('div')
			:attr({class="nomobile", style="text-align:right;border: none; padding: 0; background:none; font-size: 75%;"})	
			:wikitext("&nbsp;[[file:Incomplete list.svg|20x20px|link=]] القائمة ...") --[عرض]/[إخفاء]
        formattedvalue
			:addClass('mw-collapsible-content')
        divNavHead = mw.html.create('div'):node(divNavHead)

		formattedvalue = mw.html.create('div')
			:attr({class="mw-collapsible mw-collapsed ", style="border: none; padding: 0;"})
			:node(divNavHead)
			:node(formattedvalue)
	end
	formattedvalue =  mw.html.create('th')
			:node(formattedvalue)
			:attr({colspan = '2'})
			:css(style)
			:done()

	local row = mw.html.create('tr')
		:addClass(class)
		:css(style)
		:node(formattedvalue)
		:done()
	
	return row
end
p.buildRow1Col = p.buildrow1col

function p.buildsubtitle(params)
	local class = params.class or ''
	local style = { ['margin-top'] ='-8px',['margin-bottom'] ='10px',
		['text-align'] = 'center',
		['font-size'] = '90%',
		['background-color'] = maincolor,
		['color'] = thirdcolor,
		flex= "auto",
		width="100%"
	}

	if params.style then
		for i, j in pairs(params.style) do
			style[i] = j
		end
	end

	local text = getValue(params.value, params) or getWikidataValue(params) or params.defaultvalue
	if text == '-' then
		return
	end

	if not text then
		addMaintenanceCat(params.maintenancecat, params.sortkey)
		return nil
	end

	local title = mw.html.create('div')
		:addClass(class)
		:css(style)
		:tag('div')
		:wikitext(text)
		:allDone()

	return title
end

p.buildSubTitle = p.buildsubtitle

function p.buildtable(params)
	local tab = mw.html.create('table'):css(params.style or {})

	local rows = params.rows
	
	-- expand parameters so that we have a list of tables
	local i = 1

	while (i <= #rows) do 
		local l = rows[i]
		if type(l) == 'function' then 
			l = l(localdata, localdata.item)
		end
		if (type(l) == 'table') and (l.type == 'multi') then
			table.remove(rows, i)  
			for j, row in ipairs(l.rows) do
				table.insert(rows, i + j - 1, row) 
			end
		elseif type(l) == 'nil' then
			table.remove(rows, i)
		elseif type(l) ~= 'table' then 
			return error('أسطر قالب البطاقة ("rows") على شكل جداول (table), وليست ' .. type(l))
		else
			i = i + 1
		end
	end 

	-- CREATE ROW
	local expandedrows = {}
	for k, row in ipairs(rows) do
		local v = p.buildblock(row)
		if v then
			table.insert(expandedrows, v)
		end
	end
	if (#expandedrows == 0) then
		return nil
	end
	rows = expandedrows

	-- ADD TITLE
	local title
	if params.title or params.singulartitle or params.pluraltitle then
		local text
		if #rows > 1 and params.pluraltitle then
			text = params.pluraltitle
		elseif #rows == 1 and params.singulartitle then
			text = params.singulartitle
		else
			text = params.title
		end

		local style = params.titlestyle or {display = 'table-caption'}
		style['text-align'] = style['text-align'] or 'center'
		style['color'] = style['color'] or thirdcolor
		style['background-color'] = style['background-color'] or secondcolor

		title = mw.html.create('caption')
			:attr({colspan = '2'})
			:css(style)
			:wikitext(text)
			:done()
	end
	
	if title then
		tab:node(title)
	end
	
	for i, j in pairs (rows) do
		tab:node(j)
	end
	
	if params.separator then
		local separator = p.separator(params)
		tab:node(separator)
	end
	tab:allDone()
	return tab
end
p.buildTable = p.buildtable

function p.buildinvalidblock(args)
	addMaintenanceCat(defaultcat)
	local text = ''
	if type(args) ~= 'table' then
		text = "لبنات قالب بطاقة يجب أن تكتب على شكل جداول (table)"
	else
		text = i18n["invalid block type"] .. ' : ' .. (args.type or '??')
	end
	return text
end
p.buildInvalidBlock = p.buildinvalidblock

function p.buildmap(params)

	local latitude = getValue({'latitude','دائرة العرض','دائرة عرض'})
	local longitude = getValue({'longitude','خط الطول','خط طول'})
	
	local itemid
	if localdata.item and localdata.item.id then itemid = localdata.item.id end
		
	if(not params.ids  and not longitude and not itemid	)		then return end
	
	local width = tonumber(params.width) or 260
	if width > 260 then
		addMaintenanceCat("خطأ في بطاقة/صورة بأبعاد كبيرة")
		 width = 260
	end
	
	newparams = {
		  ['marker-symbol'] = params.marker or 'marker'
		, ['marker-color'] = params.markercolor or '#FF0000'
		, ['marker-size'] =  params.markersize
		, frameless='yes'
		, ['width']=width
		, ['height']=width
		, ['latitude']= latitude
		, ['longitude']=  longitude
		, ['align']='center'
		, type='mapframe'
		, item = itemid
		, ids = params.ids
		, zoom= params.zoom or params.default_zoom or 9
		, lang="ar"
        , title = mw.title.getCurrentTitle().text
		--, debug = 1
	}
	if params.params and type(params.params) == 'table' then -- بيانات اضافية
		for i, j in pairs(params.params) do
			if(not newparams[i]) then newparams[i] = j end
		end
	end
	
    local f_tag = require('Module:Map')._tag
	noerr,data = pcall(f_tag,newparams)	
	if noerr == true
		then return data
		else 
			addMaintenanceCat('مقالات بها أخطاء مصدرها وحدة بطاقة')
			mw.log("Error from [[Module:Map]] : "..mw.dumpObject(data))
			return nil 
	end    

end
p.buildMap = p.buildmap

function p.buildexternaltext(params)
	local value = getValue(params.value)
	if value and (type(value) == 'string') then
		externaltext = externaltext .. value
	end
end
p.buildExternalText = p.buildexternaltext

function p.buildfooter(params)
	if not params then
		params = {}
	end
	
	local class = 'navbar noprint bordered ' .. (params.class or '')
	local style = params.style or {flex= "auto";}
	style['border-top'] = style['border-top'] or '2px dotted ' .. maincolor
	style['display'] =  'block'
	
	local backlinkstr = '[' .. tostring( mw.uri.fullUrl( page.name, 'veaction=edit&section=0' ) ) .. ' ' .. i18n['edit'] .. ']'
		.. ' - [' .. tostring( mw.uri.fullUrl( page.name, 'action=edit&section=0' ) ) .. ' ' .. i18n['edit code'] .. ']'

	local itemlinkstr
	if localdata.item and  localdata.item.id then
		itemlinkstr = '[[d:' .. localdata.item.id .. '|' .. i18n['edit item'] .. ']]'
	end
	local editstr = backlinkstr
	if itemlinkstr then
		editstr = editstr .. ' - ' .. itemlinkstr
	end
	local editlinkspan =  mw.html.create('span')
		:css({['text-align'] = "right", ['font-size'] = "80%",['background'] = "inherit"})
		:addClass('plainlinks')
		:wikitext(editstr)
		:done()
	local doclinkstr = '[[File:Test_Template_Info-Icon_-_Version_(2).svg|30x15px|link=' .. localdata.templatename .. '|' .. i18n['see doc'] .. ']]'

	local doclinkspan = mw.html.create('span')
		:css({['text-align'] = "left",['float'] = "left"})
		:wikitext(doclinkstr)
		:done()
	
	local footer = mw.html.create('p')
		:addClass(class)
		:css(style)
		:node(editlinkspan)
		:node(doclinkspan)
	return footer
end
p.buildFooter = p.buildfooter

function p.buildblock(block)
	if type(block) == 'function' then
		block = block( localdata )
	end

	local blocktypes = { -- list of functions for block buildings
		['invalid'] = p.buildinvalidblock,
		['external text'] = p.buildexternaltext,
		['footer'] = p.buildfooter,
		['images'] = p.buildimages,
		['map']= p.buildmap,
		['mixed'] = p.buildrow,
		['navbox'] = p.buildnavbox,
		['table'] = p.buildtable,
		['row'] = p.buildrow,
		['row1col'] = p.buildrow1col,
		['succession'] = p.buildsuccession,
		['text'] = p.buildtext,
		['title'] = p.buildtitle,
		['subtitle'] = p.buildsubtitle,
	}
	if type(block) ~= 'table' or (not block.type) or (not blocktypes[block.type]) then
		return blocktypes['invalid'](block)
	end
	return blocktypes[block.type](block) 
end
p.buildBlock = p.buildblock

function p.build()
	
	localdata = require( 'وحدة:بطاقة/بيانات')
	item = localdata.item

	-- assign rank to the infobox, "secondary" means special formatting like no displaytitle for coordinates
	local infoboxrank = 'main' -- main infobox of the page, with coordinates displayed in title etc.
	if page.namespace ~= 0 then
		infoboxrank = 'secondary'
	end
	-- if infobox is linked to another item: rank = secondary
	if localdata.item and localdata.item.id then
		local itemlink = mw.wikibase.sitelink(localdata.item.id)
		local pagetitle = mw.title.getCurrentTitle().text
		if (itemlink or '') ~= pagetitle then
			infoboxrank = 'secondary'
		end
	end
	localdata.infoboxrank = infoboxrank

	-- load infobox module page
	local moduledata = require('وحدة:بطاقة/قالب/' .. localdata.modulename )

	moduledata.name = localdata.modulename
	localdata.wikimod = moduledata.wikimod or moduledata.wikidatamod or moduledata.wdmod
	
	-- defines main color
	maincolor = localdata['infobox color'] or localdata['لون البطاقة'] or moduledata.maincolor or maincolor
	secondcolor = moduledata.secondcolor or secondcolor
	thirdcolor = localdata['text color'] or localdata['لون النص'] or moduledata.thirdcolor or thirdcolor
	if maincolor:match( '^%x%x%x%x%x%x$' ) or maincolor:match( '^%x%x%x$' ) then
		maincolor = '#' .. maincolor
	end
	if thirdcolor:match ('نعم') or thirdcolor:match( 'true' ) then
		thirdcolor = '#000'
	end
	if thirdcolor:match ('لا') or thirdcolor:match( 'false' ) then
		thirdcolor = '#fff'
	end
	
	-- class
	local class = 'infobox_v3b mainTable infobox'
	if moduledata.class then
		class = class .. ' ' .. moduledata.class
	end
	
	-- style
	local style = moduledata.style or {}

	-- build infobox
	-- النتيجة النهائية
	local infobox = mw.html.create('td') --mw.html.create('div')
         --:addClass(class)
         :css({display= "flex"
         	,["flex-wrap"]= "wrap"
         	,["flex-direction"]= "row"
         	,["justify-content"]= "center"
         	,["align-items"]= "center"}) 
         :done()

	for i, j in pairs( moduledata.parts ) do
		infobox:node( p.buildblock(j) )
	end
	infobox	:node(p.buildfooter(moduledata.footer))
			:done()
			
    infobox=mw.html.create('table')
          :addClass(class)
         :css(style)
         :node(infobox)
         :done()
         
	templatestyles = mw.getCurrentFrame():extensionTag( 'templatestyles', '', 
		{src = "بطاقة/infobox v3b/styles.css"})
		..mw.getCurrentFrame():extensionTag( 'templatestyles', '', { src = "بطاقة/icones.css"}
	)
	;
	return templatestyles .. tostring(infobox) .. externaltext, maintenance
end

p['تركيب'] = p.build

return p