跳转到内容

模組:Delete2

被永久保护的模块
维基百科,自由的百科全书
(重定向自Module:Template:Delete2)
local mDelete = require('Module:Delete')
local getArgs = require('Module:Arguments').getArgs
local mYesno

local data_main = require('Module:Delete/data')
local _data_sandbox
-- lazy load
local function get_data_sandbox()
	if not _data_sandbox then
		_data_sandbox = require('Module:Delete/data/sandbox')
	end
	return _data_sandbox
end

local z = {}

local function yesno(value)
	if not mYesno then
		mYesno = require('Module:Yesno')
	end
	return mYesno(value)
end

local function extractShortDesc(item)
    if item['description'] then
        return item['description']:gsub('{', '{'):gsub('}', '}'):gsub('|', '|')
    else
        return ''
    end
end

local function use_sandbox_by_frame(frame)
	return yesno(frame.args.sandbox)
end

local codeLetterMap = {
	{
		letter = "G",
		name = "所有頁面" -- General
	},
	{
		letter = "A",
		name = "條目" -- Articles
	},
	{
		letter = "R",
		name = "重定向页" -- Redirects
	},
	{
		letter = "F",  -- old alias I
		name = "图片及多媒體檔案" -- Files
	},
	{
		letter = "C",
		name = "分類" -- Categories
	},
	--[=[
	{
		letter = "T",
		name = "模板" -- Templates
	},
	]=]
	{
		letter = "U",
		name = "用戶自治空間頁面" -- User pages
	},
	{
		letter = "O",
		name = "其他页面" -- Others
	},
}
local letterWeights = {}
for i, item in ipairs(codeLetterMap) do
	letterWeights[item.letter] = i
end

local function makeReasonsBox(frame, data)
    local wt = [=[
{| class="wikitable" width="100%"
|-
!width="7%"|速刪編號
!width="7%"|可使用的代碼
!width="25%"|簡介
!width="61%"|詳細說明
    ]=]

	local used_codes = {}
    local max_num = {}

	local function splitLetter(codeStr)
		local letter, numStr = codeStr:match("^([A-Za-z]+)(%d+)$")
		if letter then
			return letter:upper(), tonumber(numStr)
		end
		return nil, nil
	end
	
	local function markCode(letter, num)
        used_codes[letter] = used_codes[letter] or {}
		used_codes[letter][num] = true
		max_num[letter] = math.max(max_num[letter] or 0, num)
    end

    local function getSortKey(code, letter, num)
        if not letter then
            return { #codeLetterMap + 1, 0, code }
        end

        return { letterWeights[letter] or #codeLetterMap, num, code }
    end

    local processedData = {}
    for i, item in ipairs(data) do
        local newItem = {
            code = item.code,
            aliases = {},
            criteria = item.criteria,
            description = item.description,
            isRevoked = item.isRevoked,
            _getRevokeMessage = item._getRevokeMessage,
            isAliasRecord = false
        }
		local letter, num = splitLetter(item.code)
		newItem.sortKey = getSortKey(item.code, letter, num)
		if letter then
			markCode(letter, num)
		end

        if item.aliases then
            for j, alias in ipairs(item.aliases) do
                local formattedAlias = alias
                if type(alias) == 'string' then
                    local aliasLetter, aliasNum = splitLetter(alias)
                    if aliasLetter then
						markCode(aliasLetter, aliasNum)
                        formattedAlias = aliasLetter .. tostring(aliasNum)
						if aliasLetter ~= "I" then
	                        table.insert(processedData, {
	                            code = formattedAlias,
	                            isAliasRecord = true,
	                            mainCode = item.code,
	                            isRevoked = item.isRevoked,
	                            criteria = "此為代碼[[#csd-data-" .. item.code .. "|" .. item.code .. "]]的別稱。",
	                            description = "",
								sortKey = getSortKey(alias, aliasLetter, aliasNum)
	                        })
						end
                    end
                end
                table.insert(newItem.aliases, formattedAlias)
            end
        end
        table.insert(processedData, newItem)
    end

	for _, codeLetterItem in ipairs(codeLetterMap) do
		local letter = codeLetterItem.letter
        if max_num[letter] then
            for i = 1, max_num[letter] do
                if not used_codes[letter][i] then
					local missingCode = letter .. tostring(i)
                    table.insert(processedData, {
                        code = missingCode,
                        isMissing = true,
                        criteria = string.format('{{error|代碼%s遺失}}', missingCode),
                        description = '',
						sortKey = getSortKey(missingCode, letter, i)
                    })
                end
            end
        end
    end

    table.sort(processedData, function(a, b)
        local keyA = a.sortKey
        local keyB = b.sortKey

        if keyA[1] ~= keyB[1] then
            return keyA[1] < keyB[1]
        end

        if keyA[2] ~= keyB[2] then
            return keyA[2] < keyB[2]
        end

        return keyA[3] < keyB[3]
    end)

    for i, item in ipairs(processedData) do
        local allnames
        if item.isAliasRecord then
            allnames = '\n* ' .. item.code
        else
            local names = {item.code}
            if item.aliases then
				local sortedAliases = {}
                for _, alias in ipairs(item.aliases) do
                    table.insert(sortedAliases, alias)
                end

                table.sort(sortedAliases, function(a, b)
                    local keyA = getSortKey(a, false)
                    local keyB = getSortKey(b, false)
                    if keyA[1] ~= keyB[1] then return keyA[1] < keyB[1] end
                    if keyA[2] ~= keyB[2] then return keyA[2] < keyB[2] end
                    return keyA[3] < keyB[3]
                end)

                for j, alias in ipairs(sortedAliases) do
                    table.insert(names, alias)
                end
            end
            allnames = '\n* ' .. table.concat(names, '\n* ')
        end

        local code = item.code
        local codeDisplay = string.format('<span id="csd-data-%s">%s</span>', code, code)
        local criteria = item.criteria or ''
        
        if item.isRevoked then
            codeDisplay = '<span style="color: var(--color-disabled, #a2a9b1); text-decoration: line-through;">' .. codeDisplay .. '</span>'
            allnames = '<div class="skin-invert" style="color: var(--color-disabled, #a2a9b1); text-decoration: line-through;">' .. allnames .. '\n</div>'
            if not item.isAliasRecord and item._getRevokeMessage then
                criteria = criteria .. '\n<span style="color: var(--color-destructive, #bf3c2c); font-weight: bold;">' .. item._getRevokeMessage() .. '</span>'
            end
		elseif item.isAliasRecord then
            codeDisplay = ''
            allnames = '<div class="skin-invert" style="color: var(--color-option-orange, #a95226);">' .. allnames .. '\n</div>'
		elseif item.isMissing then
            codeDisplay = ''
            allnames = '<div class="skin-invert" style="color: var(--color-error, #bf3c2c);">' .. allnames .. '\n</div>'
        end

        local desc = ""
        if not item.isAliasRecord then
            desc = extractShortDesc(item):gsub('&#123;&#123;subst:', '{{tls|'):gsub('&#123;&#123;', '{{tl|'):gsub('&#124;', '|'):gsub('&#125;&#125;', '}}')
        end

        wt = wt .. string.format([=[
|-
|%s
|%s
|%s
|%s
        ]=],
        codeDisplay,
        allnames,
        criteria,
        desc)
    end
    wt = wt .. '|}'
    return frame:preprocess(wt)
end

function z.reasonsBox(frame)
	return makeReasonsBox(frame, use_sandbox_by_frame(frame) and get_data_sandbox() or data_main)
end

local function CSD_reason(frame, use_sandbox)
    local args = getArgs(frame, {
        parentFirst = true
    })
    local rows = mDelete._input(args, {
        maxArgs = 1,
        data = use_sandbox and get_data_sandbox() or data_main,
        allowRevoked = true
    })
    local item = rows and rows[1] or nil
    if not item or not item['code'] then
        return '[[WP:快速删除|' .. (args[2] or '快速删除方针') .. ']]'
    elseif item['code'] == '' then
        return require('Module:Error').error{'錯誤:無法找到速刪代碼為<code>' .. args[1] .. '</code>的速刪項目。'}
    else
        local text
        if args[2] ~= nil and args[2] ~= '' then
            text = args[2]
        elseif args['notCSD'] ~= nil and args['notCSD'] ~= '' then
        	text = item['code']
        else
            text = 'CSD ' .. item['code']
        end

        if args.nolink then
            return text
        elseif args.reason then
            return  '[[WP:快速删除#' .. item['code'] .. '|' .. text .. ']]:<span title="' .. extractShortDesc(item) .. '">' .. item['criteria'] .. '</span>'
        elseif args.onlyreason then
            return  '<span title="' .. extractShortDesc(item) .. '">' .. item['criteria'] ..'</span>'
        else
            return '[[WP:快速删除#' .. item['code'] .. '|' .. text .. ']]'
        end
    end
end

function z.CSD_reason(frame)
    return CSD_reason(frame, use_sandbox_by_frame(frame))
end

function z._getInputWithoutError(args)
   local rows = mDelete._input(args, {
        maxArgs = 10,
        checkFunc = false,
        checkFile = true,
        parseCommit = false
    })
    if not rows then
        return nil
    end
    local outputs = {}
    for _, item in ipairs(rows) do
        if item['code'] and item['code'] ~= '' then
            local imgLink = ''
            -- special case for F1/F5
            if item['code'] == 'F1' or item['code'] == 'F5' then
                if item['imgLink'] then
                    imgLink = '(' .. item['imgLink'] .. ')'
                end
            end
         
            table.insert(outputs, '* [[WP:快速删除#' .. item['code'] .. '|CSD ' .. item['code'] .. ']]:<b>' .. item['criteria'].. '</b>' .. imgLink )
        elseif item['code'] == '' then
        	local arg = item['criteria']
            -- try to read it as a title
            local success, aTitle = mw.title.new(mw.text.trim(arg))
            if success and aTitle and aTitle.exists then
                table.insert(outputs, '* <b>' .. '[[:' .. arg .. ']]</b>')
            else
                arg = string.gsub(arg, '^([*:#]*)(.*)', '%1<b>%2</b>')
                table.insert(outputs, '* ' .. arg)
            end
        end

        if item['commit'] then
            table.insert(outputs, '*' .. item['commit'])
        end
    end
    
    return mw.text.trim(table.concat(outputs, '\n'))
end

function z.getInputWithoutError(frame)
    local args = frame:getParent().args
    local out = z._getInputWithoutError(args);
    if not out then
        return '* <span style="color:#080;">(未填寫理由)</span>'
    end
    return out
end

z.reasons_box = z.reasonsBox

return z