Module:扩展时间线
跳到导航
跳到搜索
local module = {} local getArgs = require('Module:Arguments').getArgs local timeLineModule=require('Module:时间线') local timeLine=timeLineModule.timeLine local preArgs=timeLineModule.preArgs local clone=function(self)--浅表克隆 local new=setmetatable({},getmetatable(self)) for k,v in pairs(self) do new[k]=v end return new end local indexOf=function(list,item)--获得序号 for i=1,#list do if list[i]==item then return i end end end local bit32 = require( 'bit32' ) function bit32.get(bits,index)--设置index处的真值 return bit32.band(bits,bit32.lshift(1, index-1))~=0 end local textPredicate = require( 'Module:TextPredicate' ) --标记功能 local signFunction={ symbolSplit="#", collapsableDefault=true } function signFunction:_getNameList(text) local names=mw.text.split(text,self.symbolSplit) local values={} for index,name in ipairs(names) do if name:sub(1,1)=="-" then values[name]=false names[index]=name:sub(2) else values[name]=true end end return names,values end function signFunction:_getPattern(text) local tab={} for text in mw.text.gsplit(text,self.symbolSplit) do local b,e=text:find(":") assert(b,"auto参数不合法") local name=text:sub(1,b-1) if not tab[name] then tab[name]={text:sub(e+1)} else table.insert(tab[name],text:sub(e+1)) end end return tab end function signFunction:init(tab,args) self.__index = self local result=setmetatable(tab or {},self) if result.var then signFunction.var_array=signFunction.var_array or require('Module:Var-array') result.var=result.var=="all" and {} or mw.text.split(result.var,result.symbolSplit) result.preLoad=signFunction.preLoad_var result.preFormat=signFunction.preFormat_var end if result.collapsable then if result.collapsable=="all" then self.collapsableDefault=true result.collapsableValues={} elseif result.collapsable=="allnot" then self.collapsableDefault=false result.collapsableValues={} else result.collapsable,result.collapsableValues=result:_getNameList(result.collapsable) end result.formatNode=signFunction.formatNode_collapsible end if result.auto then result.auto=result:_getPattern(result.auto) result.analysisText=signFunction.analysisText_auto end return result end function signFunction:preLoad_var() self.tabs={} self.signs=signFunction.var_array.get("module.timeLine.ex.signs") or {} self.predicates={} for index,valueText in ipairs(self.signs) do local predicate=textPredicate.createText(valueText) if #self.var==0 or not predicate:limitTo(self.var):isReal() then self.predicates[index]=predicate self.tabs[index]={ texts =signFunction.var_array.get("module.timeLine.ex.texts."..valueText), times =signFunction.var_array.get("module.timeLine.ex.times."..valueText), } --mw.log("load",valueText,#self.tabs[index].texts,#self.tabs[index].times) else self.predicates[index]=false end end return self.tabs end function signFunction:preLoad() if self.var then self:preLoad_var() end end function signFunction.preArgs_step(self,state)--time,text,sign state.index=state.index+1 if state.mIndex then if state.index>#state.tab.texts then state.mIndex,state.tab=next(self.tabs,state.mIndex) if not state.mIndex then return nil end state.predicate=self.predicates[state.mIndex] --mw.log("state",state.mIndex,#state.tab) state.index=1 end else return nil end return state,state.tab.times[state.index],state.tab.texts[state.index],state.predicate end function signFunction:preArgs()--读取输入组 local state={ index=0 } state.mIndex,state.tab=next(self.tabs) state.predicate=self.predicates[state.mIndex] --mw.log("state",state.mIndex,state.mIndex and self.predicates[state.mIndex],state.tab and #state.tab.texts) return signFunction.preArgs_step,self,state end function signFunction:analysisText_base(originText) if not originText or originText=="" then return nil,nil end local b,e=originText:find(self.symbolBegin)--作为开端 if not b then return nil,originText end result=textPredicate.createExpress(originText:sub(e+1)) local other=originText:sub(1,b-1) return result,other end function signFunction:analysisText(originText) local result,other=self:analysisText_base(originText) return result or textPredicate._true,other end function signFunction:analysisText_auto(originText) local result,other=signFunction.analysisText_base(self,originText) if not other then return result or textPredicate._true,other end result=result or textPredicate.base() for name,tab in pairs(self.auto) do for _,pattern in ipairs(tab) do if other and other:find(pattern) then result:addExpress(name) end end end if result:isReal(false) then result=textPredicate._true end --mw.log(result) return result,other end function signFunction:formatNode(node,predicate) return node end function signFunction:formatNode_collapsible(nodeIn,predicate) --mw.log(predicate,nodeIn) if #self.collapsable>0 then predicate=predicate:limitTo(self.collapsable) --mw.log("--",predicate) if predicate:isReal() then return nodeIn end--elseif predicate:isReal(false) then end local nodeMain= mw.html.create() --mw.log("-->"..tostring(nodeIn)) for valuebits in predicate:gAllowValues() do --mw.log(node,"--|>",nodeIn) local node=nodeMain for index,name in ipairs(predicate.list) do node= node :tag("div") :addClass("mw-collapsible") :attr("id", "mw-customcollapsible-"..name) local value=self.collapsableValues[name] or self.collapsableDefault if not bit32.get(valuebits,index) then value=not value end if not value then node:addClass("mw-collapsed") end end node:node(nodeIn) end return nodeMain end function signFunction:preFormat() end function signFunction:_varAdd(timeText,text,predicate) local index=indexOf(self.predicates,predicate) local tabs if index then tabs=self.tabs[index] --mw.log("add",self.signs[index],timeText,text) for index,t in ipairs(tabs.texts) do if timeText==tabs.times[index] and text==t then return end end else tabs={times={},texts={}} local main_index=#self.signs+1 local valueText=predicate:valueText() self.signs[main_index]=valueText self.predicates[main_index]=predicate self.tabs[main_index]=tabs --mw.log("add",valueText,timeText,text) end local index=#tabs.texts+1 tabs.times[index]=timeText tabs.texts[index]=text end function signFunction:preFormat_var(time,text,predicate) if #self.var>0 then predicate=predicate:limitTo(self.var) --mw.log("--",predicate) if predicate:isReal() then return end--elseif predicate:isReal(false) then end self:_varAdd(tostring(time),text,predicate) end function signFunction:calculate_var() if #self.signs==0 then return end signFunction.var_array.new("module.timeLine.ex.signs",self.signs) --mw.log("saveCount",#self.signs) for index,tabs in pairs(self.tabs) do --mw.log("save",self.signs[index],#tabs.texts,#tabs.times) signFunction.var_array.new("module.timeLine.ex.texts."..self.signs[index],tabs.texts) signFunction.var_array.new("module.timeLine.ex.times."..self.signs[index],tabs.times) end end function signFunction:calculate() if self.var then self:calculate_var() end end --带标记时间文本 local timeLineModify=timeLine.base()--继承时间线 function timeLineModify.base(args) return setmetatable(args or {},timeLineModify) end timeLineModify.old_title=timeLine.title function timeLineModify.title(titleLevel) local this=timeLineModify.old_title(titleLevel) this.sign=textPredicate._true return timeLineModify.base(this) end timeLine.title=timeLineModify.title timeLineModify.__index = timeLineModify function timeLineModify.root() local root=timeLineModify.base(timeLine.root()) root.sign=textPredicate._true root.mark="root" timeLineModify.signFunction:preLoad() if timeLineModify.signFunction.var then for _,timeText,text,sign in timeLineModify.signFunction:preArgs() do root:insert(timeLineModify.load(timeText,text,sign)) end end return root end function timeLineModify.load(timeText,text,sign) local line=timeLineModify.base{time=timeLine.getTime(timeText),text=text,sign=sign} return line end function timeLineModify.create(withTimeText,parent)--带时间文本时间数字化·文本化函数 local this=timeLine.create(withTimeText) if not this then return end this.sign,this.text=timeLineModify.signFunction:analysisText(this.text) this=timeLineModify.base(this) if parent then parent:insert(this) end --mw.log(this.sign,this.text,this.timeRange) return this end function timeLineModify:sub(other)--执行减去折叠显示部分操作,返回剩余的显示与被剪掉的显示 local fs,ss=self.sign,other.sign fs,ss=fs:_sub(ss) if not ss:isReal(false) then local other=clone(self) self.sign=fs other.sign=ss return other end end function timeLineModify:testText() local t={"timeLineModify",tostring(self.sign),"time:"..tostring(self.time),"text:"..tostring(self.text)} return table.concat(t,";") end function timeLineModify:move(otherLine,b,e)--辅助函数,转移数据。重写 while e>=b do--转移数据删除 local left=otherLine:insert(self[e]) --mw.log("转移数据",self[e]:testText(),"到",otherLine:testText(),"剩余",left and left:testText()) if left then self[e]=left else table.remove(self,e) end e=e-1 end end function timeLineModify:insert(newLine)--插入时间函数 case相当于不同空间定位,需要被拆分进各个时段中。一次置入将把空间被包含部分置入,返回剩余部分 if not newLine then return end local other=newLine:sub(self) if other then --mw.log("_insert",other:testText()) timeLine.insert(self,other)--被剪掉的部分即从属的部分,应当插入其中 end if not newLine.sign:isReal(false) then --mw.log("last",newLine:testText()) return newLine--剩余部分返回,继续插入 end end function timeLineModify:insertText(originText)--插入文本 重写 if originText==nil or originText=="" then return end return timeLineModify.create(originText,self) end function timeLineModify:getTimeText() return timeLine.format:timeToText(self.time,self.parent and self.parent.time) end function timeLineModify:toNode(parent)--转换为html的node local node if self.titleLevel then--标题特殊处理 node=mw.html.create() if self.time then-- and self.titleLevel>0 timeLineModify.signFunction:preFormat(self.time,self.text,self.sign) local timeText=self:getTimeText() local title=timeLineModify.signFunction:formatNode(self.text and timeText..self.text or timeText,self.sign) node:node(module.makeTitle(title,self.titleLevel)) parent:node(node) end else timeLineModify.signFunction:preFormat(self.time,self.text,self.sign) local timeText=self:getTimeText() node=mw.html.create() local li=timeLineModify.signFunction:formatNode(module.makeLi(timeText,self.text or ""),self.sign) node:node(li) if not parent.ul then parent.ul=parent:tag("ul") end parent.ul:node(node) end for _,child in ipairs(self) do child:toNode(node) end return node end function timeLineModify:__tostring() local text=self:toNode():done() timeLineModify.signFunction:calculate() return text end --主函数 function module.argsSet(args)--设置参数 module.collapsable_default={} module.showIndex=((args.index or args.i or args["显示目录"])~="false") if module.showIndex then module.makeTitle=function(node,level) return mw.html.create("h"..level):node(node) end else local t={"130%","120%","110%"} module.makeTitle=function(node,level) return mw.html.create("b"):tag("font"):css("font-size",t[level]):node(node) end end local symbolBegin="##" local symbolOr="#" local symbolAnd="&" local symbolNot="-" textPredicate.symbolOr=symbolOr textPredicate.symbolAnd=symbolAnd textPredicate.symbolNot=symbolNot local tts=args["time-textsplit"] or args.tts or args["时间-文本分割符"] or "," local cw=args.columnwidth or args.cw or args["间隔宽度"] or "120px" if cw~="none" then module.makeLi=function(timeText,text) local node=mw.html.create("li") local div=node:tag("div"):css("display","flex") div:tag("span") :css("flex-shrink","0") :css("flex-basis",cw) :wikitext(timeText) div:tag("span"):wikitext(text) return node end module.makeLiSimple=function(text) local index=text:find(tts) return module.makeLi(text:sub(1,index-1),text:sub(index+1)) end else module.makeLiSimple=function(text) return mw.html.create("li"):wikitext(text) end module.makeLi=function(parent,timeText,text) return module.makeLiSimple(parent,timeText..tts..text) end end local signFunction=signFunction:init{ symbolBegin =symbolBegin, symbolSplit =symbolOr, collapsable =args.collapsable or args.clps or args["折叠标签"] , var =args.var or args["传递标签"], auto =args.auto or args["自动标签"], } timeLineModify.signFunction=signFunction args.afterrange=args.afterrange or args.ar or args["时段后符"] or ""--更改默认值 args.prerange=args.prerange or args.pr or args["时段前符"] or "" args.bullet=args.bullet or args.b or args["项目符号"] or "\*" --args.timeTitle=args.timeTitle or args.tt or args["时间标题符"] or "" timeLineModule.argsSet(args) end function module.timeLineToText(args)--时间排序模式 timeLine.format.title="" local root=timeLineModify.root() for _,sentence in preArgs(args) do root:insertText(sentence) end return tostring(root:sort()) end function module._simple(args) local bullet=args.bullet or args.b or args["项目符号"] or "\*" local level="^"..bullet.."*" local timeTextSplit=args["time-textsplit"] or args.tts or args["时间-文本分割符"] or "," local timeTitle=args.timetitle or args.tt or args["时间标题符"] or "=" args.bullet="" local time={} function time.create(withTimeText) local b,e=withTimeText:find(level) e=e+1 local level=e-b local b1,i=withTimeText:find(timeTextSplit,e) if not b1 then b1,i=withTimeText:find(timeTitle,e) if not b1 then return nil,i or 1 end end --mw.log(withTimeText:sub(i+1),withTimeText:sub(e,b1-1)) return setmetatable({ level=level, text=withTimeText:sub(e,b1-1) },time),i+1 end time.__index=time function time:supply() return self end time.compare={--时间比较结果常数 before=1,--完全在之前 equal=2,--相同 after=3,--完全在之后 include=4,--包含 inside=5,--被包含 conflict=6,--冲突 } time.compare=setmetatable(time.compare,{--时间比较,理论上只允许发生在同精确度的时间上。 __call=function(self,time1,time2) if not time2 then --mw.log(time1.text) return self.equal end if time1.level<time2.level then return self.include elseif time1.level>time2.level then return self.inside elseif time1.level==time2.level then return self.equal end end }) function time:supply() end function time:__tostring() return self.text end local timeModule={ time=time, toTime=time.create, } function timeLineModule.timeModule() return timeModule end module.argsSet(args) function timeLineModify.timeSupply() end function timeLineModify:sort() return self end function timeLineModify:getTimeText() return tostring(self.time) end return module.timeLineToText(args) end function module._main(args, frame)--主函数 local sortArgs=args["排列参数"] or args.sortargs or args.sort--使用timeLine排序参数,需要配合subst使用 if sortArgs then--返回一个sortArgs外参数相同的扩展时间线模板 if sortArgs=="once" then--排列参数一次 return timeLineModule.sortArgsSubst(args,"扩展时间线",nil) elseif sortArgs=="true" then--排列参数并返回false return timeLineModule.sortArgsSubst(args,"扩展时间线","false") --elseif sortArgs=="simple" then--简单分析模式,支持var等 --args.analysis=args.pattern or args["格式化字符串"] or "%Y%M%(Mi)%D%(Di)%H%I%S" --return timeLineModule.sortArgsSubst(args,"扩展时间线","false") elseif sortArgs=="false" then--禁用排列,使用level方式,不支持var输入 return module._simple(args) end else--正常模式 module.argsSet(args) return module.timeLineToText(args) end end function module.main(frame)--主函数 local args = getArgs(frame) return module._main(args, frame) end return module