انتقل إلى المحتوى

وحدة:Multiple image

من ويكيبيديا، الموسوعه الحره

يمكن إنشاء صفحة توثيق الوحدة في وحدة:Multiple image/شرح

--[[
وحدة لمعالجة قالب متعدد الصور
تستخدم لإنشاء معارض صور متعددة بتخطيطات مختلفة
]]

local p = {}

-- دالة مساعدة للتحقق من أن القيمة غير فارغة
local function isnotempty(s)
    return s and s:match('^%s*(.-)%s*$') ~= ''
end

-- دالة مساعدة لإزالة 'px' أو 'بك' من نهاية السلسلة
local function removepx(s)
    return tostring(s or ''):match('^(.*)[Pp][Xx]%s*$') or tostring(s or ''):match('^(.*)بك%s*$') or s
end

-- دالة مساعدة للحصول على وسيط من جدول الوسائط
local function getArg(pargs, keys)
    for _, key in ipairs(keys) do
        -- جرب المفتاح كما هو
        if isnotempty(pargs[key]) then
            return pargs[key]
        end

        local alt1 = key:gsub('_', ' ')
        if alt1 ~= key and isnotempty(pargs[alt1]) then
            return pargs[alt1]
        end

        local alt2 = key:gsub(' ', '_')
        if alt2 ~= key and isnotempty(pargs[alt2]) then
            return pargs[alt2]
        end
    end
    return nil
end

-- قاموس لتحويل الاتجاهات من العربية إلى الإنجليزية
local dir_ar_to_en = {
    ["v"] = 'vertical',
    ["عمودي"] = 'vertical',
    ["vertical"] = 'vertical',
    ["رأسي"] = 'vertical',
    ["أفقي"] = 'horizontal',
    ["horizontal"] = 'horizontal',
    ["h"] = 'horizontal',
}

-- قاموس لتحويل المحاذاة من العربية إلى الإنجليزية
local ar_to_en = {
    ["يسار"] = 'left',
    ["يمين"] = 'right',
    ["مركز"] = 'center',
    ["وسط"] = 'center',
    ["left"] = 'left',
    ["right"] = 'right',
    ["center"] = 'center'
}

-- قاموس لفئات الصور المصغرة
local thumbclass = {
    ["يسار"] = 'tleft',
    ["left"] = 'tleft',
    ["none"] = 'tnone',
    ["center"] = 'tnone',
    ["مركز"] = 'tnone',
    ["وسط"] = 'tnone',
    ["centre"] = 'tnone',
    ["right"] = 'tright',
    ["يمين"] = 'tright'
}

-- دالة للحصول على أبعاد الصورة
local function getdimensions(s, w, h)
    local width, height
    if tonumber(w) and tonumber(h) then
        p.nonautoscaledimages = true
        width, height = tonumber(w), tonumber(h)
    else
        local file = s and mw.title.new('File:' .. mw.uri.decode(mw.ustring.gsub(s, '%|.*$', ''), 'WIKI'))
        file = file and file.file or {width = 0, height = 0}
        width = tonumber(file.width) or 0
        height = tonumber(file.height) or 0
        p.autoscaledimages = true
    end
    return width, height
end

-- دالة لعرض خلية الصورة
local function renderImageCell(image, width, height, link, alt, thumbtime, caption, textalign, istyle, lang)
    local root = mw.html.create('')

    local altstr = '|alt=' .. (alt or '')
    local linkstr = link and ('|link=' .. link) or ''
    local widthstr = '|' .. tostring(width) .. 'px'
    local thumbtimestr = isnotempty(thumbtime) and ('|thumbtime=' .. thumbtime) or ''
    local langstr = isnotempty(lang) and ('|lang=' .. lang) or ''

    local imagediv = root:tag('div')
    imagediv:addClass('thumbimage')
    imagediv:cssText(istyle)
    
    if height then
        imagediv:css('height', tostring(height) .. 'px')
        imagediv:css('overflow', 'hidden')
    end
    
    imagediv:wikitext('[[ملف:' .. image .. langstr .. widthstr .. linkstr .. altstr .. thumbtimestr .. ']]')
    
    if isnotempty(caption) then
        local captiondiv = root:tag('div')
        captiondiv:addClass('thumbcaption')
        if isnotempty(textalign) then
            captiondiv:addClass('text-align-' .. textalign)
        end
        captiondiv:wikitext(caption)
    end
    
    return tostring(root)
end

-- دالة للحصول على العرض الافتراضي
local function getWidth(w1, w2)
    local w
    if isnotempty(w1) then
        w = tonumber(w1)
    elseif isnotempty(w2) then
        w = tonumber(w2)
    end
    return w or 200
end

-- دالة لتحديد عدد الصور في كل صف
local function getPerRow(pstr, ic)
    local pr = mw.text.split(pstr or '', '[^%d][^%d]*')
    if #pr < 1 then
        pr = {tostring(ic)}
    end
    
    local r = 1
    local thisrow = tonumber(pr[1] or ic) or ic
    local prownum = {}
    
    while ic > 0 do
        prownum[r] = thisrow
        ic = ic - thisrow
        r = r + 1
        thisrow = math.min(tonumber(pr[r] or thisrow) or ic, ic)
    end
    
    return prownum
end

-- الدالة الرئيسية لعرض الصور المتعددة
local function renderMultipleImages(pargs, args)
    local dir = dir_ar_to_en[getArg(pargs, {'direction', 'اتجاه'}) or args['direction'] or args['اتجاه']] or ''
    local width = removepx(pargs['width'] or pargs['عرض'] or '')
    local border = pargs['border'] or args['border'] or ''
    local align = ar_to_en[getArg(pargs, {'align', 'محاذاة'}) or args['align'] or args['محاذاة']] or ''
    local capalign = ar_to_en[getArg(pargs, {'caption_align', 'محاذاة_تعليق'}) or args['caption_align'] or args['محاذاة_تعليق']] or ''
    
    local totalwidth = removepx(getArg(pargs, {'total_width', 'مجمل_العرض'}) or args['total_width'] or args['مجمل_العرض'] or '')
    local imgstyle = getArg(pargs, {'image_style', 'نمط_الصورة'}) or args['image_style'] or args['نمط_الصورة']
    local header = getArg(pargs, {'header', 'title', 'رأس', 'عنوان'}) or args['title'] or args['عنوان'] or args['header'] or args['رأس']
    local footer = getArg(pargs, {'footer', 'تذييل'}) or args['footer'] or args['تذييل']
    local imagegap = tonumber(pargs['image_gap'] or '1') or 1
    local header_align = ar_to_en[getArg(pargs, {'header_align', 'محاذاة_العنوان'})] or ''
    local footer_align = ar_to_en[getArg(pargs, {'footer_align', 'محاذاة_التذييل'}) or args['footer_align'] or args['محاذاة_التذييل']] or 'right'
    local background_color = getArg(pargs, {'background color', 'لون_الخلفية'})
    local header_bg = getArg(pargs, {'header_background', 'خلفية_العنوان'})
    local footer_bg = getArg(pargs, {'footer_background', 'خلفية_التذييل'})
    local perrow_arg = getArg(pargs, {'perrow', 'لكل_سطر'})

    -- البحث عن جميع الصور غير الفارغة
    local imagenumbers = {}
    local imagecount = 0
    for k, v in pairs(pargs) do
        local i = tonumber(tostring(k):match('^%s*image([%d]+)%s*$') or tostring(k):match('^%s*صورة([%d]+)%s*$') or '0')
        if i > 0 and isnotempty(v) then
            table.insert(imagenumbers, i)
            imagecount = imagecount + 1
        end
    end

    -- ترتيب أرقام الصور
    table.sort(imagenumbers)

    -- إنشاء مصفوفة بعدد الصور في كل صف
    local perrow = getPerRow(dir == 'vertical' and '1' or perrow_arg, imagecount)
    local rowcount = #perrow

    -- تخزين أبعاد الصور وحساب أبعاد الصفوف
    local heights = {}
    local widths = {}
    local widthmax = 0
    local widthsum = {}
    local k = 0
    
    for r = 1, rowcount do
        widthsum[r] = 0
        for c = 1, perrow[r] do
            k = k + 1
            if k <= imagecount then
                local i = imagenumbers[k]
                if isnotempty(totalwidth) then
                    local a_image = pargs['image' .. i] or pargs['صورة' .. i]
                    local a_width = pargs['width' .. i] or pargs['عرض' .. i]
                    local a_height = pargs['height' .. i] or pargs['ارتفاع' .. i]
                    widths[k], heights[k] = getdimensions(a_image, a_width, a_height)
                else
                    local a_width = pargs['width' .. i] or pargs['عرض' .. i]
                    widths[k] = getWidth(width, a_width)
                end
                widthsum[r] = widthsum[r] + widths[k]
            end
        end
        widthmax = math.max(widthmax, widthsum[r])
    end

    -- التأكد من أن الفجوة بين الصور غير سالبة
    if imagegap < 0 then imagegap = 0 end

    -- إذا تم تحديد العرض الكلي، تغيير حجم الصور
    if isnotempty(totalwidth) then
        totalwidth = tonumber(totalwidth)
        widthmax = 0
        local k = 0
        
        for r = 1, rowcount do
            local koffset = k
            local tw = totalwidth - (3 + imagegap) * (perrow[r] - 1) - 12
            local ar = {}
            local arsum = 0
            
            for j = 1, perrow[r] do
                k = k + 1
                if k <= imagecount then
                    local i = imagenumbers[k]
                    local h = heights[k] or 0
                    if h > 0 then
                        ar[j] = widths[k] / h
                        heights[k] = h
                    else
                        ar[j] = widths[k] / 100
                    end
                    arsum = arsum + ar[j]
                end
            end
            
            local ht = tw / arsum
            local ws = 0
            k = koffset
            
            for j = 1, perrow[r] do
                k = k + 1
                if k <= imagecount then
                    local i = imagenumbers[k]
                    widths[k] = math.floor(ar[j] * ht + 0.5)
                    ws = ws + widths[k]
                    if heights[k] then
                        heights[k] = math.floor(ht)
                    end
                end
            end
            
            widthsum[r] = ws
            widthmax = math.max(widthmax, widthsum[r])
        end
    end

    -- بدء بناء مصفوفة الصور إذا كانت هناك صور
    if imagecount > 0 then
        -- حساب عرض div الخارجي
        local bodywidth = 0
        for r = 1, rowcount do
            if widthmax == widthsum[r] then
                bodywidth = widthmax + (3 + imagegap) * (perrow[r] - 1) + 12
            end
        end
        
        bodywidth = math.max(100, bodywidth - 8)

        local bg = background_color or ''
        local root = mw.html.create('div')
        root:addClass('thumb')
        root:addClass('tmulti')
        root:addClass(thumbclass[align] or 'tleft')

        if align == 'center' or align == 'centre' then
            root:addClass('center')
        end
        
        if bg ~= '' then
            root:css('background-color', bg)
        end

        local div = root:tag('div')
        div:addClass('thumbinner')
        div:css('width', tostring(bodywidth) .. 'px')
           :css('max-width', tostring(bodywidth) .. 'px')
           
        if bg ~= '' then
            div:css('background-color', bg)
        end
        
        if border == 'infobox' or border == 'none' then
            div:css('border', 'none')
        end

        -- إضافة العنوان
        if isnotempty(header) then
            div:tag('div')
               :addClass('trow')
               :tag('div')
                  :addClass('theader')
                  :css('text-align', header_align)
                  :css('background-color', header_bg)
                  :wikitext(header)
        end

        -- حلقة لعرض الصور
    local k = 0
    for r = 1, rowcount do
        local rowdiv = div:tag('div'):addClass('trow')
        
        for j = 1, perrow[r] do
            k = k + 1
            if k <= imagecount then
                local imagediv = rowdiv:tag('div')
                imagediv:addClass('tsingle')
                
                if bg ~= '' then
                    imagediv:css('background-color', bg)
                end
                
                if imagegap > 1 and j < perrow[r] then
                	-- in Arabic margin-left
                    imagediv:css('margin-left', tostring(imagegap) .. 'px')
                end
                
                local i = imagenumbers[k]
                local img = pargs['image' .. i] or pargs['صورة' .. i]
                local w = widths[k]
                local a_caption = pargs['caption' .. i] or pargs['تعليق' .. i]
                local a_link = pargs['link' .. i] or pargs['وصلة' .. i]  -- الجديد
                local a_alt = pargs['alt' .. i] or pargs['بديل' .. i]      -- الجديد
                
                imagediv:css('width', tostring(2 + w) .. 'px')
                       :css('max-width', tostring(2 + w) .. 'px')
                       :wikitext(renderImageCell(img, w, heights[k],
                           a_link, a_alt,  -- استخدام المتغيرات الجديدة
                           pargs['thumbtime' .. i], a_caption, capalign, imgstyle, pargs['lang' .. i]))
            end
        end
    end

        -- إضافة التذييل
        if isnotempty(footer) then
            local footerContainer = div:tag('div')
               :addClass('trow')
               :css('display', 'block')
            
            local footerDiv = footerContainer:tag('div')
                  :addClass('thumbcaption')
                  :css('text-align', footer_align)  
                  :css('background-color', footer_bg)
            
            if footer_align == 'center' then
                footerDiv:css('display', 'block')
                         :css('margin-left', 'auto')
                         :css('margin-right', 'auto')
            end
            
            footerDiv:wikitext(footer)
        end
        return tostring(root)
    end
    
    return ''
end

-- دالة للاستدعاء من القوالب
function p.render(frame)
    local pargs = frame:getParent().args or {}
    local args = frame.args or {}

    p.autoscaledimages = false
    p.nonautoscaledimages = false

    local result = frame:extensionTag {
        name = 'templatestyles',
        args = {src = 'Multiple image/styles.css', wrapper = ".tmulti"}
    } .. renderMultipleImages(pargs, args)
    
    if p.autoscaledimages then
        result = result .. '[[تصنيف:صفحات تستخدم قالب عدة صور بمقاس تلقائي]]'
    end
    
    if p.nonautoscaledimages then
        result = result .. '[[تصنيف:صفحات تستخدم قالب عدة صور بمقاس محدد]]'
    end
    
    return result
end

-- جعل الدالة متاحة للاستدعاء من وحدات أخرى
function p.renderMultipleImages(args)
    return renderMultipleImages(args,args) 
		.. mw.getCurrentFrame():extensionTag( 'templatestyles', '', { src = "Multiple image/styles.css"})	
end

return p