跳转到内容

模組:Reaction

维基百科,自由的百科全书

这是本页的一个历史版本,由SunAfterRain留言 | 贡献2025年6月29日 (日) 16:44编辑。这可能和当前版本存在着巨大的差异。

-- implement {{Reaction}}
local p = {}
local mIfexist

local function mayMakeFile(iconInput)
	local success, title = pcall(mw.title.new, iconInput)
	if success and title and title.namespace == 6 then
		if not mIfexist then
			mIfexist = require('Module:Ifexist')
		end
		-- if title.file.exists then
		if mIfexist._pfFileExists(title) then
			return string.format('[[File:%s|x20px|link=]]', title.text)
		end
	end
	return false
end

local function stripInputCount(inputCount, realCount)
	if inputCount ~= nil then
		inputCount = mw.text.trim(inputCount)
		if inputCount == "" then
			return "0"
		else
			-- 示例使用了 99+ 所以這裡也允許尾隨 + 號
			-- 順便把前導 0 也丟掉
			local num = mw.ustring.match(inputCount, "^0*(%d+%+?)$")
			if num then
				return num
			end
		end
	end
	return tostring(realCount)
end

local function unstripCustom(content)
	-- from [[Module:Check_for_unknown_parameters]] # local function clean
	local pos = 1
	local parts = {}
	for before, fullTag, tag, remainder in mw.ustring.gmatch(text, '([^\127]*)(\127[^\127]*%-(%l+)%-[^\127]*\127)()') do
		pos = remainder
		table.insert(parts, before)
		if tag == 'nowiki' then
			-- unstrip nowiki
			table.insert(parts, mw.text.unstripNoWiki(fullTag))
		elseif tag == 'templatestyles' or tag == 'math' or tag == 'chem' then
			-- 保留 templatestyles & 已確認和模板使用不會炸裂的標籤
			table.insert(parts, fullTag)
		end
		-- 其他通通拋棄
	end
	table.insert(parts, mw.ustring.sub(text, pos))
	return table.concat(parts)
end

local iconInvalidString = "不-{zh-hans:支持;zh-hant:支援;}-輸入圖標"

function p.main(frame)
	local parent = frame:getParent()
	if not parent then
		-- 不是模板被引用
		return ''
	end

	local args = parent.args
	local iconInput = args[1] or "👍"
	local iconInvalid = false
	iconInput = mw.text.trim(iconInput)
	if
		-- 已知幾乎無例外會大爆炸的案例(並且也明顯超出這個模板本來的用法)
		mw.ustring.find(iconInput, "<div[ >]") or
		mw.ustring.find(iconInput, "<table[ >]") or
		mw.ustring.find(iconInput, "<p[ >]") or
		mw.ustring.find(iconInput, "<li[ >]") or
		mw.ustring.find(iconInput, "\n") or
		mw.ustring.find(iconInput, "template-reaction")
	then
		iconInput = iconInvalidString
		iconInvalid = true
	end

	-- 這裡可以保留部分 mark 所以用自定義寫法
	local iconDisplay = mayMakeFile(iconInput) or mw.text.trim(unstripCustom(iconInput))
	if iconDisplay == "" then
		-- 只有被拋棄掉的 extension tag
		iconInput = iconInvalidString
		iconDisplay = iconInvalidString
		iconInvalid = true
	end
	local iconData = mw.text.unstrip(iconInput)

	local reactions = {}
	while true do
		local currentItem = args[1 + #reactions + 1] -- 反應者從第二個參數開始
		if currentItem == nil then
			break
		end
		currentItem = mw.text.trim(currentItem)
		if currentItem == '' then
			break
		end
		table.insert(reactions, currentItem)
	end
	local realReactionCount = #reactions -- 真實計數
	local reactionTitle = (realReactionCount >= 1 and mw.text.listToText(reactions, '、', '和') or '没有人') .. '回应了这条留言'
	local reactionCount = stripInputCount(args.num, realReactionCount) -- 顯示的計數

	local out = mw.html.create('span')
		:addClass('reactionable')
		:addClass('template-reaction')
		:attr('title', reactionTitle)
		:attr('data-reaction-commentors', table.concat(reactions, '/'))
		:attr('data-reaction-icon', iconData)
		:attr('data-reaction-icon-invalid', iconInvalid)
		:attr('data-reaction-count', reactionCount)
		:attr('data-reaction-real-count', realReactionCount)

	local content = out:tag('span')
		:addClass('reaction-content')

	-- icon
	content:tag('span')
		:addClass('reaction-icon-container')
		:tag('span')
			:addClass('reaction-icon')
			:wikitext(iconDisplay)
	
	-- counter
	content:tag('span')
		:addClass('reaction-counter-container')
		:tag('span')
			:addClass('reaction-counter')
			:wikitext(tostring(reactionCount))
	
	return frame:extensionTag({ name = 'templatestyles', args = { src = 'Template:Reaction/styles.css' } }) .. tostring(out)
end

return p