Module:少女歌剧
跳到导航
跳到搜索
- local module = {}
- module.BASEPAGE = "Module:少女歌剧" -- 常量,表示获取少女歌剧专题信息查询模块根页面路径。
- module.DATABASEPAGE = module.BASEPAGE .. "/Data" -- 常量,表示获取Data的模块根页面路径。
- module.NGROUPPAGE = module.BASEPAGE .. "/NGroup" -- 常量,表示获取名称组列表的模块根页面路径。
- local mps = require("Module:ModulePageSystem")
- --[==[
- 加载某一个模块页中的数据。
- --]==]
- local loadData = function(page, ignoreerror)
- if page == nil then return nil end
- local title = mw.title.new(page)
- if title == nil then
- mps.util.error(mw.ustring.format("加载数据页\"%s\"时发生错误:%s", page, "页面路径地址不符合规范。"), mps.util.ELID_WARNING)
- return nil
- elseif not title.exists then
- mps.util.error(mw.ustring.format("加载数据页\"%s\"时发生错误:%s", page, "页面不存在。"), mps.util.ELID_WARNING)
- return nil
- end
- local success, result = pcall(mw.loadData, page)
- if success then
- return result
- else
- mps.util.error(mw.ustring.format("加载数据页\"%s\"时发生错误:%s", page, result), mps.util.ELID_WARNING)
- return nil
- end
- end
- --[==[
- 获取传入的参数,若#invoke时传入至少一个以数字为参数名的参数,则使用#invoke时传入的参数列表;否则使用包装了模块#invoke的模板传入的参数列表。
- --]==]
- local getArgs = function(frame)
- local args
- if (function()
- for k, _ in pairs(frame.args) do
- if type(k) == "number" then
- return true
- end
- end
- end)() then
- args = frame.args
- else
- args = require("Module:Arguments").getArgs(frame:getParent() or frame)
- end
- return args
- end
- --[==[
- 获取分级索引关键词。
- --]==]
- local getPath = function(args, normalize)
- local path = {}
- for _, name in ipairs(args) do
- if normalize == true then name = mps.util.normalize(name) end
- table.insert(path, name)
- end
- return path
- end
- -- 可匹配多个正则。
- mw.ustring.gsub_m = function(s, patterns, repl, n)
- local length = mw.ustring.len(s)
- local init = 1
- local v1, v2
- local i = 0
- local ss = {}
- while (n == nil or i < n) and init < length do
- v1, v2 = length + 1, length
- local p = nil
- for _, pattern in ipairs(patterns) do
- local v3, v4 = mw.ustring.find(s, pattern, init, false)
- if v3 ~= nil and (v3 < v1 or (v3 == v1 and v4 <= v2)) then
- v1, v2 = v3, v4 -- 更新匹配范围。
- p = pattern -- 更新使用的正则。
- end
- end
- if p ~= nil then
- table.insert(ss, mw.ustring.sub(s, init, v1 - 1))
- local new_s = mw.ustring.gsub(mw.ustring.sub(s, v1, v2), p, repl, 1) -- 调用原生替换函数。
- table.insert(ss, new_s)
- else break
- end
- init = v2 + 1
- i = i + 1
- end
- table.insert(ss, mw.ustring.sub(s, init))
- return table.concat(ss)
- end
- module.gsub_m = function(str, func)
- local patterns = {
- "(%$(%$))",
- "(%$%(([^)]*)%))",
- "(%$(%d))",
- "(%$([^($]))"
- }
- return mw.ustring.gsub_m(str, patterns, func or "-")
- end
- function module.data(frame)
- local args = getArgs(frame)
- local ignoreerror = frame.args.ignoreerror == "yes" or args.ignoreerror == "yes" or false
- local path = getPath(args)
- local page = frame.args.page or args.page or module.DATABASEPAGE
- local params = { ngpage = { path = module.NGROUPPAGE, data = loadData(module.NGROUPPAGE) or {} } }
- local result = loadData(page, true) or {}
- for index, name in ipairs(path) do
- if type(result) ~= "table" then -- 上级节点含有值。
- -- 回溯一次查询,并将上级节点的键作为目录尝试加载本级页面,以重新从本级页面中查询。
- page = mw.ustring.format("%s/%s", page, path[index - 1])
- result = loadData(page, true) or {}
- end
- local keyexists = false
- for cname, subnodes in pairs(result) do
- if mps.util.KEYCOMPARER_NGROUP(cname, name, params) then -- 表中含有这个值
- result = subnodes
- keyexists = true
- end
- end
- if not keyexists then
- -- 尝试加载次级页面,以从次级页面中继续查询。
- page = mw.ustring.format("%s/%s", page, name)
- result = loadData(page, true) or {}
- end
- end
- if type(result) == "table" then -- 查询结果不是值。
- if not ignoreerror then error("查询到的值为空(可能在指定名称上的值的类型不是字符串,或者指定名称不存在)。")
- else return nil
- end
- else
- -- 成功查询到值。
- return result
- end
- end
- --[==[
- 【将要弃用】
- --]==]
- local vardefine = function(name, value, frame)
- local wiki
- if mw.ustring.sub(value, 1, 1) == "$" then -- 是wiki
- wiki = mw.ustring.gsub(mw.ustring.sub(value, 2), "%%[%%$]", function(m)
- if m == "%%" then return "%"
- elseif m == "%$" then return "$"
- else return ""
- end
- end)
- wiki = frame:preprocess(wiki)
- else
- wiki = value
- end
- return frame:callParserFunction("#vardefine", name, wiki)
- end
- --[==[
- 将指定的名称组通过{{#vardefine}}写入到维基文本中。
- --]==]
- function module.ngroup(frame)
- local ngroup = mw.loadData(module.NGROUPPAGE)
- local vdexprs = {}
- for gname, names in pairs(ngroup) do
- if type(gname) == "string" then
- for _, name in ipairs(names) do
- local expr = vardefine(mw.ustring.format("%s %s", "名称组", name), gname, frame)
- if expr ~= nil then
- table.insert(vdexprs, expr) -- 添加定义语句。
- end
- end
- end
- end
- return table.concat(vdexprs)
- end
- --[==[
- 将指定的数据通过{{#vardefine}}写入到维基文本中。
- --]==]
- function module.define(frame)
- local args = getArgs(frame)
- local datapage
- if mw.ustring.match(args.datapage or "", "^[/\\]") then -- 是相对路径
- datapage = module.DATABASEPAGE .. args.datapage
- else -- 是绝对路径
- datapage = args.datapage
- end
- local ngroup = mw.loadData(module.NGROUPPAGE)
- local vdexprs = {}
- local function defineInternal(data, path, dir)
- if type(data) == "table" then
- if #path == 0 then table.insert(path, "$") end -- 若path提供的匹配列表没有查询到底层节点,则插入默认的匹配所有键正则以查询到底层节点。
- elseif type(data) == "string" then
- if #path > 0 then error("无法继续向下层节点查询,因为当前节点已经是底层节点。") end
- local expr = vardefine(dir, data, frame)
- if expr ~= nil then
- table.insert(vdexprs, expr) -- 添加定义语句。
- end
- return
- else return -- 不支持其他类型的值。
- end
- local pattern = path[1]
- local isngroup = mw.ustring.sub(pattern, 1, 2) == "$$" -- 仅匹配名称组时在开头添加两个$字符。
- local isall = not isngroup and (mw.ustring.sub(pattern, 1, 1) == "$") -- 匹配所有键时在开头添加一个$字符。
- for dkey, dvalue in pairs(data) do
- if isall or (mw.ustring.sub(dkey, 1, 1) == "$") == isngroup then -- 同或,表示数据键和查找键正则同时是或同时不是名称组。
- if mw.ustring.sub(dkey, 1, 1) == "$" then -- 数据键是名称组。
- local ngkey = mps.util.normalize(mw.ustring.sub(dkey, 2)) -- 获取名称组键。
- if isall then
- pattern = mw.ustring.sub(pattern, 2) -- 获取正则。
- elseif isngroup then
- pattern = mw.ustring.sub(pattern, 3) -- 获取正则。
- end
- if mw.ustring.match(ngkey, pattern) then -- 匹配成功。
- local newdata = dvalue
- local newpath = {}
- for i = 2, #path do table.insert(newpath, path[i]) end
- local newdir
- if dir == nil then
- newdir = ngkey
- else
- newdir = mw.ustring.format("%s %s", dir, ngkey)
- end
- defineInternal(newdata, newpath, newdir)
- end
- else -- 数据键不是名称组。
- dkey = mps.util.normalize(dkey)
- if isall then
- pattern = mw.ustring.sub(pattern, 2) -- 获取正则。
- end
- if mw.ustring.match(dkey, pattern) then -- 匹配成功。
- local newdata = dvalue
- local newpath = {}
- for i = 2, #path do table.insert(newpath, path[i]) end
- local newdir
- if dir == nil then
- newdir = dkey
- else
- newdir = mw.ustring.format("%s %s", dir, dkey)
- end
- defineInternal(newdata, newpath, newdir)
- end
- end
- end
- end
- end
- defineInternal(mw.loadData(datapage), getPath(args), nil)
- return table.concat(vdexprs)
- end
- -- Only for Template:九九组成员对她的称呼 and Template:舞台少女称呼表
- function module.aishou(frame)
- local args = frame.args
- local data = mw.loadData(module.DATABASEPAGE.."/角色称呼表")
- local name = args.name or "爱城华恋" -- 她的名字。
- local node = mw.html.create("table")
- :css("font-size", "89%")
- :css("text-align", "center")
- :css("max-width", "260px")
- :css("float", "right")
- :css("background-color", "white")
- :tag("tr"):tag("th")
- :css("color", "white")
- :css("background-color", frame:callParserFunction{ name = "#var", args = { name } })
- :css("font-size", "100%")
- :css("font-weight", "bold")
- :css("padding", "1em")
- :attr("colspan", 2)
- :wikitext("其他人对")
- :wikitext(frame:expandTemplate{ title = "少女歌剧/角色信息", args = { name, "姓名地区转换" } })
- :wikitext("的称呼")
- :allDone()
- for _, cname in ipairs(module.sortNameGroup()) do
- local cothers = data["$" .. cname] or {}
- for cother, ass in pairs(cothers) do
- cother = mw.text.trim(cother, "$") -- 简单处理。
- if name == cother then
- -- 处理格式字符串 --
- local as_process = function(as)
- local patterns = {
- "(%$(%$))",
- "(%$%(([^)]*)%))",
- "(%$([^($]))"
- }
- -- 进行通用格式字符串替换,获得新格式字符串。
- as = mw.ustring.gsub_m(as, patterns, function(rawtext, matchtext)
- if rawtext == "$$" then return "$$"
- else
- local numindex = tonumber(matchtext) -- 如果索引值是数字,优先转换为number类型键。
- if numindex then
- return data.COMMON[numindex] or data.COMMON[matchtext] or rawtext
- else
- if not mw.ustring.find(matchtext, "^日文") then
- matchtext = "日文"..matchtext -- 在前方添加“日文”。
- rawtext = "$("..matchtext..")" -- 在前方添加“日文”。
- end
- return data.COMMON[matchtext] or rawtext
- end
- end
- end)
- as = mw.ustring.gsub_m(as, patterns, function(rawtext, matchtext)
- if rawtext == "$$" then return "$"
- else
- return frame:expandTemplate{ title = "少女歌剧/角色信息", args = { name, matchtext } } -- 调用模板,获取角色信息。
- end
- end)
- return as
- end
- local empty = false
- if type(ass) == "table" then
- local _ass = {}
- for i_as, as in ipairs(ass) do
- _ass[i_as] = frame:expandTemplate{ title = "lj", args = { as_process(as) } }
- end
- if #_ass == 0 then empty = true
- else
- ass = table.concat(_ass, "、")
- end
- else
- if mw.text.trim(ass) == "" then empty = true
- else
- ass = frame:expandTemplate{ title = "lj", args = { as_process(ass) } }
- end
- end
- if not empty then
- local ltext
- if name == cname then
- ltext = "自称"
- else
- ltext =
- frame:expandTemplate{ title = "少女歌剧/角色表述", args =
- {
- cname,
- "内链",
- frame:expandTemplate{ title = "Color", args =
- {
- "white",
- frame:expandTemplate{ title = "少女歌剧/角色信息", args = { cname, "名地区转换" } }
- } }
- } }
- end
- --------------------
- node:tag("tr")
- :tag("td")
- :css("color", "white")
- :css("background-color", frame:callParserFunction{ name = "#var", args = { cname } })
- :css("font-weight", "bold")
- :css("padding", "0 1em")
- :css("min-width", "80px")
- :wikitext(ltext)
- :done()
- :tag("td")
- :css("padding", "0 1em")
- :css("min-width", "140px")
- :wikitext(ass)
- end
- end
- end
- end
- return tostring(node)
- end
- -- 对名称组列表list,按categories(匿名函数)列表指示的顺序排序。
- function module.sortNameGroup(list, --[[ categories ]]...)
- local categories = {}
- -- 整理排序分类列表。
- for i = 1, select("#", ...) do
- local cat = select(i, ...)
- if cat then
- table.insert(categories, cat)
- end
- end
- local data = loadData(module.NGROUPPAGE) -- 加载名称组数据。
- if #categories == 0 then categories = data[0] end -- 使用默认排序分类列表。
- local result = {}
- for _, cat in ipairs(categories) do
- for _, catinfo in ipairs(data) do
- if catinfo.category == cat then
- for _, _ng in ipairs(catinfo) do
- if type(list) == "table" then
- for _, ng in ipairs(list) do
- if ng == _ng then
- table.insert(result, ng)
- end
- end
- elseif type(list) == "string" and list == _ng then
- table.insert(result, list)
- elseif list == nil then
- table.insert(result, _ng)
- else
- mps.util.error(mw.ustring.format("参数list的值类型错误。(应为%s,实际为%s)", "table、string或nil", type(list)), mps.util.ELID_ERROR)
- end
- end
- end
- end
- end
- return result
- end
- return module