モジュール:系統図
表示
モジュールの解説[作成]
local max=0
local function measure(node)
local h=0
if #node.sub~=0 then
for _,subnode in ipairs(node.sub) do
h=h+subnode.height
end
else
h=1
end
node.height=h
end
local function paint(node,data,x,y)
if #node.text~=0 then
if x~=0 then
table.insert(data[2],{x=x,y=2*y+node.height})
x=x+1
end
table.insert(data[1],{x=x,y=2*y+node.height,text=node.text,type=mw.title.getCurrentTitle().text==node.text and 1 or (mw.title.new(node.text,0).exists and 0 or 2)})
x=x+#node.text/3+1
end
if #node.sub>0 then
table.insert(data[2],{x=x,y=2*y+node.height})
x=x+1
if #node.sub~=1 then
table.insert(data[3],{x=x,y=2*y+node.sub[1].height,h=2*node.height-(node.sub[#node.sub].height+node.sub[1].height)})
end
for _,subnode in ipairs(node.sub) do
paint(subnode,data,x,y)
y=y+subnode.height
end
end
if max<x then
max=x
end
end
local function create(args)
local root=nil
local stack={}
for line in string.gmatch(mw.text.trim(args[2]),"[^\n]+") do
local t=string.gsub(line, "^%s*(.-)%s*$", "%1")
if(#t~=0) then
if(t:match("{$")) then
local node={text=string.sub(t,1,-2),sub={}}
if(#stack==0) then
root=node
else
table.insert(stack[#stack].sub,node)
end
table.insert(stack,node)
elseif(t=="}") then
measure(stack[#stack])
table.remove(stack)
else
local node={text=t,sub={}}
measure(node)
table.insert(stack[#stack].sub,node)
end
end
end
local data={{},{},{}}
paint(root,data,0,0)
return{
width=max*16+16,
height=root.height*32+16,
signals={
{
name="o",
init=nil,
streams={
{
type="rect:click",
expr="datum.type==1?null:open('https://ja-two.iwiki.icu/wiki/'+datum.text)"
}
}
}
},
data={
{
name="text",
values=data[1]
},
{
name="h",
values=data[2]
},
{
name="v",
values=data[3]
}
},
marks={
{
type="rect",
from={
data="v"
},
properties={
enter={
x={
field="x",
mult=16,
offset=7
},
y={
field="y",
mult=16,
offset=7
},
width={
value=2
},
height={
field="h",
mult=16,
offset=2
},
fill={
value="#88c"
}
}
}
},
{
type="rect",
from={
data="h"
},
properties={
enter={
x={
field="x",
mult=16,
offset=7
},
y={
field="y",
mult=16,
offset=7
},
width={
value=18
},
height={
value=2
},
fill={
value="#88c"
}
}
}
},
{
type="rect",
from={
data="text",
transform={
{
type="formula",
field="w",
expr="length(datum.text)+1"
}
}
},
properties={
enter={
x={
field="x",
mult=16,
offset=8
},
y={
field="y",
mult=16,
offset=-4
},
width={
field="w",
mult=16
},
height={
value=24
},
fill={
value="#eef"
},
strokeWidth={
value=2
},
stroke={
value="#88c"
},
cursor={
{
test="datum.type==1",
value="default"
},
{
value="pointer"
}
}
}
}
},
{
type="text",
interactive=false,
from={
data="text"
},
properties={
enter={
text={
field="text"
},
x={
field="x",
mult=16,
offset=16
},
y={
field="y",
mult=16,
offset=8
},
fill={
{
test="datum.type==2",
value="#600"
},
{
test="datum.type==1",
value="black"
},
{
value="#006"
}
},
fontWeight={
{
test="datum.type==1",
value="bold"
},
{
value="normal"
}
},
fontSize={
value=16
},
baseline={
value="middle"
},
font={
value="TakaoGothic"
}
}
}
}
}
}
end
return {
_=function(frame)
return frame:extensionTag('graph',mw.text.jsonEncode(create(frame:getParent().args)),{mode='interactive'})
end
}