Module:ModulePageSystem
跳到导航
跳到搜索
- local mps = {}
- mps.util = require("Module:ModulePageSystem/util")
- local dictionary = require("Module:Dictionary")
- mps.FUNC_HASVALUE_TRUE = function() return true end
- mps.FUNC_HASVALUE_FALSE = function() return false end
- mps.FUNC_VALUE_NIL = function() return nil end
- --定义一个常量,表示该节点值不存在。
- mps.NOVALUE = {
- hasValue = mps.FUNC_HASVALUE_FALSE,
- value = mps.FUNC_VALUE_NIL
- }
- --[[
- 验证一个节点是否是格式正确的对象。
- 通过检测数个字段、函数是否存在,类型是否正确来验证节点格式是否正确。
- -----
- node - 将要验证的节点。
- validations - 指定了验证的类型,若有多个验证类型,则以空白字符分隔,验证结果将取与。
- value - 该节点支持存储值。
- sub - 该节点支持包含次级节点。
- -----
- 返回:多个验证类型结果的与值。
- --]]
- function mps.validate(node, validations)
- if node == nil then return false
- elseif type(node) ~= "table" then return false
- end
- if type(validations) == "table" then validations = table.concat(validations, " ")
- elseif type(validations) ~= "string" then return false
- end
- for validation in mw.ustring.gmatch(validations, "%S+") do
- if validation == "value" then
- if type(node.hasValue) ~= "function" or
- type(node.value) ~= "function" then return false end
- elseif validation == "ref" then
- if type(node.getTarget) ~= "function" then return false end
- elseif validation == "sub" then
- if type(node.plain) ~= "function" or
- type(node.wiki) ~= "function" or
- type(node.ref) ~= "function" or
- type(node.sub) ~= "function" or
- type(node.substart) ~= "function" or
- type(node.subend) ~= "function" or
- type(node.format) ~= "function" or
- type(node.find) ~= "function" then return false end
- else
- mps.util.error(mw.ustring.format("不支持的验证类型:\"%s\"", validation), mps.util.ELID_WARNING)
- return false
- end
- end
- return true
- end
- --[[
- 从指定的节点开始按路径查找值。
- -----
- node - 指定的节点。
- path - 路径
- -----
- 返回:路径name处的值。
- --]]
- function mps.find(node, path, params)
- if type(params) ~= "table" then params = {} end
- if type(params.path) ~= "table" then params.path = {} end
- if type(params.basestack) ~= "table" then params.basestack = {} end
- if type(params.refhistory) ~= "table" then params.refhistory = dictionary.create() end
- if node == nil or type(node) == "string" then -- node为表示以这个字符串为网页路径创建的节点。
- -- 若node为空,则设为调用页面的标题。
- node = node or mw.title.getCurrentTitle().prefixedText
- -- 尝试加载页面。
- local root = mps.load({}, node)
- if mps.validate(node, "value") and value:hasValue(params) then
- -- 以这个字符串为基地址创建根节点。
- node = mps.create(node)
- else
- node = root
- end
- end
- if params.root == nil then params.root = node end -- 将自身设为查询根节点。
- local value
- local subpath = mps.util.pathSplit(path)
- -- 截取顶层目录为当前名称;其余为下级名称。
- local name = subpath[1]
- table.remove(subpath, 1)
- table.insert(params.path, name) -- 将当前名称添加到路径中。
- table.insert(params.basestack, { node.base }) -- 将当前所属页面路径添加到页面路径堆栈中。(由于所属页面路径可能为nil,故用table包裹。)
- -- 筛选子节点。子节点是否为底层节点将对其是否会被接受有影响。
- -- 底层节点:接受值节点;不接受含有子节点的节点。
- -- 非底层节点:接受含有子节点的节点;不接受值节点。
- local findInternal = function(_value)
- -- 获取节点值。
- if mps.validate(_value, "ref") then -- 如果是引用节点
- -- 获取引用节点指向的节点。
- _value = _value:getTarget(params)
- end
- if (params.novalidation or false) == true then -- 若忽略子节点是否为底层节点对其是否会被接受的影响。
- if #subpath == 0 then -- 仅当子节点为底层节点时生效。
- if (mps.validate(_value, "value") and _value:hasValue(params)) or mps.validate(_value, "sub") then
- -- 仅在子节点是含有值的值节点或者含有子节点的节点时,直接返回子节点本身。
- return _value
- end
- end
- end
- if #subpath == 0 and mps.validate(_value, "value") then -- 如果是底层节点,且节点是值节点。
- if _value:hasValue(params) then -- 如果有值则返回节点。
- return _value
- end
- elseif #subpath ~= 0 and mps.validate(_value, "sub") then -- 如果不是底层节点,且节点含有子节点。
- -- 进行递归查找。
- _value = _value:find(subpath, params)
- if mps.validate(_value, "value") and _value:hasValue(params) then -- 子节点查找到值则返回节点。
- return _value
- elseif mps.validate(_value, "sub") then -- 从findInternal返回的含有子节点的节点绝对是忽略层级影响。
- return _value
- end
- elseif #subpath == 0 and not (mps.validate(_value, "value") or mps.validate(_value, "sub")) then -- 节点不是任何节点,且是底层节点。
- mps.util.error("非节点对象。", mps.util.ELID_ERROR)
- end
- return mps.NOVALUE -- 查找不到子节点树的值。
- end
- if mps.validate(node, "sub") then -- 本节点含有子节点。
- -- 寻找键name。
- if node.dic:hasKey(name) then
- value = findInternal(node.dic:getValue(name))
- if mps.validate(value, "value") and value:hasValue(params) then
- table.remove(params.path, #params.path) -- 从路径中删除最后一段名称。
- table.remove(params.basestack, #params.basestack) -- 从页面路径堆栈中删除最后一段所属页面路径。
- return value
- elseif mps.validate(value, "sub") then -- 从findInternal返回的含有子节点的节点绝对是忽略层级影响。
- table.remove(params.path, #params.path) -- 从路径中删除最后一段名称。
- table.remove(params.basestack, #params.basestack) -- 从页面路径堆栈中删除最后一段所属页面路径。
- return value
- end
- end
- -- 寻找通用函数formatfunc。
- if node.formatfunc ~= nil then -- 找到通用函数formatfunc。
- -- 获取处理结果。
- value = node:formatfunc(name, params)
- value = findInternal(value)
- if mps.validate(value, "value") and value:hasValue(params) then
- table.remove(params.path, #params.path) -- 从路径中删除最后一段名称。
- table.remove(params.basestack, #params.basestack) -- 从页面路径堆栈中删除最后一段所属页面路径。
- return value
- elseif mps.validate(value, "sub") then -- 从findInternal返回的含有子节点的节点绝对是忽略层级影响。
- table.remove(params.path, #params.path) -- 从路径中删除最后一段名称。
- table.remove(params.basestack, #params.basestack) -- 从页面路径堆栈中删除最后一段所属页面路径。
- return value
- end
- end
- end
- -- 尝试加载页面。
- local fullpagename = nil
- -- 沿堆栈向下查询上级节点的基路径。
- for i = #params.basestack, 1, -1 do
- if #params.basestack[i] ~= 0 then
- fullpagename = params.basestack[i][1]
- break;
- end
- end
- if fullpagename == nil then
- -- 无法获取基路径。
- mps.util.error(mw.ustring.format("无法获取节点“%s”基路径,因为上层节点均未定义基路径。", mps.util.pathCombine(params.path)), mps.util.ELID_WARNING)
- else
- fullpagename = mw.ustring.format("%s/%s", fullpagename, table.concat(mps.util.pathSplit(params.path), "/")) -- 要加载的页面。
- value = findInternal(mps.load(node, fullpagename))
- if mps.validate(value, "value") and value:hasValue(params) then -- 页面加载成功。
- table.remove(params.path, #params.path) -- 从路径中删除最后一段名称。
- table.remove(params.basestack, #params.basestack) -- 从页面路径堆栈中删除最后一段所属页面路径。
- return value
- elseif mps.validate(value, "sub") then -- 从findInternal返回的含有子节点的节点绝对是忽略层级影响。
- table.remove(params.path, #params.path) -- 从路径中删除最后一段名称。
- table.remove(params.basestack, #params.basestack) -- 从页面路径堆栈中删除最后一段所属页面路径。
- return value
- end
- end
- table.remove(params.path, #params.path) -- 从路径中删除最后一段名称。
- table.remove(params.basestack, #params.basestack) -- 从页面路径堆栈中删除最后一段所属页面路径。
- return mps.NOVALUE -- 查询不到值。
- end
- mps.FUNC_SUBEND_COMMON = function(self)
- mps.util.error("语法错误:subend。(当前并未处于定义子项的上下文。)", mps.util.ELID_WARNING)
- return self
- end
- --[[
- 从一个页面地址创建一个节点。
- -----
- page - 定义这个节点的页面,应当是你在书写这个代码时所处的模块名页面全名。
- -----
- 返回:新节点。
- --]]
- function mps.create(page)
- if page ~= nil and type(page) ~= "string" then mps.util.error(mw.ustring.format("在create中参数page的值类型错误。(应为%s,实际为%s)", "nil或string", type(page)), mps.util.ELID_FATAL)
- elseif page == nil then -- 检测页面地址是否为空。
- mps.util.error(mw.ustring.format("页面地址为空。", page), mps.util.ELID_WARNING)
- elseif type(page) == "string" and mw.title.new(page) == nil then -- 检测页面地址是否包含不合法字符。
- mps.util.error(mw.ustring.format("页面地址“%s”包含不合法字符。", page), mps.util.ELID_ERROR)
- end
- local prototype = {
- dic = dictionary.create(function(k1, k2) return mps.util.normalize(k1) == mps.util.normalize(k2) end),
- base = page, -- 本节点所在的页面地址。
- inheritbase = "", -- [未启用]以定义了页面地址的最近一个上层节点开始到本节点的路径,即本节点的“继承”得到的基路径。
- plain = mps.registerPlain,
- wiki = mps.registerWiki,
- ref = mps.registerRef,
- sub = mps.registerSubpage,
- substart = mps.registerNewSubpage,
- subend = mps.FUNC_SUBEND_COMMON,
- format = mps.registerFormat,
- find = mps.find
- }
- return prototype
- end
- mps.FUNC_VALUE_PLAIN = function(self) return self.innervalue end
- --[[
- 创建一个纯文本的值节点。
- -----
- plain - 文本内容。
- page - 定义这个节点的页面,应当是你在书写这个代码时所处的模块名页面全名。
- -----
- 返回:新值节点。
- --]]
- function mps.createPlain(plain, page)
- if plain ~= nil and type(plain) ~= "string" then mps.util.error(mw.ustring.format("参数plain的值类型错误。(应为%s,实际为%s)", "nil或string", type(plain)), mps.util.ELID_FATAL) end
- if page ~= nil and type(page) ~= "string" then mps.util.error(mw.ustring.format("参数page的值类型错误。(应为%s,实际为%s)", "nil或string", type(page)), mps.util.ELID_FATAL)
- elseif page == nil then -- 检测页面地址是否为空。
- mps.util.error(mw.ustring.format("页面地址为空。", page), mps.util.ELID_WARNING)
- elseif type(page) == "string" and mw.title.new(page) == nil then -- 检测页面地址是否包含不合法字符。
- mps.util.error(mw.ustring.format("页面地址“%s”包含不合法字符。", page), mps.util.ELID_ERROR)
- end
- return {
- base = page,
- innervalue = plain,
- hasValue = mps.FUNC_HASVALUE_TRUE,
- value = mps.FUNC_VALUE_PLAIN
- }
- end
- mps.FUNC_VALUE_WIKI = function(self, params)
- if self.innervalue == nil then return nil
- elseif params.plain then return self.innervalue
- elseif self.innerwiki ~= nil then return self.innerwiki
- elseif params == nil or params.frame == nil then
- mps.util.error(mw.ustring.format("无法获取wiki执行对象(frame的值为nil)。"), mps.util.ELID_WARNING)
- else
- self.innerwiki = params.frame:preprocess(self.innervalue)
- return self.innerwiki
- end
- end
- --[[
- 创建一个Wiki内容的值节点。
- -----
- wiki - Wiki内容。
- plain - 指示wiki参数的字符串值是否是纯文本,默认为true。
- page - 定义这个节点的页面,应当是你在书写这个代码时所处的模块名页面全名。
- -----
- 返回:新值节点。
- --]]
- function mps.createWiki(wiki, plain, page)
- if wiki ~= nil and type(wiki) ~= "string" then mps.util.error(mw.ustring.format("参数wiki的值类型错误。(应为%s,实际为%s)", "nil或string", type(wiki)), mps.util.ELID_FATAL) end
- if page ~= nil and type(page) ~= "string" then mps.util.error(mw.ustring.format("参数page的值类型错误。(应为%s,实际为%s)", "nil或string", type(page)), mps.util.ELID_FATAL)
- elseif page == nil then -- 检测页面地址是否为空。
- mps.util.error(mw.ustring.format("页面地址为空。", page), mps.util.ELID_WARNING)
- elseif type(page) == "string" and mw.title.new(page) == nil then -- 检测页面地址是否包含不合法字符。
- mps.util.error(mw.ustring.format("页面地址“%s”包含不合法字符。", page), mps.util.ELID_ERROR)
- end
- local result = {
- base = page,
- innervalue = wiki,
- innerwiki = nil,
- hasValue = mps.FUNC_HASVALUE_TRUE,
- value = mps.FUNC_VALUE_WIKI
- }
- if (plain or false) ~= true then result.innerwiki = wiki end -- 默认是以纯文本形式创建。
- return result
- end
- local find_ref = function(node, params)
- -- 查找引用历史,检测是否循环引用。
- local flag = false
- local path = mps.util.pathCombine(params.path)
- if params.refhistory:hasKey(path) then
- -- 检测到循环引用。
- flag = true
- else
- for _, rh_entry in params.refhistory:enum() do
- if rh_entry.value == node then
- -- 检测到循环引用。
- flag = true
- break
- end
- end
- end
- if flag then
- local errorinfo = {}
- for _, _entry in params.refhistory:enum() do
- table.insert(errorinfo, _entry.key)
- end
- table.insert(errorinfo, rh_entry.key)
- mps.util.error("形成了循环引用。(“%s”)", table.concat(errorinfo, "”→“"), mps.util.ELID_ERROR)
- return mps.NOVALUE
- end
- -- 构建引用目标节点的路径。
- local newPath
- if node.isabsolute then -- 绝对路径
- newPath = mps.util.pathCombine(node.innervalue)
- else -- 相对路径
- newPath = mps.util.pathCombine(params.path, mps.util.PARENTNODE, node.innervalue)
- end
- -- 构建查找引用目标节点的新参数。
- local newParams = {
- frame = params.frame,
- plain = params.plain,
- refhistory = dictionary.create(nil, params.refhistory):add(path, node), -- 新建引用历史字典的副本,并将自身添加进去。
- novalidation = true -- 忽略节点所处层级的影响。
- }
- return mps.find(params.root, newPath, newParams), newParams
- end
- mps.FUNC_GETTARGET_REF = function(self, params)
- local target, newParams = find_ref(self, params)
- -- 递归获得指向的目标节点。
- if mps.validate(target, "ref") then
- return target:getTarget(target, newParams)
- else
- return target
- end
- end
- --[[
- 创建一个引用节点。
- -----
- target - 引用指向的目标。
- isabsolute - 指示target参数表示的引用目标路径是否为绝对路径,默认为true。
- page - 定义这个节点的页面,应当是你在书写这个代码时所处的模块名页面全名。
- -----
- 返回:新引用节点。
- --]]
- function mps.createRef(target, isabsolute, page)
- if page ~= nil and type(page) ~= "string" then mps.util.error(mw.ustring.format("参数page的值类型错误。(应为%s,实际为%s)", "nil或string", type(page)), mps.util.ELID_FATAL)
- elseif page == nil then -- 检测页面地址是否为空。
- mps.util.error(mw.ustring.format("页面地址为空。", page), mps.util.ELID_WARNING)
- elseif type(page) == "string" and mw.title.new(page) == nil then -- 检测页面地址是否包含不合法字符。
- mps.util.error(mw.ustring.format("页面地址“%s”包含不合法字符。", page), mps.util.ELID_ERROR)
- end
- return {
- base = page,
- innervalue = target,
- isabsolute = (isabsolute or false) == true,
- getTarget = mps.FUNC_GETTARGET_REF
- }
- end
- --[[
- 向节点中注册一个纯文本的子值节点。
- -----
- parent - 节点本身。
- name - 子节点名称。
- plain - 文本内容。
- page - 定义这个节点的页面,应当是你在书写这个代码时所处的模块名页面全名。若为非空值,则将覆盖参数parent的继承。
- -----
- 返回:节点本身。(为语法糖提供支持)
- --]]
- function mps.registerPlain(parent, name, plain, page)
- if type(parent) == "nil" then mps.util.error(mw.ustring.format("参数parent的值类型错误。(应为%s,实际为%s)", "table", type(parent)), mps.util.ELID_FATAL) end
- if type(name) ~= "string" then mps.util.error(mw.ustring.format("参数name的值类型错误。(应为%s,实际为%s)", "string", type(name)), mps.util.ELID_FATAL) end
- if page ~= nil and type(page) ~= "string" then mps.util.error(mw.ustring.format("参数page的值类型错误。(应为%s,实际为%s)", "nil或string", type(page)), mps.util.ELID_FATAL) end
- plain = mps.createPlain(plain, page or parent.page)
- if parent.dic:hasKey(name) then
- if parent.dic:getValue(name) ~= nil and parent.dic:getValue(name):hasValue() then
- mps.util.error(mw.ustring.format("在对节点\"%s\"赋值时失败,该节点已存在另外的值。", name), mps.util.ELID_ERROR)
- else
- parent.dic:setValue(name, plain)
- end
- else
- parent.dic:add(name, plain)
- end
- return parent
- end
- --[[
- 向节点中注册一个Wiki内容的子值节点。
- -----
- parent - 节点本身。
- name - 子节点名称。
- wiki - Wiki内容。
- plain - 指示wiki参数的字符串值是否是纯文本,默认为true。
- page - 定义这个节点的页面,应当是你在书写这个代码时所处的模块名页面全名。若为非空值,则将覆盖参数parent的继承。
- -----
- 返回:节点本身。(为语法糖提供支持)
- --]]
- function mps.registerWiki(parent, name, wiki, plain, page)
- if type(parent) == "nil" then mps.util.error(mw.ustring.format("参数parent的值类型错误。(应为%s,实际为%s)", "table", type(parent)), mps.util.ELID_FATAL) end
- if type(name) ~= "string" then mps.util.error(mw.ustring.format("参数name的值类型错误。(应为%s,实际为%s)", "string", type(name)), mps.util.ELID_FATAL) end
- if page ~= nil and type(page) ~= "string" then mps.util.error(mw.ustring.format("参数page的值类型错误。(应为%s,实际为%s)", "nil或string", type(page)), mps.util.ELID_FATAL) end
- wiki = mps.createWiki(wiki, plain, page or parent.page)
- if parent.dic:hasKey(name) then
- if parent.dic:getValue(name) ~= nil and parent.dic:getValue(name):hasValue() then
- mps.util.error(mw.ustring.format("在对节点\"%s\"赋值时失败,该节点已存在另外的值。", name), mps.util.ELID_ERROR)
- else
- parent.dic:setValue(name, wiki)
- end
- else
- parent.dic:add(name, wiki)
- end
- return parent
- end
- --[[
- 向节点中注册一个引用的子值节点。
- -----
- parent - 节点本身。
- names - 所有引用子节点的名称(被指向目标的别名)。若类型为string则表示一个名称;若类型为table则表示多个名称。
- target - 引用指向的目标。
- isabsolute - 指示target参数表示的引用目标路径是否为绝对路径,默认为true。
- page - 定义这个节点的页面,应当是你在书写这个代码时所处的模块名页面全名。若为非空值,则将覆盖参数parent的继承。
- -----
- 返回:节点本身。(为语法糖提供支持)
- --]]
- function mps.registerRef(parent, names, target, isabsolute, page)
- if type(parent) == "nil" then mps.util.error(mw.ustring.format("参数parent的值类型错误。(应为%s,实际为%s)", "table", type(parent)), mps.util.ELID_FATAL) end
- if type(names) == "string" then names = { names }
- elseif type(names) ~= "table" then mps.util.error(mw.ustring.format("参数names的值类型错误。(应为%s,实际为%s)", "string或table", type(names)), mps.util.ELID_FATAL)
- end
- if page ~= nil and type(page) ~= "string" then mps.util.error(mw.ustring.format("参数page的值类型错误。(应为%s,实际为%s)", "nil或string", type(page)), mps.util.ELID_FATAL) end
- local ref
- for i, name in ipairs(names) do
- if type(name) ~= "string" then
- mps.util.error(mw.ustring.format("参数names的第%d项的值类型错误。(应为%s,实际为%s)", i, "string", type(name)), mps.util.ELID_FATAL)
- else
- ref = ref or mps.createRef(target, isabsolute, page or parent.base) -- 只创建一次,整个循环使用同一且唯一的引用节点。
- if parent.dic:hasKey(name) then
- if parent.dic:getValue(name) ~= nil and parent.dic:getValue(name):hasValue() then
- mps.util.error(mw.ustring.format("在对节点\"%s\"赋值时失败,该节点已存在另外的值。", name), mps.util.ELID_ERROR)
- else
- parent.dic:setValue(name, ref)
- end
- else
- parent.dic:add(name, ref)
- end
- end
- end
- return parent
- end
- --[[
- 向节点中注册一个现有的子节点。
- 这个子节点可以是从另一个页面导入、在本地定义的——node节点、储存了纯数据的普通Lua表。
- -----
- parent - 节点本身。
- name - 子节点名称。
- node - 将作为被添加的子节点的内容。
- page - 定义这个节点的页面,应当是你在书写这个代码时所处的模块名页面全名。若为非空值,则将覆盖参数parent的继承。
- -----
- 返回:节点本身。(为语法糖提供支持)
- --]]
- function mps.registerSubpage(parent, name, node, page)
- if type(parent) == "nil" then mps.util.error(mw.ustring.format("参数parent的值类型错误。(应为%s,实际为%s)", "table", type(parent)), mps.util.ELID_FATAL) end
- if type(name) ~= "string" then mps.util.error(mw.ustring.format("参数name的值类型错误。(应为%s,实际为%s)", "string", type(name)), mps.util.ELID_FATAL) end
- if page ~= nil and type(page) ~= "string" then mps.util.error(mw.ustring.format("参数page的值类型错误。(应为%s,实际为%s)", "nil或string", type(page)), mps.util.ELID_FATAL) end
- if type(node) == "string" then -- 是从指定路径的页面导入的内容。
- -- node默认是绝对路径,若需要引用节点所处页面路径则需使用“%0”。
- -- 获取绝对路径。
- local path = mw.ustring.gsub(node, "%%[%%0]", function(m)
- if m == "%%" then return "%"
- elseif m == "%0" then return parent.base
- else return ""
- end
- end)
- -- 加载页面。
- node = mps.load(parent, path)
- elseif type(node) == "table" then -- 是在本地定义的内容。
- if mps.validate(node, "sub") then -- 检测是否是含有子节点的节点对象。
- node = mps.derive(parent, node, page) -- 创建一个node的继承节点。
- elseif mps.validate(node, "value") then -- 检测是否是值节点。
- -- 设置所属页面路径。
- node.base = node.base or page or parent.base -- 取值原则:本地定义的值节点的已定义所属页面路径 → 覆盖参数parent继承的页面路径 → 参数parent继承的页面路径。
- else
- node = mps.parse(parent, node, page) -- 从一个普通Lua表转换成为节点。
- end
- end
- if parent.dic:hasKey(name) then
- if parent.dic:getValue(name) ~= nil and parent.dic:getValue(name):hasValue() then
- mps.util.error(mw.ustring.format("在对节点\"%s\"赋值时失败,该节点已存在另外的值。", name), mps.util.ELID_ERROR)
- else
- parent.dic:setValue(name, node)
- end
- else
- parent.dic:add(name, node)
- end
- return parent
- end
- mps.FUNC_SUBEND_SUB = function(self) return self.parent end
- --[[
- 向节点中注册一个子节点,并切换到子节点的上下文。
- 这个子节点可以是从另一个模板导入、在本地定义的——node节点、储存了纯数据的普通Lua表。
- -----
- parent - 节点本身。
- name - 子节点名称。
- node - 将作为被添加的子节点的内容。
- page - 定义这个节点的页面,应当是你在书写这个代码时所处的模块名页面全名。若为非空值,则将覆盖参数parent的继承。
- -----
- 返回:子节点本身。(为语法糖提供支持)
- --]]
- function mps.registerNewSubpage(parent, name)
- if type(parent) == "nil" then mps.util.error(mw.ustring.format("参数parent的值类型错误。(应为%s,实际为%s)", "table", type(parent)), mps.util.ELID_FATAL) end
- if type(name) ~= "string" then mps.util.error(mw.ustring.format("参数name的值类型错误。(应为%s,实际为%s)", "string", type(name)), mps.util.ELID_FATAL) end
- local prototype = mps.create(parent.page) -- 获取一个标准的节点对象。
- prototype.inheritbase = mps.util.pathCombine(parent.inheritbase, name) -- 继承本节点的路径组成新路径。
- prototype.parent = parent -- 将本节点保存在parent字段中
- prototype.subend = mps.FUNC_SUBEND_SUB -- 结束子节点定义,返回到其父节点,即本节点。
- if parent.dic:hasKey(name) then
- if parent.dic:getValue(name) ~= nil and parent.dic:getValue(name):hasValue() then
- mps.util.error(mw.ustring.format("在对节点\"%s\"赋值时失败,该节点已存在另外的值。", name), mps.util.ELID_ERROR)
- else
- parent.dic:setValue(name, prototype)
- end
- else
- parent.dic:add(name, prototype)
- end
- return prototype
- end
- function mps.registerFormat(parent, format)
- if type(parent) == "nil" then mps.util.error(mw.ustring.format("参数parent的值类型错误。(应为%s,实际为%s)", "table", type(parent)), mps.util.ELID_FATAL) end
- if format == nil then return
- elseif type(format) ~= "function" then mps.util.error(mw.ustring.format("通用函数formatfunc类型错误。(应为%s,实际为%s)", "function", type(format)), mps.util.ELID_FATAL)
- end
- if parent.formatfunc == nil then
- parent.formatfunc = format
- else
- mps.util.error("通用函数赋值失败,该节点已存在另外的通用函数。", mps.util.ELID_ERROR)
- end
- return parent
- end
- --[[
- 从指定页面加载节点。
- -----
- parent - 本节点。
- path - 包含节点的模块页面地址。
- -----
- 返回:指定页面包含的节点。
- --]]
- function mps.load(parent, path)
- if type(parent) == "nil" then mps.util.error(mw.ustring.format("在load中参数parent的值类型错误。(应为%s,实际为%s)", "table", type(parent)), mps.util.ELID_FATAL) end
- if type(path) ~= "string" then mps.util.error(mw.ustring.format("在load中参数path的值类型错误。(应为%s,实际为%s)", "string", type(path)), mps.util.ELID_FATAL) end
- local success, result = pcall(function(_path)
- local title = mw.title.new(_path) -- 获取要加载的页面的标题对象。
- if title == nil then
- error(mw.ustring.format("页面“%s”路径格式不正确。"), _path)
- elseif title.exists then -- 加载的页面存在。
- return require(_path)
- else
- mps.util.error(mw.ustring.format("页面“%s”不存在。", _path), mps.util.ELID_WARNING)
- return mps.NOVALUE
- end
- end, path)
- if result == mps.NOVALUE then return result
- elseif not success then
- mps.util.error(result, mps.util.ELID_ERROR)
- return mps.NOVALUE
- end
- local node = result
- if mps.validate(node, "sub") then -- 检测是否是节点对象。
- node = mps.derive(parent, node, path)
- else
- node = mps.parse(parent, node, path)
- end
- return node
- end
- --[[
- 将一个节点设为本节点的继承节点。
- -----
- parent - 本节点。
- sub - 要被设为继承节点的节点。
- page - 定义这个节点的页面,应当是你在书写这个代码时所处的模块名页面全名。若为非空值,则将覆盖参数parent的继承。
- -----
- 返回:被设为继承节点的节点。
- --]]
- function mps.derive(parent, sub, page)
- if type(parent) == "nil" then mps.util.error(mw.ustring.format("在derive中参数parent的值类型错误。(应为%s,实际为%s)", "table", type(parent)), mps.util.ELID_FATAL) end
- if type(sub) ~= "table" then mps.util.error(mw.ustring.format("在derive中参数sub的值类型错误。(应为%s,实际为%s)", "table", type(sub)), mps.util.ELID_FATAL) end
- if page ~= nil and type(page) ~= "string" then mps.util.error(mw.ustring.format("参数page的值类型错误。(应为%s,实际为%s)", "nil或string", type(page)), mps.util.ELID_FATAL) end
- sub.base = sub.base or page or parent.base
- return sub
- end
- --[[
- 将一个普通Lua表转换成为本节点的子节点。
- -----
- parent - 本节点。
- tab - 要被转换为本节点的子节点的普通Lua表。
- page - 定义这个节点的页面,应当是你在书写这个代码时所处的模块名页面全名。若为非空值,则将覆盖参数parent的继承。
- -----
- 返回:转换后的节点。
- --]]
- function mps.parse(parent, tab, page)
- if type(parent) == "nil" then mps.util.error(mw.ustring.format("在parse中参数parent的值类型错误。(应为%s,实际为%s)", "table", type(parent)), mps.util.ELID_FATAL) end
- if type(tab) ~= "table" then mps.util.error(mw.ustring.format("在parse中参数tab的值类型错误。(应为%s,实际为%s)", "table", type(tab)), mps.util.ELID_FATAL) end
- if page ~= nil and type(page) ~= "string" then mps.util.error(mw.ustring.format("参数page的值类型错误。(应为%s,实际为%s)", "nil或string", type(page)), mps.util.ELID_FATAL) end
- local node = mps.create(page or parent.base)
- for _name, _node in pairs(tab) do
- if type(_node) == "table" then
- -- 递归转换Lua表中的节点
- mps.registerSubpage(node, _name, _node)
- elseif type(_node) == "string" then
- -- 默认转换为纯文本节点。
- mps.registerPlain(node, _name, _node)
- end
- end
- return node
- end
- return mps