Modul:Gallery: Forskjell mellom sideversjoner
Hopp til navigering
Hopp til søk
(norske parametre) |
m (Én sideversjon ble importert) |
||
(4 mellomliggende versjoner av 3 brukere er ikke vist) | |||
Linje 1: | Linje 1: | ||
-- This module implements {{gallery}} |
-- This module implements {{gallery}} by wrapping the <gallery> core extension tag. |
||
local p = {} |
local p = {} |
||
Linje 5: | Linje 5: | ||
local templatestyles = 'Module:Gallery/styles.css' |
local templatestyles = 'Module:Gallery/styles.css' |
||
local yesno = require('Module:Yesno') |
local yesno = require('Module:Yesno') |
||
local plaintextModule = require('Module:Plain text') |
|||
local function plaintext(text) |
|||
-- stips out external links without labels, |
|||
-- and then passes to the Plain_text module to clean the rest |
|||
return plaintextModule.main({ args = { |
|||
text:gsub("([^%[])%[([^%[%]%s]+)%]", '%1') |
|||
, encode = "no" } }) |
|||
end |
|||
local function trim(s) |
local function trim(s) |
||
return mw.ustring.gsub(mw.ustring.gsub(s, '%s', ' '), '^%s*(.-)%s*$', '%1') |
return mw.ustring.gsub(mw.ustring.gsub(s or '', '%s', ' '), '^%s*(.-)%s*$', '%1') |
||
end |
end |
||
local tracking, preview |
local tracking, preview |
||
local function isImage(file) |
|||
local file = trim(file):lower() -- Case insensitive check |
|||
-- Check if it starts with "Fil:", "Bilde:", "File:", "Image:", or "Media:" |
|||
local prefix = file:match("^(%a+):") |
|||
if prefix and (prefix == "fil" or prefix == "bilde" or prefix == "file" or prefix == "image" or prefix == "media") then |
|||
return true |
|||
end |
|||
local valid_extensions = { |
|||
"apng", "djvu", "flac", "gif", "jfi", "jfif", "jif", "jpe", "jpeg", "jpg", |
|||
"m1a", "m1v", "m2a", "m2v", "mid", "mp1", "mp2", "mp3", "mpa", "mpe", "mpeg", "mpg", |
|||
"mpv", "oga", "ogg", "ogv", "opus", "pdf", "png", "stl", "svg", "svgz", "tif", "tiff", |
|||
"wav", "wave", "webm", "webp", "xcf" |
|||
} |
|||
-- Extract file extension, of 3 or 4 characters only |
|||
local ext = file:match("%.(%w%w%w%w?)$") |
|||
-- Check if the extension is in the valid list |
|||
if ext then |
|||
for _, valid_ext in ipairs(valid_extensions) do |
|||
if ext == valid_ext then |
|||
table.insert(tracking, '[[Category:Pages using gallery without a media namespace prefix]]') |
|||
return true |
|||
end |
|||
end |
|||
end |
|||
return false |
|||
end |
|||
local function checkarg(k,v) |
local function checkarg(k,v) |
||
if k and type(k) == 'string' then |
if k and type(k) == 'string' then |
||
if |
if k == 'bredde' or k == 'høyde' or k == 'tittel' or 'fotnote' or |
||
k == 'align' or k == 'state' or k == 'style' or k == 'title' or |
|||
k == 'width' or k == 'height' or k == 'whitebg' or |
k == 'width' or k == 'height' or k == 'whitebg' or |
||
k == 'mode' or k == 'footer' or k == 'perrow' or k == 'noborder' or |
k == 'mode' or k == 'footer' or k == 'perrow' or k == 'noborder' or |
||
k:match('^alt%d+$') or k:match('^%d+$') then |
k:match('^alt%d+$') or k:match('^class%d+$') or k:match('^%d+$') then |
||
-- valid |
-- valid |
||
elseif k == 'captionstyle' then |
elseif k == 'captionstyle' then |
||
Linje 27: | Linje 67: | ||
-- invalid |
-- invalid |
||
local vlen = mw.ustring.len(k) |
local vlen = mw.ustring.len(k) |
||
k = mw.ustring.sub(k, 1, (vlen < 25) and vlen or 25) |
k = mw.ustring.sub(k, 1, (vlen < 25) and vlen or 25) |
||
k = mw.ustring.gsub(k, '[^%w%-_ ]', '?') |
k = mw.ustring.gsub(k, '[^%w%-_ ]', '?') |
||
table.insert(tracking, '[[Category:Pages using gallery with unknown parameters|' .. k .. ']]') |
table.insert(tracking, '[[Category:Pages using gallery with unknown parameters|' .. k .. ']]') |
||
Linje 39: | Linje 79: | ||
-- Otherwise, for testing purposes, assume args are being passed directly in. |
-- Otherwise, for testing purposes, assume args are being passed directly in. |
||
local origArgs = (type(frame.getParent) == 'function') and frame:getParent().args or frame |
local origArgs = (type(frame.getParent) == 'function') and frame:getParent().args or frame |
||
-- ParserFunctions considers the empty string to be false, so to preserve the previous |
-- ParserFunctions considers the empty string to be false, so to preserve the previous |
||
-- behavior of {{gallery}}, change any empty arguments to nil, so Lua will consider |
-- behavior of {{gallery}}, change any empty arguments to nil, so Lua will consider |
||
-- them false too. |
-- them false too. |
||
Linje 53: | Linje 93: | ||
if (args.mode or '') == 'packed' and (args.align or '') == '' then |
if (args.mode or '') == 'packed' and (args.align or '') == '' then |
||
args.align = 'center' |
|||
end |
|||
if (args.align or '') == 'centre' then |
|||
args.align = 'center' |
args.align = 'center' |
||
end |
end |
||
Linje 58: | Linje 102: | ||
local tbl = mw.html.create('div') |
local tbl = mw.html.create('div') |
||
tbl:addClass('mod-gallery') |
tbl:addClass('mod-gallery') |
||
if args.state then |
if args.state then |
||
tbl |
tbl |
||
Linje 96: | Linje 140: | ||
end |
end |
||
local virtualgallery = {} |
|||
local gallery = {} |
local gallery = {} |
||
local imageCount = |
local imageCount = 0 |
||
local zwsp = string.char(0xE2, 0x80, 0x8B) -- U+200B Zero Width Space |
|||
for i = 1, imageCount do |
|||
local zwnj = string.char(0xE2, 0x80, 0x8C) -- U+200C Zero Width Non-Joiner |
|||
local img = trim(args[i*2 - 1] or '') |
|||
local caption = trim(args[i*2] or '') |
|||
-- create a coding to identify classes |
|||
local alt = trim(args['alt' .. i] or '') |
|||
-- using unicode non-printing characters |
|||
if img ~= '' then |
|||
-- this is a workaround until we get the class arg in the <gallery> tag |
|||
table.insert(gallery, img .. (alt ~= '' and ('|alt=' .. alt) or '') .. '|' .. caption ) |
|||
-- https://phabricator.wikimedia.org/T344784 |
|||
local skininvert = zwsp .. zwsp .. zwsp; |
|||
local bgtransparent = zwsp .. zwsp .. zwnj; |
|||
for i = 1, #args do |
|||
local currentfield = trim(args[i]) or '' |
|||
if currentfield == '' then |
|||
-- Skip empty fields |
|||
elseif isImage(currentfield) then |
|||
imageCount = imageCount + 1 |
|||
virtualgallery[imageCount] = { currentfield } |
|||
elseif imageCount > 0 and virtualgallery[imageCount][2] == nil then |
|||
-- In case of multiple captions, use the first and ignore the laters |
|||
virtualgallery[imageCount][2] = currentfield |
|||
end |
|||
end |
|||
local altCount = 0; |
|||
-- Run through virtualgallery and builds gallery |
|||
for n = 1, #virtualgallery do |
|||
local img = virtualgallery[n][1] |
|||
local caption = virtualgallery[n][2] or '' |
|||
local alt = trim(args['alt' .. n] or '') |
|||
local class = trim(args['class' .. n] or '') |
|||
-- we count alt text only before any modification |
|||
if alt ~= '' then |
|||
altCount = altCount + 1 |
|||
else |
|||
-- if alt is empty, we use the caption as a alt text. |
|||
-- It is necessary because we add classes codes in the next step, |
|||
-- we do not want to let the alt empty with just the non-printing characters. |
|||
alt = (caption ~= '') and plaintext(caption) or '' |
|||
end |
|||
-- we attach the non-printing code to the end of the alt text |
|||
if mw.ustring.find(class, 'skin%-invert') then -- this matches both skin-invert and skin-invert-image |
|||
alt = alt .. skininvert |
|||
end |
|||
-- as it is possible to combine multiple classes, we use find instead of == |
|||
if mw.ustring.find(class, 'bg%-transparent') then |
|||
alt = alt .. bgtransparent |
|||
end |
|||
-- Some space between the arguments and the pipe to prevent unexpected behaviors. |
|||
-- for example: in some cases the parser interpret the pipe as part of urls |
|||
table.insert(gallery, img .. |
|||
(alt ~= '' and (' |alt=' .. alt) or '') .. |
|||
(caption ~= '' and (' |' .. caption) or '')) |
|||
end |
|||
-- For tracking and verifying during migration to the new algorimth. |
|||
-- It can be removed once everything is verified |
|||
if math.ceil(#args / 2) > imageCount then |
|||
if altCount > 0 then |
|||
table.insert(tracking, '[[Category:Pages using gallery with potential alt text mismatch]]') |
|||
--else |
|||
-- table.insert(tracking, '[[Category:Pages using gallery with extra empty fields]]') |
|||
end |
end |
||
end |
end |
||
Linje 115: | Linje 222: | ||
frame:extensionTag{ name = 'gallery', content = '\n' .. table.concat(gallery,'\n'), args = gargs} |
frame:extensionTag{ name = 'gallery', content = '\n' .. table.concat(gallery,'\n'), args = gargs} |
||
) |
) |
||
if args.footer then |
if args.footer then |
||
tbl:tag('div') |
tbl:tag('div') |
Siste sideversjon per 18. mar. 2025 kl. 21:26
Dokumentasjon for denne modulen kan opprettes på Modul:Gallery/dok
-- This module implements {{gallery}} by wrapping the <gallery> core extension tag. local p = {} local templatestyles = 'Module:Gallery/styles.css' local yesno = require('Module:Yesno') local plaintextModule = require('Module:Plain text') local function plaintext(text) -- stips out external links without labels, -- and then passes to the Plain_text module to clean the rest return plaintextModule.main({ args = { text:gsub("([^%[])%[([^%[%]%s]+)%]", '%1') , encode = "no" } }) end local function trim(s) return mw.ustring.gsub(mw.ustring.gsub(s or '', '%s', ' '), '^%s*(.-)%s*$', '%1') end local tracking, preview local function isImage(file) local file = trim(file):lower() -- Case insensitive check -- Check if it starts with "Fil:", "Bilde:", "File:", "Image:", or "Media:" local prefix = file:match("^(%a+):") if prefix and (prefix == "fil" or prefix == "bilde" or prefix == "file" or prefix == "image" or prefix == "media") then return true end local valid_extensions = { "apng", "djvu", "flac", "gif", "jfi", "jfif", "jif", "jpe", "jpeg", "jpg", "m1a", "m1v", "m2a", "m2v", "mid", "mp1", "mp2", "mp3", "mpa", "mpe", "mpeg", "mpg", "mpv", "oga", "ogg", "ogv", "opus", "pdf", "png", "stl", "svg", "svgz", "tif", "tiff", "wav", "wave", "webm", "webp", "xcf" } -- Extract file extension, of 3 or 4 characters only local ext = file:match("%.(%w%w%w%w?)$") -- Check if the extension is in the valid list if ext then for _, valid_ext in ipairs(valid_extensions) do if ext == valid_ext then table.insert(tracking, '[[Category:Pages using gallery without a media namespace prefix]]') return true end end end return false end local function checkarg(k,v) if k and type(k) == 'string' then if k == 'bredde' or k == 'høyde' or k == 'tittel' or 'fotnote' or k == 'align' or k == 'state' or k == 'style' or k == 'title' or k == 'width' or k == 'height' or k == 'whitebg' or k == 'mode' or k == 'footer' or k == 'perrow' or k == 'noborder' or k:match('^alt%d+$') or k:match('^class%d+$') or k:match('^%d+$') then -- valid elseif k == 'captionstyle' then if not v:match('^text%-align%s*:%s*center[;%s]*$') then table.insert(tracking, '[[Category:Pages using gallery with the captionstyle parameter]]') end else -- invalid local vlen = mw.ustring.len(k) k = mw.ustring.sub(k, 1, (vlen < 25) and vlen or 25) k = mw.ustring.gsub(k, '[^%w%-_ ]', '?') table.insert(tracking, '[[Category:Pages using gallery with unknown parameters|' .. k .. ']]') table.insert(preview, '"' .. k .. '"') end end end function p.gallery(frame) -- If called via #invoke, use the args passed into the invoking template. -- Otherwise, for testing purposes, assume args are being passed directly in. local origArgs = (type(frame.getParent) == 'function') and frame:getParent().args or frame -- ParserFunctions considers the empty string to be false, so to preserve the previous -- behavior of {{gallery}}, change any empty arguments to nil, so Lua will consider -- them false too. local args = {} tracking, preview = {}, {} for k, v in pairs(origArgs) do if v ~= '' then args[k] = v checkarg(k,v) end end if (args.mode or '') == 'packed' and (args.align or '') == '' then args.align = 'center' end if (args.align or '') == 'centre' then args.align = 'center' end local tbl = mw.html.create('div') tbl:addClass('mod-gallery') if args.state then tbl :addClass('mod-gallery-collapsible') :addClass('collapsible') :addClass(args.state) end if args.style then tbl:cssText(args.style) else tbl:addClass('mod-gallery-default') end if args.align then tbl:addClass('mod-gallery-' .. args.align:lower()) end if args.title then tbl:tag('div') :addClass('title') :tag('div') :wikitext(args.title) end local gargs = {} gargs['class'] = 'nochecker' .. (args.noborder and '' or ' bordered-images') gargs['widths'] = tonumber(args.width) or 180 gargs['heights'] = tonumber(args.height) or 180 gargs['bredde'] = tonumber(args.width) or 180 gargs['høyde'] = tonumber(args.height) or 180 gargs['style'] = args.captionstyle gargs['perrow'] = args.perrow gargs['mode'] = args.mode if yesno(args.whitebg or 'yes') then gargs['class'] = gargs['class'] .. ' whitebg' end local virtualgallery = {} local gallery = {} local imageCount = 0 local zwsp = string.char(0xE2, 0x80, 0x8B) -- U+200B Zero Width Space local zwnj = string.char(0xE2, 0x80, 0x8C) -- U+200C Zero Width Non-Joiner -- create a coding to identify classes -- using unicode non-printing characters -- this is a workaround until we get the class arg in the <gallery> tag -- https://phabricator.wikimedia.org/T344784 local skininvert = zwsp .. zwsp .. zwsp; local bgtransparent = zwsp .. zwsp .. zwnj; for i = 1, #args do local currentfield = trim(args[i]) or '' if currentfield == '' then -- Skip empty fields elseif isImage(currentfield) then imageCount = imageCount + 1 virtualgallery[imageCount] = { currentfield } elseif imageCount > 0 and virtualgallery[imageCount][2] == nil then -- In case of multiple captions, use the first and ignore the laters virtualgallery[imageCount][2] = currentfield end end local altCount = 0; -- Run through virtualgallery and builds gallery for n = 1, #virtualgallery do local img = virtualgallery[n][1] local caption = virtualgallery[n][2] or '' local alt = trim(args['alt' .. n] or '') local class = trim(args['class' .. n] or '') -- we count alt text only before any modification if alt ~= '' then altCount = altCount + 1 else -- if alt is empty, we use the caption as a alt text. -- It is necessary because we add classes codes in the next step, -- we do not want to let the alt empty with just the non-printing characters. alt = (caption ~= '') and plaintext(caption) or '' end -- we attach the non-printing code to the end of the alt text if mw.ustring.find(class, 'skin%-invert') then -- this matches both skin-invert and skin-invert-image alt = alt .. skininvert end -- as it is possible to combine multiple classes, we use find instead of == if mw.ustring.find(class, 'bg%-transparent') then alt = alt .. bgtransparent end -- Some space between the arguments and the pipe to prevent unexpected behaviors. -- for example: in some cases the parser interpret the pipe as part of urls table.insert(gallery, img .. (alt ~= '' and (' |alt=' .. alt) or '') .. (caption ~= '' and (' |' .. caption) or '')) end -- For tracking and verifying during migration to the new algorimth. -- It can be removed once everything is verified if math.ceil(#args / 2) > imageCount then if altCount > 0 then table.insert(tracking, '[[Category:Pages using gallery with potential alt text mismatch]]') --else -- table.insert(tracking, '[[Category:Pages using gallery with extra empty fields]]') end end tbl:tag('div') :addClass('main') :tag('div') :wikitext( frame:extensionTag{ name = 'gallery', content = '\n' .. table.concat(gallery,'\n'), args = gargs} ) if args.footer then tbl:tag('div') :addClass('footer') :tag('div') :wikitext(args.footer) elseif args.fotnoter then tbl:tag('div') :addClass('footer') :tag('div') :wikitext(args.fotnoter) end local trackstr = (#tracking > 0) and table.concat(tracking, '') or '' if #preview > 0 then trackstr = require('Module:If preview')._warning({ 'Unknown parameters ' .. table.concat(preview, '; ') .. '.' }) .. trackstr end return frame:extensionTag{ name = 'templatestyles', args = { src = templatestyles} } .. tostring(tbl) .. trackstr end return p