このモジュールについての説明文ページを モジュール:画像サイズ/doc に作成できます
--[==[
モジュール:画像サイズ
なにをするもの?
記事に書かれた [[ファイル:○○.jpg]] のように「大きさの指定がない画像」に、
表示に必要なぶんだけの大きさ(既定360px)を自動でつけます。
なぜ必要?
大きさを書かないと、MediaWikiは元の画像をそのまま送ります。
宇宙wikiのインフォボックスは、画像をPCで359px・スマホで334pxの枠に
収めて表示しているのに、実際には900pxや600pxの元画像が
そのまま送られていました(実測: 10,231枚・819MBのうち、
800pxより大きい画像が4,500枚・562MB)。
大きさを書けばMediaWikiが縮小版を作り、しかも
画面のこまかさ(1倍/1.5倍/2倍)に合わせて自動で選んでくれます。
実測では1枚117KB → 22〜67KBになりました。
記事を1本ずつ直すのは現実的ではないので、
テンプレート側で一度だけ通せば全記事に効くようにしています。
つかいかた(テンプレートの中で):
{{#invoke:画像サイズ|fit|{{{画像|}}}}}
大きさを変えたいとき:
{{#invoke:画像サイズ|fit|{{{画像|}}}|px=250}}
さわらないもの(そのまま素通しします):
・すでに 250px / x200px / upright などの大きさ指定があるもの
・thumb や サムネイル が書かれているもの(MediaWikiが既に縮めているため)
・ファイル以外のリンク
・テンプレート({{...}})やHTMLタグが混ざっているもの
・空っぽのもの
注意: この説明文の中に [[ ]] が出てくるため、
コメントの囲みは --[[ ではなく --[==[ を使っています。
--]==]
local p = {}
-- 既定の幅(px)。インフォボックスの実測表示幅(PC 359px / スマホ 334px)に合わせる。
local DEFAULT_PX = 360
-- 「ファイル」を表す名前空間の書き方(小文字にして比べる)
local FILE_NS = {
['ファイル'] = true,
['file'] = true,
['画像'] = true,
['image'] = true,
}
-- 画像として扱う拡張子(ファイル名だけが書かれていた場合の判定用)
local IMAGE_EXT = {
jpg = true, jpeg = true, png = true, gif = true, webp = true, svg = true,
}
-- thumb / frame などが書かれている画像は、MediaWiki が
-- もともと既定の大きさ(220pxなど)に縮めてくれるので、
-- こちらから px を足すとかえって大きくなってしまう。さわらない。
local ALREADY_SIZED = {
thumb = true,
thumbnail = true,
frameless = true,
frame = true,
['サムネイル'] = true,
['枠なし'] = true,
['枠'] = true,
}
-- その値が「大きさの指定」かどうか
local function isSize( s )
s = mw.text.trim( s )
local lower = mw.ustring.lower( s )
if lower:match( '^%d+%s*px$' ) then return true end
if lower:match( '^x%d+%s*px$' ) then return true end
if lower:match( '^%d+%s*x%s*%d+%s*px$' ) then return true end
if lower:match( '^upright' ) then return true end
return false
end
-- [[...]] の中身を受け取り、必要なら大きさを足して返す。
-- 足す必要がなければ nil を返す(= 呼び出し元はもとのまま残す)。
local function fixInner( inner, px )
local parts = mw.text.split( inner, '|', true )
local target = mw.text.trim( parts[ 1 ] )
-- 先頭の「ファイル:」を確認する。無ければ画像リンクではない。
local ns = target:match( '^([^:]+):' )
if not ns then return nil end
if not FILE_NS[ mw.ustring.lower( mw.text.trim( ns ) ) ] then return nil end
-- すでに大きさが書かれている、または thumb などで
-- MediaWiki が自動で縮めてくれるものは、何もしない
for i = 2, #parts do
local v = mw.ustring.lower( mw.text.trim( parts[ i ] ) )
if isSize( v ) or ALREADY_SIZED[ v ] then return nil end
end
table.insert( parts, 2, px .. 'px' )
return '[[' .. table.concat( parts, '|' ) .. ']]'
end
-- 本体
function p._fit( text, px )
if text == nil then return '' end
text = mw.text.trim( text )
if text == '' then return '' end
px = tonumber( px ) or DEFAULT_PX
if px < 40 or px > 2000 then px = DEFAULT_PX end
-- テンプレートやHTMLが混ざっているものは、こわす危険があるのでさわらない
if text:find( '{{', 1, true ) or text:find( '<', 1, true ) then
return text
end
-- (1) [[ファイル:...]] の形
if text:find( '[[', 1, true ) then
local changed = false
local out = text:gsub( '%[%[([^%[%]]-)%]%]', function( inner )
local fixed = fixInner( inner, px )
if fixed then
changed = true
return fixed
end
return nil -- そのまま
end )
return changed and out or text
end
-- (2) ファイル名だけが書かれている形 (例: れじぇくん.jpg)
if not text:find( '|', 1, true ) and not text:find( ']', 1, true ) then
local ext = text:match( '%.([%a%d]+)$' )
if ext and IMAGE_EXT[ mw.ustring.lower( ext ) ] then
return '[[ファイル:' .. text .. '|' .. px .. 'px]]'
end
end
return text
end
function p.fit( frame )
local args = frame.args
return p._fit( args[ 1 ], args.px or args[ 2 ] )
end
return p