const fs = require('fs')
const path = require('path')
const schema = JSON.parse(fs.readFileSync('tooling/cli.rs/schema.json').toString())
const templatePath = path.join(__dirname, '../../docs/.templates/config.md')
const targetPath = path.join(__dirname, '../../docs/api/config.md')
const template = fs.readFileSync(templatePath, 'utf8')
function formatDescription(description) {
return description ?
description
.replace(/`/g, '\\`')
.replace(/\n/g, ' ')
.replace(/ /g, ' ')
.replace(/{/g, '\\{')
.replace(/}/g, '\\}') :
''
}
function generatePropertiesEl(schema, anchorRoot, definition, tab) {
const previousTabLevel = tab.replace(' ', '')
const fields = [`anchorRoot="${anchorRoot}"`]
if (definition.additionalProperties) {
fields.push(`type="${definition.type}"`)
fields.push(`description="${formatDescription(definition.description)}"`)
}
const rows = []
for (const propertyName in definition.properties) {
const property = definition.properties[propertyName]
if ('type' in property) {
let type
if ('items' in property) {
if (property.items.type) {
type = `${property.items.type}[]`
} else {
const typeName = property.items.$ref.replace('#/definitions/', '')
const propDefinition = schema.definitions[typeName]
const propertyEl = generatePropertiesEl(schema, `${anchorRoot}.${propertyName}`, propDefinition, `${tab} `)
rows.push({
property: propertyName,
optional: ('default' in property) || property.type.includes('null'),
type: `${typeName}[]`,
description: property.description,
child: `\n${tab}${propertyEl}\n${previousTabLevel}`
})
continue
}
} else if (Array.isArray(property.type)) {
type = property.type.join(' | ')
} else {
type = property.type
}
rows.push({
property: propertyName,
optional: true,
type,
description: property.description,
default: property.default
})
} else if ('anyOf' in property) {
const subType = property.anyOf[0].$ref.replace('#/definitions/', '')
const propDefinition = schema.definitions[subType]
const propertyEl = generatePropertiesEl(schema, `${anchorRoot}.${propertyName}`, propDefinition, `${tab} `)
rows.push({
property: propertyName,
optional: property.anyOf.length > 1 && property.anyOf[1].type === 'null',
type: subType,
description: property.description,
child: propertyEl
})
} else if ('allOf' in property) {
const subType = property.allOf[0].$ref.replace('#/definitions/', '')
const propDefinition = schema.definitions[subType]
const propertyEl = propDefinition.properties ? generatePropertiesEl(schema, `${anchorRoot}.${propertyName}`, propDefinition, `${tab} `) : undefined
rows.push({
property: propertyName,
optional: 'default' in property,
type: property.type || subType,
description: property.description,
child: propertyEl
})
}
}
if (rows.length > 0) {
const serializedRows = rows
.map(row => {
const fields = [`property: "${row.property}"`, `optional: ${row.optional}`, `type: "${row.type}"`, `description: \`${formatDescription(row.description)}\``]
if (row.child) {
fields.push(`child: ${row.child}`)
}
return `{ ${fields.join(', ')} },`
})
.join(`\n${tab}`)
fields.push(`rows={[\n${tab}${serializedRows}\n${previousTabLevel}]}`)
} else {
fields.push('rows={[]}')
}
return ``
}
const output = []
for (const propertyName in schema.properties) {
const property = schema.properties[propertyName]
const definitionName = property.allOf[0].$ref.replace('#/definitions/', '')
const definition = schema.definitions[definitionName]
let contents = `## \`${propertyName}\`\n\n${generatePropertiesEl(schema, propertyName, definition, ' ')}`
output.push(contents)
}
fs.writeFileSync(targetPath, template.replace('{properties}', output.join('\n\n')))