-
Notifications
You must be signed in to change notification settings - Fork 132
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from TheJuanAndOnly99/issue-1068
Issue 1068
- Loading branch information
Showing
2 changed files
with
236 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,231 @@ | ||
const fs = require('fs-extra'); | ||
const yaml = require('js-yaml'); | ||
const path = require('path'); | ||
|
||
function processProperty(propertyName, propertyDetails, schemaExamples) { | ||
let markdownContent = ''; | ||
|
||
if (propertyName === 'type') { | ||
markdownContent += `### ${'Type'|| propertyName}\n\n`; | ||
markdownContent += `\`${propertyDetails.const}\`\n\n`; | ||
} else { | ||
markdownContent += `### ${propertyDetails.title || propertyName}\n\n`; | ||
markdownContent += `\`${propertyName}\`\n\n`; | ||
|
||
if (propertyDetails.description != null) { | ||
markdownContent += `${escape(propertyDetails.description)}\n\n`; | ||
} | ||
|
||
if (propertyDetails.type) { | ||
markdownContent += `**Type**: ${propertyDetails.type}\n\n`; | ||
} else { | ||
const contextRef = propertyDetails.properties?.context?.$ref || propertyDetails.$ref; | ||
|
||
if (contextRef) { | ||
markdownContent += renderRef(contextRef); | ||
} | ||
} | ||
|
||
if (propertyDetails.enum) { | ||
markdownContent += `Possible values: ${propertyDetails.enum.join(', ')}\n\n`; | ||
} | ||
|
||
if (propertyDetails.allOf) { | ||
markdownContent += `${propertyDetails.allOf.map((item) => renderRef(item.$ref)).join(', ')}\n\n`; | ||
} | ||
|
||
if (schemaExamples) { | ||
const example = schemaExamples[0]; | ||
|
||
if (typeof example[propertyName] === 'object') { | ||
markdownContent += `**Example Value**: \n\`\`\`json\n${JSON.stringify(example[propertyName], null, 2)}\n\`\`\`\n\n`; | ||
} else if (example[propertyName]) { | ||
markdownContent += `**Example Value**: \`'${example[propertyName]}'\`\n\n`; | ||
} | ||
} | ||
} | ||
return markdownContent; | ||
} | ||
|
||
function renderRef(contextRef) { | ||
const filePath = contextRef.split('#')[0]; // ../api/api.schema.json | ||
const objectType = filePath.split('/').pop().split('.')[0]; // api | ||
|
||
// FROM ../api/api.schema.json#/definitions/AppIdentifier | ||
// TO ../api/schemas/Appidentifier | ||
|
||
// FROM timerange.schema.json# | ||
// TO timerange/schemas/timerange | ||
|
||
const objectPath = contextRef.split('#')[1]; // /definitions/AppIdentifier | ||
let objectName = objectType; | ||
if (objectPath) { | ||
objectName = objectPath.split('/').pop(); // AppIdentifier | ||
} | ||
|
||
let objectRef = objectName; | ||
if (filePath.startsWith('../')) { | ||
objectRef = "../../" + objectType + "/schemas/" + objectName; | ||
} | ||
|
||
console.log('from contextRef:', contextRef, 'to objectRef:', objectRef); | ||
|
||
return `**Reference**: [${objectType}/${objectName}](${objectRef})\n\n`; | ||
} | ||
|
||
function hasAllOf(allOfArray) { | ||
return Array.isArray(allOfArray) && | ||
allOfArray.length > 0 && | ||
allOfArray[0] != null && | ||
allOfArray[0].properties != null | ||
} | ||
|
||
function hasProperties(schema) { | ||
return schema.properties != null; | ||
} | ||
|
||
// Function to generate Markdown content from JSON schema | ||
function generateObjectMD(schema, title, schemaFolderName) { | ||
|
||
const objectName = schema.title | ||
|
||
if (schema.title != null) { | ||
title = schema.title; | ||
} | ||
|
||
let markdownContent = `# ${title}\n\n`; | ||
|
||
if (schema.description != null) { | ||
markdownContent += `${escape(schema.description)}\n\n`; | ||
} | ||
|
||
console.log('hasAllOf/hasProperties', hasAllOf(schema.allOf), hasProperties(schema)); | ||
if (hasAllOf(schema.allOf) || hasProperties(schema)) { | ||
// Extract properties, required fields, and $ref from the first allOf object | ||
let root = schema; | ||
if (hasAllOf(schema.allOf)) { | ||
root = schema.allOf[0]; | ||
} | ||
|
||
const properties = root.properties; | ||
const required = root.required; | ||
const ref = root.$ref; | ||
|
||
markdownContent += `## Properties\n\n`; | ||
|
||
for (const [propertyName, propertyDetails] of Object.entries(properties)) { | ||
markdownContent += processProperty(propertyName, propertyDetails, schema.examples); | ||
} | ||
|
||
// show required properties | ||
if (required && required.length > 0) { | ||
markdownContent += `### Required Properties:\n\n`; | ||
// for each required property show the name | ||
required.forEach((propertyName) => { | ||
markdownContent += `* \`${propertyName}\`\n`; | ||
}); | ||
markdownContent += '\n'; | ||
} | ||
|
||
if (ref) { | ||
markdownContent += `ref: ${ref}\n\n`; | ||
} | ||
|
||
if (schema.examples) { | ||
markdownContent += `## Examples\n\n`; | ||
markdownContent += '```json\n'; | ||
markdownContent += JSON.stringify(schema.examples, null, 2); | ||
markdownContent += '\n```'; | ||
} | ||
} | ||
|
||
const frontMatter = generateFrontMatter(objectName, schema.description); | ||
console.log('frontMatter:', frontMatter); | ||
|
||
const outputFileName = `./website/versioned_docs/version-2.1/${schemaFolderName}/schemas/${title.replace(/\s+/g, '')}.md`; | ||
|
||
fs.outputFileSync(outputFileName, `---\n${yaml.dump(frontMatter)}\n---\n\n${markdownContent}`); | ||
|
||
// objectName must not contain any spaces | ||
if (objectName != null) { | ||
return schemaFolderName + '/schemas/' + objectName.replace(/\s+/g, ''); | ||
} | ||
} | ||
|
||
function escape(text) { | ||
let output = text; | ||
output = output.replace(/>/g, '\\>'); | ||
|
||
return output; | ||
} | ||
|
||
function generateFrontMatter(title, description) { | ||
return { | ||
title: title + ' Schema', | ||
description: description, | ||
sidebar_label: title + ' Schema', | ||
}; | ||
} | ||
|
||
function processSchemaFile(schemaFile, schemaFolderName) { | ||
const schemaData = fs.readJSONSync(schemaFile); | ||
|
||
// if there is allOf, then it is an object | ||
const allOfArray = schemaData.allOf; | ||
let sidebarItems = []; | ||
if (Array.isArray(allOfArray) && allOfArray.length > 0) { | ||
sidebarItems.push(generateObjectMD(schemaData, null, schemaFolderName)); | ||
} | ||
if (schemaData.definitions) { | ||
for (const [objectName, objectDetails] of Object.entries(schemaData.definitions)) { | ||
sidebarItems.push(generateObjectMD(objectDetails, objectName, schemaFolderName)); | ||
} | ||
} | ||
|
||
// return sidebarItems.flat().filter(item => !item.endsWith('undefined')); | ||
return sidebarItems; | ||
} | ||
|
||
function parseSchemaFolder(schemaFolderName) { | ||
// Read all files in the schema folder | ||
const schemaFiles = fs.readdirSync("./schemas/"+schemaFolderName) | ||
.filter(file => file.endsWith('.json')) | ||
.map(file => path.join("./schemas/"+schemaFolderName, file)); | ||
|
||
// Process each schema file | ||
let sidebarItems = []; | ||
for (const schemaFile of schemaFiles) { | ||
sidebarItems.push(processSchemaFile(schemaFile, schemaFolderName)); | ||
} | ||
|
||
// filter out null values | ||
return sidebarItems.flat().filter(item => item); | ||
} | ||
|
||
function main() { | ||
let sidebarObject = require('./website/versioned_sidebars/version-2.1-sidebars.json') | ||
|
||
let sidebarContextObject = { | ||
"type": "category", | ||
"label": "Context Schemas Part", | ||
"items": [] | ||
} | ||
|
||
let sidebarApiObject = { | ||
"type": "category", | ||
"label": "API Schemas Part", | ||
"items": [] | ||
} | ||
|
||
sidebarApiObject.items = parseSchemaFolder('api'); | ||
sidebarContextObject.items = parseSchemaFolder('context'); | ||
|
||
sidebarObject.docs["FDC3 Standard"].push(sidebarContextObject) | ||
sidebarObject.docs["FDC3 Standard"].push(sidebarApiObject) | ||
|
||
fs.outputJSONSync('./website/versioned_sidebars/version-2.1-sidebars.json', sidebarObject, { spaces: 2 }); | ||
} | ||
|
||
if (require.main === module) { | ||
main(); | ||
} |