Skip to content

Commit

Permalink
add schema-2-markdown script
Browse files Browse the repository at this point in the history
  • Loading branch information
TheJuanAndOnly99 committed Feb 7, 2024
1 parent f4a46c0 commit 69aeded
Show file tree
Hide file tree
Showing 3 changed files with 233 additions and 2 deletions.
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
"preprepare": "npm run typegen && npm run typegen-bridging",
"prepare": "tsdx build",
"typegen": "node s2tQuicktypeUtil.js schemas/context src/context/ContextTypes.ts && tsdx lint src/context/ --fix",
"typegen-bridging": "node s2tQuicktypeUtil.js schemas/api schemas/bridging schemas/context/context.schema.json src/bridging/BridgingTypes.ts && tsdx lint src/bridging/ --fix"
"typegen-bridging": "node s2tQuicktypeUtil.js schemas/api schemas/bridging schemas/context/context.schema.json src/bridging/BridgingTypes.ts && tsdx lint src/bridging/ --fix",
"schema-2-markdown": "node schema2Markdown.js"
},
"peerDependencies": {},
"husky": {
Expand All @@ -51,6 +52,8 @@
"quicktype": "23.0.78",
"tsdx": "^0.14.1",
"tslib": "^2.0.1",
"typescript": "^4.0.3"
"typescript": "^4.0.3",
"fs-extra": "^11.2.0",
"js-yaml": "^4.1.0"
}
}
129 changes: 129 additions & 0 deletions schema2Markdown.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
const fs = require('fs-extra');
const yaml = require('js-yaml');
const path = require('path');

// Function to generate Markdown content from JSON schema
function generateMarkdown(schema) {
const allOfArray = schema.allOf;

if (!Array.isArray(allOfArray) || allOfArray.length === 0) {
console.error('Invalid or empty "allOf" array in the JSON schema.');
return '';
}

const firstAllOf = allOfArray[0];
if (!firstAllOf || typeof firstAllOf !== 'object') {
console.error('Invalid or missing "allOf" object in the JSON schema.');
return '';
}

// Extract properties, required fields, and $ref from the first allOf object
const properties = firstAllOf.properties;
const required = firstAllOf.required;
const ref = firstAllOf.$ref;

if (!properties || typeof properties !== 'object') {
console.error('Invalid or missing "properties" object in the JSON schema.');
return '';
}

let markdownContent = `# ${schema.title}\n\n`;
markdownContent += `${schema.description}\n\n`;
markdownContent += `## Properties\n\n`;


function processProperty(propertyName, propertyDetails) {
if (propertyName === 'type') {
markdownContent += `### ${'Type'|| propertyName}\n\n`;
markdownContent += `\`${propertyDetails.const}\`\n\n`;
} else {
markdownContent += `### ${propertyDetails.title || propertyName}\n\n`;
markdownContent += `\`${propertyName}\`\n\n`;
markdownContent += `${propertyDetails.description}\n\n`;

if (propertyDetails.type) {
markdownContent += `**Type**: ${propertyDetails.type}\n\n`;
} else {
const contextRef = propertyDetails.properties?.context?.$ref || propertyDetails.$ref;
if (contextRef) {
const reference = contextRef.toLowerCase().replace(/\s+/g, '-');
markdownContent += `**Reference**: [${contextRef}](${reference}.md)\n\n`;
}
}

if (propertyDetails.enum) {
markdownContent += `Possible values: ${propertyDetails.enum.join(', ')}\n\n`;
}

if (propertyDetails.allOf) {
markdownContent += `**Reference**: ${propertyDetails.allOf.map((item) => item.$ref).join(', ')}\n\n`;
}
}
}

for (const [propertyName, propertyDetails] of Object.entries(properties)) {
processProperty(propertyName, propertyDetails);
}

// 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: ${schema.allOf[1].$ref}\n\n`;
}

markdownContent += `## Examples\n\n`;
markdownContent += '```json\n';
markdownContent += JSON.stringify(schema.examples, null, 2);
markdownContent += '\n```';

return markdownContent;
}

function generateFrontMatter(title, description) {
return {
title: title + ' Schema',
description: description,
sidebar_label: title + ' Schema',
};
}

function processSchemaFile(schemaFile) {
const schemaData = fs.readJSONSync(schemaFile);
const markdownContent = generateMarkdown(schemaData);
const frontMatter = generateFrontMatter(schemaData.title, schemaData.description);

const outputFileName = `./docs/context/schemas/${schemaData.title.toLowerCase().replace(/\s+/g, '-')}-schema.md`;
fs.outputFileSync(outputFileName, `---\n${yaml.dump(frontMatter)}\n---\n\n${markdownContent}`);
}

function main() {
// Folder containing JSON schema files
const schemaFolder = './schemas/context';

// Read all files in the schema folder
const schemaFiles = fs.readdirSync(schemaFolder)
.filter(file => file.endsWith('.json'))
.map(file => path.join(schemaFolder, file));

// Log number of schema files found
console.log(`Found ${schemaFiles.length} schema files.`);

// Process each schema file
schemaFiles.forEach(processSchemaFile);

// Log number of schema markdown files generated in the markdown folder
const markdownFiles = fs.readdirSync('./docs/context/schemas') || [];
console.log(`Generated ${markdownFiles.length} markdown files.`);
}

if (require.main === module) {
main();
}
99 changes: 99 additions & 0 deletions schema2Markdown2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
const fs = require('fs');
const path = require('path');

// Specify the folder path here
const folderPath = './schemas/context'; // Update this with your folder path

// Function to convert JSON schema to Markdown
function convertSchemaToMarkdown(schema) {
// Log schema object
console.log('Schema:', schema);

// Find properties within allOf field
let properties;
let requiredProperties = [];
for (const subSchema of schema.allOf || []) {
if (subSchema.properties) {
properties = subSchema.properties;
if (subSchema.required) {
requiredProperties = subSchema.required;
}
break;
}
}

if (!properties) {
console.error('Error: properties field not found in schema.');
return '';
}

// Convert JSON schema to Markdown
const markdown = `
# ${schema.title}
${schema.description}
## Properties
| Name | Description | Type | Required |
|---------------|------------------------------------------------------|--------|----------|
${Object.entries(properties).map(([propName, prop]) => `| ${propName} | ${prop.description} | ${prop.type} | ${requiredProperties.includes(propName) ? 'Yes' : 'No'} |`).join('\n')}
## Examples
\`\`\`json
${JSON.stringify(schema.examples, null, 2)}
\`\`\`
`;

return markdown;
}

// Function to process each file
function processFile(filePath) {
// Load the JSON schema
const data = fs.readFileSync(filePath, 'utf8');
const schema = JSON.parse(data);
const markdown = convertSchemaToMarkdown(schema);

// Create output directory if not exists
const outputDir = path.join('docs', 'output');
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}

// Write Markdown to a file
const markdownFilePath = path.join(outputDir, path.basename(filePath, path.extname(filePath))) + '.md';
fs.writeFileSync(markdownFilePath, markdown);

console.log(`Markdown conversion completed for ${filePath}. Markdown file saved as ${markdownFilePath}`);
}

// Main function
function main() {
// Create output directory if not exists
const outputDir = path.join(folderPath, 'output');
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir);
}

// Read files from folder
fs.readdir(folderPath, (err, files) => {
if (err) {
console.error(`Error reading folder: ${err}`);
process.exit(1);
}

// Filter JSON schema files
const jsonSchemaFiles = files.filter(file => path.extname(file) === '.json');

// Process each JSON schema file
jsonSchemaFiles.forEach(file => {
const filePath = path.join(folderPath, file);
processFile(filePath);
});
});
}

// Call main function
main();

0 comments on commit 69aeded

Please sign in to comment.