Module:UtilsSchema

local p = {} local h = {}

local utilsMarkup = require("Module:UtilsMarkup") local utilsTable = require("Module:UtilsTable")

local SYMBOLS = { optional = "[%s]", required = "%s!", array = "{%s}", oneOf = "%s|%s", default = "%s=%s", }

function p.getTypeDefinitions(schemaName, schema) schema = h.resolveReferences(schema, h.collectReferences(schema)) local definitions = h.getTypeDoc(schemaName, schema) local definitionsList = utilsMarkup.definitionList({definitions}) return definitionsList end

function h.collectReferences(schema, references) references = references or {} h.walkSchema(function(schemaNode)		if schemaNode._id then			references[schemaNode._id] = schemaNode		end	end, schema) return references end

function h.resolveReferences(schema, references) h.walkSchema(function(schemaNode)		if schemaNode._ref then			local resolvedSchema = utilsTable.merge({}, references[schemaNode._ref], schemaNode)			utilsTable.merge(schemaNode, resolvedSchema)			schemaNode._ref = nil		end	end, schema) return schema end

function h.walkSchema(fn, schema) fn(schema) if schema.items then h.walkSchema(fn, schema.items) end if schema.properties then for i, v in ipairs(schema.properties) do			h.walkSchema(fn, v)		end end if schema.oneOf then for i, v in ipairs(schema.oneOf) do			h.walkSchema(fn, v)		end end end

function h.getTypeDoc(schemaName, schema, parentSchema) local type = schema.type local isSubtype = parentSchema and (parentSchema.type == "array" or parentSchema.oneOf) local definitions = {} if type == "record" then for _, prop in ipairs(schema.properties) do			local propDefs = h.getTypeDoc(prop.name, prop, schema) table.insert(definitions, {propDefs}) end elseif type == "array" then definitions, subtype, subtypeInfo = h.getTypeDoc(schemaName, schema.items, schema) type = string.format(SYMBOLS.array, subtype) elseif schema.oneOf then local subtypes = {} for i, subschema in ipairs(schema.oneOf) do			local subdefs, subtype, subtypeInfo = h.getTypeDoc(nil, subschema, schema) table.insert(definitions, {subdefs}) if i == 1 then type = subtype else type = string.format(SYMBOLS.oneOf, type, subtype) end end end if schema.desc then table.insert(definitions, 1, schema.desc) end if isSubtype then table.insert(definitions, 1, "") return definitions, type end local definitionKey = schemaName if schema.default then definitionKey = string.format(SYMBOLS.default, schemaName, schema.default) end if schema.required then type = string.format(SYMBOLS.required, type) else type = string.format(SYMBOLS.optional, type) definitionKey = string.format(SYMBOLS.optional, definitionKey) end definitionKey = utilsMarkup.code(definitionKey) local formattedType = utilsMarkup.code(type) definitionKey = utilsMarkup.explain(formattedType)(definitionKey) table.insert(definitions, 1, definitionKey) return definitions, type end

return p