Module:JSONPageList
Module documentation
[create]
-- Demo for T332484
require( 'strict' )
local r={}
--local lang="en"
local site="enwiki"
local siteprefix="en:"
local function get_link(qid, label)
local sitelink=mw.wikibase.getSitelink(qid,site)
label=label or mw.wikibase.getLabel(qid)
if sitelink then
return '[[:'..siteprefix..sitelink..'|'..label..']]'
else
return '[[d:'..qid..'|'..label..']]'
end
end
local function get_heading(field)
if field:match(":(.*)$") then
return field:match(":(.*)$")
elseif field=='@link' then
return 'item'
elseif field:sub(1,1)=='$' then
local entity_id=field:sub(2):match("([PQpq]%d+)$")
return mw.wikibase.getLabel(entity_id)
else
return field
end
end
local function get_cell(field, item, data_fields_map, raw)
if field:match("(.*):.*$") then
field=field:match("(.*):.*$")
end
local qid=item._qid
if field=='@qid' then
return qid or ''
elseif field=='@link' then
if qid and not item._page then
return get_link(qid, item._name)
else
return '[[:'..siteprefix..(item._page or item._name)..'|'..item._name..']]'
end
elseif field=='@description' then
return mw.wikibase.getDescription(qid)
elseif field:sub(1,1)=='$' then
local entity_path=field:sub(2)
if entity_path:match("^([Pp]%d+)$") then
return mw.getCurrentFrame():callParserFunction("#statements",{entity_path, from=qid})
elseif entity_path:match("^([Pp]%d+)/([Qq]%d+)/([Pp]%d+)$") then
local pid, qid2, pid2=entity_path:match("^([PQpq]%d+)/([PQpq]%d+)/([PQpq]%d+)$")
local vals=mw.wikibase.getBestStatements(qid, pid)
for _, v in ipairs(vals) do
if v.mainsnak.datavalue.value and v.mainsnak.datavalue.value.id==qid2 and v.qualifiers and v.qualifiers[pid2] then
return mw.wikibase.formatValues(v.qualifiers[pid2])
end
end
end
else
if item[field] then
return tostring(item[field])
elseif qid and data_fields_map[field] and data_fields_map[field].property then
local vals=mw.wikibase.getBestStatements(qid, data_fields_map[field].property)
if data_fields_map[field].enum_map and vals and vals[1] and vals[1].mainsnak.datavalue.value and data_fields_map[field].enum_map[vals[1].mainsnak.datavalue.value.id] then
return tostring(data_fields_map[field].enum_map[vals[1].mainsnak.datavalue.value.id])
end
end
if data_fields_map[field] and data_fields_map[field].default then
return tostring(data_fields_map[field].default)
end
end
return '...'
end
local function parse_params(pagename, result_fields, params)
if type(pagename) == "table" then
pagename, result_fields, params = pagename.args[1], pagename.args[2], pagename
end
if params:getParent() and params:getParent().args[1] then
pagename, result_fields, params = params:getParent().args[1], params:getParent().args[2], params:getParent()
end
params=params.args
return pagename, result_fields, params
end
local function get_content(pagename)
local content
if mw.title.new( pagename ).namespace==828 then
content=require(pagename)
else
content=mw.title.new(pagename):getContent()
content=mw.text.jsonDecode(content)
end
return content
end
local function set_site(content)
site=content.site or site
siteprefix=content.siteprefix or siteprefix
end
local function get_fields_and_items(content)
local data_fields=content.fields or {}
local data_fields_map={}
for _, v in ipairs( data_fields ) do
if type(v)=="table" then
data_fields_map[v[1]]=v
end
if v.enum then
v.enum_map={}
for _, p in ipairs( v.enum ) do
if type(p)=='table' then
v.enum_map[p[2]]=p[1]
end
end
end
end
local items=content.items
for i, v in ipairs( items ) do
if type(v) == "string" then
items[i]={_qid=v}
end
end
return data_fields, data_fields_map, items
end
local function clear_csv(param_str)
if not param_str then
return {}
end
local param_val=mw.text.split(param_str,',')
local result={}
for _,v in ipairs(param_val) do
if mw.text.trim(v)~='' then
table.insert(result,mw.text.trim(v))
end
end
return result
end
local function populate_result_fields(result_fields, data_fields)
result_fields=clear_csv(result_fields)
if #result_fields==0 then
result_fields={'@link'}
for _, v in ipairs( data_fields ) do
table.insert(result_fields,v[1] .. (v.display_name and (":"..v.display_name) or ''))
end
end
return result_fields
end
local function parse_data(pagename, result_fields, params)
pagename, result_fields, params = parse_params(pagename, result_fields, params)
local content=get_content(pagename)
set_site(content)
local data_fields, data_fields_map, items=get_fields_and_items(content)
result_fields=populate_result_fields(result_fields, data_fields)
-- filter
local filter=clear_csv(params.filter)
if #filter>0 then
local filtered_items={}
for _, v in ipairs(items) do
local selected=true
for _, v2 in ipairs(filter) do
if v2:match("(.-)==(.*)") then
local l, r=v2:match("(.-)==(.*)")
if get_cell(l,v,data_fields_map)~=r then
selected=false
break
end
elseif v2:match("(.-)!=(.*)") then
local l, r=v2:match("(.-)!=(.*)")
if get_cell(l,v,data_fields_map)==r then
selected=false
break
end
elseif v2:match("(.-)>=(.*)") then
local l, r=v2:match("(.-)>=(.*)")
if get_cell(l,v,data_fields_map)<r then
selected=false
break
end
elseif v2:match("(.-)<=(.*)") then
local l, r=v2:match("(.-)<=(.*)")
if get_cell(l,v,data_fields_map)>r then
selected=false
break
end
elseif v2:match("(.-)>(.*)") then
local l, r=v2:match("(.-)>(.*)")
if get_cell(l,v,data_fields_map)<=r then
selected=false
break
end
elseif v2:match("(.-)<(.*)") then
local l, r=v2:match("(.-)<(.*)")
if get_cell(l,v,data_fields_map)>=r then
selected=false
break
end
end
end
if selected then
table.insert(filtered_items,v)
end
end
items=filtered_items
end
-- orderby
local orderby=clear_csv(params.orderby)
local function _o(i1, i2)
for _, v in ipairs(orderby) do
local v1=get_cell(v,i1,data_fields_map)
local v2=get_cell(v,i2,data_fields_map)
if v1<v2 then
return true
elseif v1>v2 then
return false
end
end
return false
end
if #orderby>0 then
table.sort(items, _o)
end
-- groupby
local groupby=clear_csv(params.groupby)
local item_groups={}
for _, v in ipairs( items ) do
local cur_node=item_groups
for _, v2 in ipairs(groupby) do
local subnode_name=get_cell(v2,v,data_fields_map)
if cur_node[subnode_name]==nil then
if cur_node._subnodes==nil then
cur_node._subnodes={}
end
table.insert(cur_node._subnodes,subnode_name)
cur_node[subnode_name]={}
end
cur_node=cur_node[subnode_name]
end
table.insert(cur_node,v)
end
return pagename, result_fields, params, content, data_fields, data_fields_map, item_groups
end
function r.table(pagename, result_fields, params)
local content, data_fields, data_fields_map, item_groups
pagename, result_fields, params, content, data_fields, data_fields_map, item_groups=parse_data(pagename, result_fields, params)
local result=mw.html.create("table"):attr( 'class', 'wikitable' )
local heading=result:tag("tr")
for i, field in ipairs( result_fields ) do
heading:tag("th"):wikitext(get_heading(field))
end
local function populate_table(node, level)
for _, item in ipairs(node) do
local row=result:tag("tr")
for _, field in ipairs( result_fields ) do
row:tag("td"):wikitext(get_cell(field,item,data_fields_map))
end
end
if node._subnodes then
for _, v in ipairs(node._subnodes) do
result:tag("tr"):tag("td"):attr("colspan",#result_fields):wikitext('\n' .. ('='):rep(level) .. v .. ('='):rep(level) .. '\n')
populate_table(node[v], level+1)
end
end
end
populate_table(item_groups, tonumber(params.level) or 2)
return tostring( result )
end
function r.plainlist(pagename, result_fields, params)
local content, data_fields, data_fields_map, item_groups
pagename, result_fields, params, content, data_fields, data_fields_map, item_groups=parse_data(pagename, result_fields, params)
local all_results={}
local function populate_plainlist(node, level)
local clear_node={}
if node[1] then
for _, v in ipairs(node) do
table.insert(clear_node,get_cell("@link",v,data_fields_map))
end
end
table.insert(all_results,table.concat(clear_node,', '))
if node._subnodes then
for _, v in ipairs(node._subnodes) do
table.insert(all_results,('='):rep(level) .. v .. ('='):rep(level))
populate_plainlist(node[v], level+1)
end
end
end
populate_plainlist(item_groups, tonumber(params.level) or 2)
return table.concat(all_results,'\n')
end
function r.navbox(pagename, result_fields, params)
local content, data_fields, data_fields_map, item_groups
pagename, result_fields, params, content, data_fields, data_fields_map, item_groups=parse_data(pagename, result_fields, params)
local navbox_mod=require('Module:Navbox')
local function populate_navbox(node, primary)
local clear_node={}
local result
if node[1] then
for _, v in ipairs(node) do
table.insert(clear_node,'* '..get_cell("@link",v,data_fields_map)..'\n')
end
result=table.concat(clear_node)
end
if node._subnodes then
result={list1=result}
local n=result.list1 and 1 or 0
for _, v in ipairs(node._subnodes) do
n=n+1
result['group'..n]=v
local sub_result=populate_navbox(node[v])
if type(sub_result)=='table' then
sub_result[1]='child'
result['list'..n]=navbox_mod._navbox(sub_result)
else
result['list'..n]=sub_result
end
end
return result
else
return result or ''
end
end
local result=populate_navbox(item_groups)
if type(result)=='string' then
result={list1=result}
end
result.title='Navbox'
result.listclass='hlist'
return navbox_mod._navbox(result)
end
return r