generate-config-doc.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. const fs = require('fs')
  2. const path = require('path')
  3. const schema = JSON.parse(
  4. fs.readFileSync('tooling/cli.rs/schema.json').toString()
  5. )
  6. const templatePath = path.join(__dirname, '../../docs/.templates/config.md')
  7. const targetPath = path.join(__dirname, '../../docs/api/config.md')
  8. const template = fs.readFileSync(templatePath, 'utf8')
  9. function formatDescription(description) {
  10. return description
  11. ? description
  12. .replace(/`/g, '\\`')
  13. .replace(/\n/g, ' ')
  14. .replace(/ /g, ' ')
  15. .replace(/{/g, '\\{')
  16. .replace(/}/g, '\\}')
  17. : ''
  18. }
  19. function generatePropertiesEl(schema, anchorRoot, definition, tab) {
  20. const previousTabLevel = tab.replace(' ', '')
  21. const fields = [`anchorRoot="${anchorRoot}"`]
  22. if (definition.additionalProperties) {
  23. fields.push(`type="${definition.type}"`)
  24. fields.push(`description="${formatDescription(definition.description)}"`)
  25. }
  26. const rows = []
  27. for (const propertyName in definition.properties) {
  28. const property = definition.properties[propertyName]
  29. if ('type' in property) {
  30. let type
  31. if ('items' in property) {
  32. if (property.items.type) {
  33. type = `${property.items.type}[]`
  34. } else {
  35. const typeName = property.items.$ref.replace('#/definitions/', '')
  36. const propDefinition = schema.definitions[typeName]
  37. const propertyEl = generatePropertiesEl(
  38. schema,
  39. `${anchorRoot}.${propertyName}`,
  40. propDefinition,
  41. `${tab} `
  42. )
  43. rows.push({
  44. property: propertyName,
  45. optional: 'default' in property || property.type.includes('null'),
  46. type: `${typeName}[]`,
  47. description: property.description,
  48. child: `<Array type="${typeName}">\n${tab}${propertyEl}\n${previousTabLevel}</Array>`
  49. })
  50. continue
  51. }
  52. } else if (Array.isArray(property.type)) {
  53. type = property.type.join(' | ')
  54. } else {
  55. type = property.type
  56. }
  57. rows.push({
  58. property: propertyName,
  59. optional: true,
  60. type,
  61. description: property.description,
  62. default: property.default
  63. })
  64. } else if ('anyOf' in property) {
  65. const subType = property.anyOf[0].$ref.replace('#/definitions/', '')
  66. const propDefinition = schema.definitions[subType]
  67. const propertyEl = generatePropertiesEl(
  68. schema,
  69. `${anchorRoot}.${propertyName}`,
  70. propDefinition,
  71. `${tab} `
  72. )
  73. rows.push({
  74. property: propertyName,
  75. optional:
  76. property.anyOf.length > 1 && property.anyOf[1].type === 'null',
  77. type: subType,
  78. description: property.description,
  79. child: propertyEl
  80. })
  81. } else if ('allOf' in property) {
  82. const subType = property.allOf[0].$ref.replace('#/definitions/', '')
  83. const propDefinition = schema.definitions[subType]
  84. const propertyEl = propDefinition.properties
  85. ? generatePropertiesEl(
  86. schema,
  87. `${anchorRoot}.${propertyName}`,
  88. propDefinition,
  89. `${tab} `
  90. )
  91. : undefined
  92. rows.push({
  93. property: propertyName,
  94. optional: 'default' in property,
  95. type: property.type || subType,
  96. description: property.description,
  97. child: propertyEl
  98. })
  99. }
  100. }
  101. if (rows.length > 0) {
  102. const serializedRows = rows
  103. .map((row) => {
  104. const fields = [
  105. `property: "${row.property}"`,
  106. `optional: ${row.optional}`,
  107. `type: "${row.type}"`,
  108. `description: \`${formatDescription(row.description)}\``
  109. ]
  110. if (row.child) {
  111. fields.push(`child: ${row.child}`)
  112. }
  113. return `{ ${fields.join(', ')} },`
  114. })
  115. .join(`\n${tab}`)
  116. fields.push(`rows={[\n${tab}${serializedRows}\n${previousTabLevel}]}`)
  117. } else {
  118. fields.push('rows={[]}')
  119. }
  120. return `<Properties ${fields.join(' ')}/>`
  121. }
  122. const output = []
  123. for (const propertyName in schema.properties) {
  124. const property = schema.properties[propertyName]
  125. const definitionName = property.allOf[0].$ref.replace('#/definitions/', '')
  126. const definition = schema.definitions[definitionName]
  127. let contents = `## \`${propertyName}\`\n\n${generatePropertiesEl(
  128. schema,
  129. propertyName,
  130. definition,
  131. ' '
  132. )}`
  133. output.push(contents)
  134. }
  135. fs.writeFileSync(
  136. targetPath,
  137. template.replace('{properties}', output.join('\n\n'))
  138. )