コンテンツにスキップ

モジュール:Namespace other/sandbox

提供: Wikisource
モジュールの解説[表示] [編集] [履歴] [キャッシュを破棄]

以下の実装

require('strict')

local p = {}

local getArgs = require('Module:Arguments').getArgs
local yesno   = require('Module:Yesno')

-- 文字列を正規化(小文字+空白→アンダースコア)
local function norm(s)
	if not s or s == '' then
		return ''
	end
	s = mw.text.trim(s)
	s = mw.ustring.lower(s)
	s = s:gsub(' ', '_')
	return s
end

-- target / demospace から名前空間 ID を引く
--   ・canonical 名
--   ・ローカル名
--   ・数値 ID
-- のいずれでも指定可
local function resolveTarget(target)
	if not target or target == '' then
		return 0, 'main'  -- 省略時は main
	end

	target = norm(target)

	if target == 'main' then
		return 0, 'main'
	end
	if target == 'talk' then
		-- 特別扱い(全トーク名前空間)
		return 'talk', 'talk'
	end

	-- 名前空間テーブルから検索
	for id, data in pairs(mw.site.namespaces) do
		local canon = data.canonicalName and norm(data.canonicalName)
		local name  = data.name           and norm(data.name)
		if canon == target or name == target then
			return id, target
		end
	end

	-- 数値だった場合はそのまま ID とみなす
	local asNum = tonumber(target)
	if asNum then
		return asNum, target
	end

	-- 解決できない場合
	return nil, target
end

-- demospace / include-talk を考慮して現在(またはデモ)の名前空間情報を取得
-- 戻り値: nsId, nsName(正規化 canonical), title, nsTable
local function getNamespaceInfo(demospace, includeTalk)
	-- demospace が指定されているときは実際のページではなくその名前空間で判定
	if demospace and demospace ~= '' then
		local id, name = resolveTarget(demospace)
		if id == 'talk' then
			-- demospace=talk は「任意のトーク名前空間」を示す特殊値として扱う
			return 'talk', 'talk', mw.title.getCurrentTitle(), {}
		elseif id ~= nil then
			local nsTable = mw.site.namespaces[id] or {}
			local canonical = nsTable.canonicalName or nsTable.name or ''
			return id, norm(canonical), mw.title.getCurrentTitle(), nsTable
		else
			-- よく分からない demospace の場合はその文字列だけ返す
			return nil, name, mw.title.getCurrentTitle(), {}
		end
	end

	-- 通常は現在のページのタイトルから
	local title   = mw.title.getCurrentTitle()
	local nsId    = title.namespace
	local nsTable = mw.site.namespaces[nsId] or {}

	-- include-talk 指定時はトーク空間を本文側に寄せる
	if includeTalk and nsTable.subject then
		nsId    = nsTable.subject.id
		nsTable = mw.site.namespaces[nsId] or nsTable
	end

	local canonical = nsTable.canonicalName or nsTable.name or ''
	return nsId, norm(canonical), title, nsTable
end

function p._namespace_other(args)
	local includeTalk = yesno(args['include-talk'])
	local nsId, nsName, title = getNamespaceInfo(args.demospace, includeTalk)
	local targetId, targetName = resolveTarget(args.target)

	-- 特別ターゲット: talk(全トーク名前空間)
	if targetName == 'talk' then
		if title.isTalkPage then
			return args[1]
		else
			return args[2]
		end
	end

	-- 特別ターゲット: main(標準名前空間)
	if targetName == 'main' then
		if nsId == 0 then
			return args[1]
		else
			return args[2]
		end
	end

	-- ターゲット側の名前空間 ID が解決できなかった場合は常に other
	if not targetId then
		return args[2]
	end

	if nsId == targetId then
		return args[1]
	else
		return args[2]
	end
end

function p.namespace_other(frame)
	return p._namespace_other(getArgs(frame))
end

-- Page / Index / その他を出し分け
local function _page_index_other(args)
	local page_entry  = args['page index'] or args['page']  or args[1]
	local index_entry = args['page index'] or args['index'] or args[2]
	local other_entry = args['other']      or args[3]

	-- Page / Index 名前空間を canonical 名で判定
	-- (include-talk=true なので Page talk / Index talk も本文側に寄せる)
	local nsId, nsName = getNamespaceInfo(args.demospace, true)

	if nsName == 'page' then
		return page_entry
	elseif nsName == 'index' then
		return index_entry
	else
		return other_entry
	end
end

function p.page_index_other(frame)
	return _page_index_other(getArgs(frame))
end

return p