MediaWiki/Luaスクリプティング
はじめに
[編集]MediaWikiのLuaモジュールは、Scribuntoエクステンションを通じて実行される再利用可能なコードです。テンプレートよりも高速で柔軟な処理が可能です。
基本構造
[編集]基本的なLuaモジュールは以下の構造を持ちます:
-- Module:Example return { hello = function( frame ) return "Hello, Wiki!" end }
このコードは、MediaWikiで使用する最もシンプルなLuaモジュールの例です。
モジュール名のコメント
[編集]- Module
- Example
-- Module:Example
これは、このモジュールの名前が「Example」であることを示すコメントです。MediaWikiでは Module:
名前空間にこのコードを設置します。
モジュールの定義と返却
[編集]return { -- モジュールの内容 }
- モジュール全体を1つのテーブルとして定義し、直接returnしています
- これは
local p = {} ... return p
という一般的なパターンの短縮形です
関数の定義
[編集]hello = function( frame ) return "Hello, Wiki!" end
hello
という名前の関数を定義していますframe
パラメータは、MediaWikiからの情報を含むオブジェクトです- この関数は単純に文字列
"Hello, Wiki!"
を返します
使用方法
[編集]このモジュールは以下のように呼び出せます:
{{#invoke:Example|hello}}
これにより、ページ上にHello, Wiki!
と表示されます。
特徴と利点
[編集]- シンプルな構造
- 1つの関数のみを含む最小限のモジュール
- 理解しやすく、拡張も容易
- 効率的な実装
- テーブルを直接returnすることで、コードを簡潔に保っています
- メモリ使用が最適化されています
- 標準的なMediaWikiの慣習に従っている
frame
パラメータの使用- モジュール名のコメント付与
拡張例
[編集]このモジュールは以下のように拡張できます:
- Module
- Example
-- Module:Example return { hello = function( frame ) return "Hello, Wiki!" end, greet = function( frame ) local name = frame.args[1] or "Anonymous" return "Hello, " .. name .. "!" end }
この拡張版は以下のように使用できます:
{{#invoke:Example|hello}} {{#invoke:Example|greet|John}}
データ型と基本機能
[編集]文字列操作
[編集]return { concat = function(frame) local args = frame.args local text1 = args[1] or "" local text2 = args[2] or "" return text1 .. " " .. text2 end }
テーブル操作
[編集]return { listItems = function(frame) local items = {"リンゴ", "バナナ", "オレンジ"} local output = "" for i, item in ipairs(items) do output = output .. "* " .. item .. "\n" end return output end }
MediaWiki固有の機能
[編集]ページタイトルの取得
[編集]return { getTitle = function(frame) return mw.title.getCurrentTitle().text end }
WikiテキストのパーサーAPIの使用
[編集]return { formatText = function(frame) local text = frame.args[1] or "" -- WikiテキストをHTMLに変換 return frame:preprocess(text) end }
カテゴリの操作
[編集]return { addCategory = function(frame) local category = frame.args[1] or "未分類" return "[[Category:" .. category .. "]]" end }
MediaWikiのLuaモジュールの引数 frame
について
[編集]MediaWikiでLuaモジュールを使用する際に、frame
は重要な引数の一つです。frame
引数は、モジュール内で呼び出し元のテンプレートやモジュールのコンテキストにアクセスするために使用されます。この引数を通じて、モジュールは呼び出された際のページやテンプレートの状態を参照できます。
frame
引数とは?
[編集]frame
は、Luaモジュール内で呼び出し元のテンプレートが持つ情報を引き渡す特別なオブジェクトです。この引数を使うことで、モジュールは呼び出し元の引数やパラメータを動的に取得し、処理を行うことができます。これにより、テンプレートの内容に基づいた柔軟な処理が可能になります。
frame
引数の使用方法
[編集]frame
引数を利用することで、モジュール内で以下のような情報にアクセスすることができます:
- 呼び出し元のテンプレート引数
- テンプレート内の他のパラメータ
- モジュールを含むページの情報
frame
引数は通常、#invoke
を使ってモジュールを呼び出す際に自動的に渡されます。具体的には、以下のように利用されます:
return { main = function(frame) -- 引数 'frame' からテンプレートの引数を取得する local value = frame.args["key"] return "Value of key: " .. value end }
上記の例では、frame.args["key"]
を使用して、呼び出し元のテンプレートで指定された引数 key
の値を取得し、その値を返す処理が行われています。
frame
引数の主なメソッド
[編集]frame
引数には、いくつかの重要なメソッドが提供されています。代表的なものをいくつか紹介します。
frame.args
: 呼び出し元のテンプレートで指定された引数のテーブル。これを使って、テンプレート内の引数を動的に取得できます。frame:getParent()
: 親テンプレートを取得します。親テンプレートがある場合、このメソッドを使って親テンプレートにアクセスすることができます。frame:preprocess()
: テンプレートのプレプロセスを実行し、結果を文字列として返します。これを使うことで、テンプレート内のプレプロセスされた内容を取得することができます。
frame
引数を使用した実践的な例
[編集]例えば、次のようなモジュールがあるとします。このモジュールでは、呼び出し元のテンプレートに渡された引数に基づいて異なるメッセージを表示します。
return { displayMessage = function(frame) local message = frame.args["message"] or "デフォルトメッセージ" return "メッセージ: " .. message end }
このモジュールは、呼び出し元のテンプレートから message
引数を受け取り、その内容を表示します。引数が指定されていない場合、デフォルトメッセージが表示されます。
frame
引数を活用する利点
[編集]- 動的なテンプレート引数の処理:
frame
引数を使うことで、呼び出し元テンプレートの引数を動的に処理でき、モジュール内で柔軟な処理が可能になります。 - コードの再利用性: 1つのモジュールで複数のテンプレート引数に対応できるため、同じモジュールを様々なテンプレートで再利用できます。
- 複雑なテンプレート構造の管理:
frame
引数を使うことで、親子関係があるテンプレートや複数の引数が渡される複雑なテンプレート構造でも、効率的にデータを扱うことができます。
注意点
[編集]frame.args
にアクセスする際は、必ず引数が存在するか確認しましょう。引数が存在しない場合にエラーが発生することを避けるためです。frame:getParent()
を使用する場合、親テンプレートが存在しない場合に備えて、適切にエラーハンドリングを行うことが推奨されます。
結論
[編集]frame
引数は、MediaWikiのLuaモジュールで呼び出し元のテンプレートに関する情報を動的に扱うために不可欠なツールです。これをうまく活用することで、モジュールは非常に柔軟で強力なものとなり、複雑なテンプレートの処理が可能になります。
エラー処理
[編集]return { safeOperation = function(frame) local success, result = pcall(function() -- 危険な操作 return someRiskyOperation() end) if not success then return "エラーが発生しました: " .. result end return result end }
モジュールのテスト
[編集]テスト用関数の作成
[編集]return { main = function(frame) local args = frame.args return p._main(args[1], args[2]) end, _main = function(param1, param2) return param1 .. param2 end, test = function() local tests = { { input = {"Hello", "World"}, expected = "HelloWorld" } } for i, test in ipairs(tests) do local result = p._main(table.unpack(test.input)) if result ~= test.expected then return "Test " .. i .. " failed" end end return "All tests passed" end }
パフォーマンスの最適化
[編集]メモ化(キャッシュ)の実装
[編集]local cache = {} return { expensiveOperation = function(frame) local input = frame.args[1] if cache[input] then return cache[input] end -- 重い処理 local result = someExpensiveCalculation(input) cache[input] = result return result end }
ベストプラクティス
[編集]- モジュール名の規約
- 明確で説明的な名前を使用
- 名前空間の衝突を避ける
- 引数の検証
return { main = function(frame) local args = frame.args if not args[1] then error("必須パラメータが指定されていません") end -- 処理続行 end }
- ドキュメンテーション
--[[ Module:Example Description: これは例示用のモジュールです Parameters: 1: 最初のパラメータの説明 2: 2番目のパラメータの説明 Example usage: {{#invoke:Example|main|param1|param2}} ]]
- コードの分割
- 関連する機能ごとにサブモジュールを作成
- 共通機能を別モジュールとして切り出し
デバッグ技法
[編集]ログ出力
[編集]return { debug = function(frame) local args = frame.args mw.log("デバッグ情報: " .. mw.dumpObject(args)) return "ログを確認してください" end }
変数の検査
[編集]inspect = function(frame) local var = frame.args[1] return mw.dumpObject(var) end
セキュリティ考慮事項
[編集]- 入力の検証
secureOperation = function p.(frame) local input = frame.args[1] if not input:match("^[A-Za-z0-9]+$") then error("不正な入力です") end -- 安全な処理を続行 end
- リソース使用の制限
- 無限ループを避ける
- 大きなテーブルの生成を制限
このガイドに従うことで、効率的で保守性の高いLuaモジュールを作成することができます。必要に応じて機能を追加・修正し、Wikiの要件に合わせてカスタマイズしてください。