コンテンツにスキップ

MediaWiki/Luaスクリプティング

出典: フリー教科書『ウィキブックス(Wikibooks)』

はじめに

[編集]

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. シンプルな構造
    • 1つの関数のみを含む最小限のモジュール
    • 理解しやすく、拡張も容易
  2. 効率的な実装
    • テーブルを直接returnすることで、コードを簡潔に保っています
    • メモリ使用が最適化されています
  3. 標準的な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
}

ベストプラクティス

[編集]
  1. モジュール名の規約
    • 明確で説明的な名前を使用
    • 名前空間の衝突を避ける
  2. 引数の検証
return {
    main = function(frame)
        local args = frame.args
        if not args[1] then
            error("必須パラメータが指定されていません")
        end
        -- 処理続行
    end
}
  1. ドキュメンテーション
    --[[
    Module:Example
    Description: これは例示用のモジュールです
    Parameters:
        1: 最初のパラメータの説明
        2: 2番目のパラメータの説明
    Example usage:
        {{#invoke:Example|main|param1|param2}}
    ]]
    
  2. コードの分割
    • 関連する機能ごとにサブモジュールを作成
    • 共通機能を別モジュールとして切り出し

デバッグ技法

[編集]

ログ出力

[編集]
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

セキュリティ考慮事項

[編集]
  1. 入力の検証
    secureOperation = function p.(frame)
        local input = frame.args[1]
        if not input:match("^[A-Za-z0-9]+$") then
            error("不正な入力です")
        end
        -- 安全な処理を続行
    end
    
  2. リソース使用の制限
    • 無限ループを避ける
    • 大きなテーブルの生成を制限

このガイドに従うことで、効率的で保守性の高いLuaモジュールを作成することができます。必要に応じて機能を追加・修正し、Wikiの要件に合わせてカスタマイズしてください。