モジュール:File clip
表示
このモジュールはアルファ版です。現在、挙動や仕様などをテストしています。機能の追加や変更の提案も歓迎します。 |
![]() | このモジュールはテンプレートスタイルを使用しています: |
画像やPDFファイルのトリミング表示を行います。このモジュールは{{File clip}}の実装を置き換える目的で作成されました。
現時点では{{File clip/sandbox}}が当モジュールのラッパーテンプレートになっており、Template:File clip/testcasesにて動作テストを行っています。
使い方[編集]
{{#invoke:File clip|呼び出す関数名|ファイル名|width=表示サイズ(横幅)|その他のオプション ... }}呼び出す関数名にthumbを指定するとサムネイル形式で表示し、nothumbを指定するとフレームなしの形式で表示します。 ファイル名と表示サイズの指定は省略できません。 ファイル名を指定する際に名前空間プレフィックス︵ファイル:やFile:など︶を付ける必要はありません。
|width=
には表示する際の横幅をピクセル単位で指定します。指定する値は数値のみとし、単位は付けないでください。
その他のオプションには以下の指定が可能です。
●|t=
, |r=
, |b=
, |l=
- それぞれ切り抜く上部分、右部分、下部分、左部分の大きさを百分率で指定します。指定する値は0以上100未満の数値のみとし、%は付けないでください。省略した場合は0を指定した場合と同じになります。
●|w=
, |h=
- それぞれ元のファイルの横幅・縦幅をピクセル単位で指定します。指定する値は数値のみとし、単位は付けないでください。省略した場合はScribuntoのファイルメタデータを利用して横幅・縦幅を自動的に取得しますが、これを行うと高負荷構文解析関数使用回数のカウンタが増加します。|w=
と|h=
の両方を指定することにより、これを回避することができます。
●|align=
- ファイルの表示位置を指定します。指定可能な値と省略時の挙動については[[ファイル:ファイル名|...]]による画像の表示と同様です。詳細についてはthumb形式の場合はHelp:画像の表示#thumbを、nothumb形式の場合はHelp:画像の表示#配置指定をご覧ください。
●|caption=
︵あるいは|c=
︶ - キャプションを指定します。省略時はファイル名が使われます。
●|alt=
- キャプションとは別にimg要素のalt属性の値を設定する場合は指定します。空文字列を指定することもできます。
●|page=
- ファイル形式がDjVuやPDFの場合に、表示するページの番号を指定します。省略すると1ページ目を表示します。
●|link=
- 画像をクリックした際のリンクを変更することができます︵空文字列も指定可能︶。CC BYなど、ファイルのライセンスが帰属表示を求めている場合は、このオプションを使わないでください。詳しくはHelp:画像の表示#画像リンクをご覧ください。
使用例[編集]
コード{{#invoke:File clip|thumb|Wikipedia Logo 1.0.png|width=200|align=left|t=0|r=25|b=70|l=35|caption=2003年から2010年まで使われていたウィキペディアのロゴの一部分}}表示
require('strict') local function showImage(filename, caption, options) --[=[ 画像を表示するウィキテキスト構文を生成して返す filename: ファイル名(文字列型、必須) caption(): 画像のキャプション(文字列型、省略可) options: その他のオプション(テーブル型、省略可) ]=]-- if type(filename) ~= 'string' or filename == '' then error('ファイル名が正しく指定されていません。', 2) end local t = { filename } if options then for k, v in pairs(options) do table.insert( t, (type(k) == 'string') and mw.ustring.format('%s=%s', k, v) or v ) end end if caption then table.insert(t, caption) end return mw.ustring.format('[[File:%s]]', table.concat(t, '|')) end local function isValign(value) for _, v in ipairs({'baseline', 'sub', 'super', 'top', 'text-top', 'middle', 'bottom', 'text-bottom'}) do if v == value then return true end end return false end -------------------------------------------------------------------------------- -- fileClipクラス -- -- fileClipをテーブルのメタテーブルに設定することで、 -- そのテーブルはfileClipクラスのインスタンスであるかのように振る舞う -------------------------------------------------------------------------------- local fileClip = {} fileClip.__index = fileClip function fileClip:_setError(message) self._error = mw.html.create('strong') :addClass('error') :wikitext('エラー:' .. message) return self end function fileClip._new(args) local obj = {} setmetatable(obj, fileClip) -- 配置指定 obj._align = args.align if not args[1] then return obj:_setError('ファイル名が指定されていません。') end -- 表示サイズ(横幅) obj._width = tonumber(args.width) if not obj._width then obj._width = 200 return obj:_setError('表示サイズが指定されていません。') end -- 切り抜き範囲(百分率) -- 指定省略時は0% local crop_top = tonumber(args[2] or args.t) or 0 local crop_right = tonumber(args[3] or args.r) or 0 local crop_bottom = tonumber(args[4] or args.b) or 0 local crop_left = tonumber(args[5] or args.l) or 0 -- 画像の表示範囲(百分率)を計算 -- 縦方向・横方向のどちらか一方でも0%以下ならエラー local v_rest = 100 - (crop_top + crop_bottom) local h_rest = 100 - (crop_right + crop_left) if v_rest <= 0 then return (h_rest <= 0) and obj:_setError('縦方向・横方向ともに100%以上切り取っています。') or obj:_setError('縦方向に100%以上切り取っています。') end if h_rest <= 0 then return obj:_setError('横方向に100%以上切り取っています。') end -- ファイルページのタイトルオブジェクト local filepage = mw.title.new(args[1], 'ファイル') -- ファイル名(名前空間プレフィックスを含まない) obj._filename = filepage.text -- 元の画像の横幅・縦幅 -- 画像の横幅・縦幅はファイルメタデータを参照すれば取得可能だが、 -- ファイルメタデータを取得する処理は高負荷である。 -- 横幅・縦幅の両方が手動で指定されている場合は、それを使用し、 -- ファイルメタデータの取得を避ける。 local orig_width, orig_height if args.w and args.h then orig_width = tonumber(args.w) orig_height = tonumber(args.h) else local filemetadata = filepage.file -- 高負荷 if not filemetadata.exists then return obj:_setError( mw.ustring.format('[[:File:%s]]は存在しません。', obj._filename) ) end if string.find(filemetadata.mimeType, 'image/', 1, true) ~= 1 and filemetadata.mimeType ~= 'application/pdf' then return obj:_setError( mw.ustring.format( '[[:File:%s]]([[MIMEタイプ]]: %s)は切り抜き表示に対応していません。', obj._filename, filemetadata.mimeType ) ) end local page = tonumber(args.page) if page and page > 1 and filemetadata.pages then filemetadata = filemetadata.pages[page] end orig_width = filemetadata.width orig_height = filemetadata.height end -- 切り抜き画像の表示サイズ(縦幅)を計算 obj._height = math.floor( (obj._width * orig_height * v_rest) / (orig_width * h_rest) ) -- 画像を拡大後、上方向および左方向に何pxずらせばよいか計算 obj._shift_up = math.floor( (obj._width * orig_height * crop_top) / (orig_width * h_rest) ) obj._shift_left = math.floor((obj._width * crop_left) / h_rest) -- 画像のキャプション -- 指定省略時は指定されたファイル名(名前空間プレフィックスを含まない) obj._caption = args[6] or args.c or args.caption or obj._filename -- 拡大後の画像の横幅、その他のオプション obj._image_options = { math.floor((obj._width * 100) / h_rest) .. 'px', alt = args.alt, link = args.link, page = args.page, class = args.class, lang = args.lang } return obj end function fileClip:thumb() local center = mw.html.create('div'):addClass('center') local thumb = mw.html.create('div') if self._align == 'center' or self._align == 'none' then thumb:addClass('thumb fileclip-thumb tnone') elseif self._align == 'left' then thumb:addClass('thumb fileclip-thumb tleft') else thumb:addClass('thumb fileclip-thumb tright') end local thumbinner = mw.html.create('div') :addClass('thumbinner fileclip-thumbinner') :css('width', (self._width + 2) .. 'px') if self._error then thumb:node(thumbinner:node(self._error)) return (self._align == 'center') and center:node(thumb) or thumb end local clipper = mw.html.create('div') :addClass('fileclip-clipper thumbimage') :css({ width = self._width .. 'px', height = self._height .. 'px' }) :cssText('position: relative; overflow: hidden;') local shifting = mw.html.create('div') :addClass('fileclip-shifting') :css({ top = -self._shift_up .. 'px', left = -self._shift_left .. 'px' }) :cssText('position: absolute;') :wikitext(showImage(self._filename, nil, self._image_options)) clipper:node(shifting) local thumbcaption = mw.html.create('div'):addClass('thumbcaption') local magnify = mw.html.create('div') :addClass('magnify fileclip-magnify') :wikitext( showImage( 'Scissors icon black.svg', '拡大', { 'text-top|16px', link = 'File:' .. self._filename } ) ) thumbcaption:node(magnify):wikitext(self._caption) thumb:node(thumbinner:node(clipper):node(thumbcaption)) return (self._align == 'center') and center:node(thumb) or thumb end function fileClip:nothumb() if self._error then return self._error end local center = mw.html.create('div'):addClass('center') local aligndiv local clipper = mw.html.create('span') :addClass('fileclip-clipper') :css({ width = (self._width .. 'px'), height = (self._height .. 'px') }) :cssText('position: relative; overflow: hidden; display: inline-block;') if self._align == 'center' or self._align == 'none' then aligndiv = mw.html.create('div'):addClass('floatnone') elseif self._align == 'right' or self._align == 'left' then aligndiv = mw.html.create('div'):addClass('float' .. self._align) elseif self._align and isValign(self._align) then clipper:css({ ['vertical-align'] = self._align }) else clipper:css('vertical-align', 'middle') end local shifting = mw.html.create('span') :addClass('fileclip-shifting') :css({ top = -self._shift_up .. 'px', left = -self._shift_left .. 'px' }) :cssText('position: absolute;') :wikitext(showImage(self._filename, self._caption, self._image_options)) clipper:node(shifting) if not aligndiv then return clipper end aligndiv:node(clipper) return (self._align == 'center') and center:node(aligndiv) or aligndiv end local getArgs local function _main(mode, frame) if not getArgs then getArgs = require('モジュール:Arguments').getArgs end local args = getArgs(frame, { valueFunc = function (key, value) -- alt引数とlink引数については、省略した場合と -- 空文字列を指定した場合を区別する if value then value = mw.text.trim(value) end if value == '' and key ~= 'alt' and key ~= 'link' then return nil end return value end, wrappers = { 'Template:File clip', 'Template:File clip2' } }) local thumb = fileClip._new(args) thumb._export = thumb[mode] return frame:extensionTag{ name = 'templatestyles', args = { src = 'File clip/styles.css' } } .. tostring(thumb:_export()) .. '[[Category:切り抜き画像]]' end local p = { thumb = function(frame) return _main('thumb', frame) end, nothumb = function(frame) return _main('nothumb', frame) end } return p