モジュール:サンドボックス/likibp/ruby

提供:Wikisource
モジュールの解説[作成]
require( 'strict' )
local getArgs = require('Module:Arguments').getArgs
local p = {}

---メイン関数
---@param frame table
function p.main(frame)
    local args = getArgs(frame)
    return p._main(args)
end

---メイン関数(プライベート)
---@param args table
---@return string
function p._main(args)
    local str -- 返り値用変数
    local ruby_base = args.ruby_base or ''
    local ruby_class = 'wst-ruby ' .. (args.ruby_class or '')
    local start_rp = args.start_rp or '('
    local end_rp = args.end_rp or ')'

    local ruby = {
        first = {
            text = args.first_ruby or '',
            position = args.first_ruby_position or 'over',
            ruby_element_style = args.first_ruby_element_style or '',
            rt_element_style = args.first_rt_element_style or ''
        },
        second = {
            text = args.second_ruby or '',
            position = args.second_ruby_position or 'under',
            ruby_element_style = args.second_ruby_element_style or '',
            rt_element_style = args.second_rt_element_style or ''
        }
    }
    -- ruby-positionのチェック
    local order = { 'first', 'second' }
    for _, value in pairs(order) do
        if not (string.lower(ruby[value].position) == "over" or
            string.lower(ruby[value].position) == "under") then
            return p._error(mw.ustring.format(
                '引数:\"%s_ruby_position\"\"over\"または\"under\"のみ指定できます',
                value))
        end
    end
    str = p._generateRubyBasedOnTable(ruby_base, start_rp, end_rp, ruby,
        ruby_class)
    return str
end

---rubyテーブルを元にruby要素を生成
---@param ruby_base string ルビベース
---@param start_rp_content string rt要素の前のrp要素の内容
---@param end_rp_content string rt要素の後のrp要素の内容
---@param ruby_table table ルビのデータが入ったテーブル
---@param ruby_class string ruby要素に設定するクラス名
---@return string
function p._generateRubyBasedOnTable(ruby_base, start_rp_content, end_rp_content, ruby_table,
                                     ruby_class)
    local ruby_str
    local first_ruby_str
    -- rtable.second.textが空白の場合、ruby要素をそのまま生成
    if ruby_table.second.text == "" then
        ruby_str = p._createRubyElement(ruby_base, start_rp_content, ruby_table.first.text,
            ruby_table.first.rt_element_style, end_rp_content, ruby_table.first.ruby_element_style,
            ruby_table.first.position, ruby_class)
        -- rtable.second.textに内容がある場合ruby要素を入れ子にして生成
    else
        first_ruby_str = p._createRubyElement(ruby_base, start_rp_content, ruby_table.first.text,
            ruby_table.first.rt_element_style, end_rp_content, ruby_table.first.ruby_element_style,
            ruby_table.first.position, '')

        ruby_str = p._createRubyElement(first_ruby_str, start_rp_content, ruby_table.second.text,
            ruby_table.second.rt_element_style, end_rp_content, ruby_table.second.ruby_element_style,
            ruby_table.second.position, ruby_class)
    end
    return ruby_str
end

---ルビ要素を組み立てる
---@param ruby_base string ルビベース
---@param start_rp_content string rt要素の前のrp要素の内容
---@param rt_content string rt要素の内容
---@param rt_element_style string rt要素に設定するスタイル
---@param end_rp_content string rt要素の後のrp要素の内容
---@param ruby_element_style string ruby要素に設定するスタイル
---@param ruby_position string ルビの位置(上:top,下:under)
---@param ruby_element_class string ruby要素に設定するクラス名
---@return string
function p._createRubyElement(ruby_base, start_rp_content, rt_content, rt_element_style, end_rp_content,
                              ruby_element_style, ruby_position, ruby_element_class)
    local rt_element = mw.html.create('rt')
    if rt_element_style ~= "" then
        rt_element:cssText(rt_element_style)
    end
    rt_element:wikitext(rt_content)

    local ruby_element = mw.html.create('ruby')
    if ruby_element_class ~= '' then
        ruby_element:addClass(ruby_element_class)
    end
    if ruby_element_style ~= '' then
        ruby_element:cssText(ruby_element_style)
    end
    ruby_element:css('ruby-position', ruby_position)
        :wikitext(ruby_base):wikitext('<rp>' .. start_rp_content .. '</rp>'):node(rt_element):wikitext(
        '<rp>' .. end_rp_content .. '</rp>')
    return tostring(ruby_element)
end

---エラーメッセージを処理するためのヘルパー関数
---@param error_str string
---@return string
function p._error(error_str)
    local frame = mw.getCurrentFrame()
    local error_category = frame.args.error_category or
        'Module:Rubyで報告されたエラー'
    local ignore_errors = frame.args.ignore_errors or false
    local no_category = frame.args.no_category or false

    if p._getBoolean(ignore_errors) then return '' end

    local error_wikitext = '<strong class="error">Ruby Module Error: ' ..
        error_str .. '</strong>'
    if error_category ~= '' and not p._getBoolean(no_category) then
        error_wikitext = '[[Category:' .. error_category .. ']]' ..
            error_wikitext
    end

    return error_wikitext
end

---論理値文字列を解釈するヘルパー関数
---@param boolean_str string
---@return boolean
function p._getBoolean(boolean_str)
    local boolean_value

    if type(boolean_str) == 'string' then
        boolean_str = boolean_str:lower()
        if boolean_str == 'false' or boolean_str == 'no' or boolean_str == '0' or
            boolean_str == '' then
            boolean_value = false
        else
            boolean_value = true
        end
    elseif type(boolean_str) == 'boolean' then
        boolean_value = boolean_str
    else
        error('No boolean value found')
    end
    return boolean_value
end

return p