Skip to content

Commit

Permalink
Update check-markdown.js
Browse files Browse the repository at this point in the history
  • Loading branch information
Sarvesh2783 authored Dec 6, 2024
1 parent 6865988 commit c65c5e2
Showing 1 changed file with 61 additions and 61 deletions.
122 changes: 61 additions & 61 deletions scripts/markdown/check-markdown.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
const fs = require('fs');
const matter = require('gray-matter');
const path = require('path');
const pLimit = require('p-limit'); // Import the p-limit package
const pLimit = require('p-limit'); // Import p-limit for concurrency control

Check warning on line 4 in scripts/markdown/check-markdown.js

View check run for this annotation

Codecov / codecov/patch

scripts/markdown/check-markdown.js#L4

Added line #L4 was not covered by tests

const limit = pLimit(5); // Limit the number of concurrent tasks

Check warning on line 6 in scripts/markdown/check-markdown.js

View check run for this annotation

Codecov / codecov/patch

scripts/markdown/check-markdown.js#L6

Added line #L6 was not covered by tests

/**
* Checks if a given string is a valid URL.
Expand All @@ -20,36 +22,30 @@ function isValidURL(str) {
/**
* Validates the frontmatter of a blog post.
* @param {object} frontmatter - The frontmatter object to validate.
* @param {string} filePath - The path to the file being validated.
* @returns {string[]|null} An array of validation error messages, or null if no errors.
*/
function validateBlogs(frontmatter) {
const requiredAttributes = ['title', 'date', 'type', 'tags', 'cover', 'authors'];
const errors = [];

// Check for required attributes
requiredAttributes.forEach(attr => {
if (!frontmatter.hasOwnProperty(attr)) {
errors.push(`${attr} is missing`);
}
});

// Validate date format
if (frontmatter.date && Number.isNaN(Date.parse(frontmatter.date))) {
errors.push(`Invalid date format: ${frontmatter.date}`);
}

// Validate tags format (must be an array)
if (frontmatter.tags && !Array.isArray(frontmatter.tags)) {
errors.push(`Tags should be an array`);
}

// Validate cover is a string
if (frontmatter.cover && typeof frontmatter.cover !== 'string') {
errors.push(`Cover must be a string`);
}

// Validate authors (must be an array with valid attributes)
if (frontmatter.authors) {
if (!Array.isArray(frontmatter.authors)) {
errors.push('Authors should be an array');
Expand All @@ -74,18 +70,14 @@ function validateBlogs(frontmatter) {
/**
* Validates the frontmatter of a documentation file.
* @param {object} frontmatter - The frontmatter object to validate.
* @param {string} filePath - The path to the file being validated.
* @returns {string[]|null} An array of validation error messages, or null if no errors.
*/
function validateDocs(frontmatter) {
const errors = [];

// Check if title exists and is a string
if (!frontmatter.title || typeof frontmatter.title !== 'string') {
errors.push('Title is missing or not a string');
}

// Check if weight exists and is a number
if (frontmatter.weight === undefined || typeof frontmatter.weight !== 'number') {
errors.push('Weight is missing or not a number');
}
Expand All @@ -94,67 +86,75 @@ function validateDocs(frontmatter) {
}

/**
* Recursively checks markdown files in a folder and validates their frontmatter with concurrency control.
* @param {string} folderPath - The path to the folder to check.
* Processes a single Markdown file for validation.
* @param {string} filePath - The full path to the Markdown file.
* @param {Function} validateFunction - The function used to validate the frontmatter.
* @param {string} [relativePath=''] - The relative path of the folder for logging purposes.
* @param {number} concurrencyLimit - The maximum number of files to process concurrently.
* @param {string} relativePath - The relative path for logging purposes.
* @returns {Promise<void>}
*/
function checkMarkdownFiles(folderPath, validateFunction, relativePath = '', concurrencyLimit = 5) {
const limit = pLimit(concurrencyLimit); // Limit the concurrency
const tasks = [];

fs.readdir(folderPath, (err, files) => {
if (err) {
console.error('Error reading directory:', err);
return;
}

files.forEach(file => {
const filePath = path.join(folderPath, file);
const relativeFilePath = path.join(relativePath, file);

// Skip the folder 'docs/reference/specification'
if (relativeFilePath.includes('reference/specification')) {
function processMarkdownFile(filePath, validateFunction, relativePath) {
return new Promise((resolve, reject) => {
fs.readFile(filePath, 'utf-8', (err, content) => {
if (err) {
reject(new Error(`Error reading file ${filePath}: ${err.message}`));

Check warning on line 99 in scripts/markdown/check-markdown.js

View check run for this annotation

Codecov / codecov/patch

scripts/markdown/check-markdown.js#L96-L99

Added lines #L96 - L99 were not covered by tests
return;
}

const task = new Promise((resolve, reject) => {
fs.stat(filePath, (err, stats) => {
if (err) {
reject('Error reading file stats:', err);
} else {
// Recurse if directory, otherwise validate markdown file
if (stats.isDirectory()) {
checkMarkdownFiles(filePath, validateFunction, relativeFilePath, concurrencyLimit);
} else if (path.extname(file) === '.md') {
const fileContent = fs.readFileSync(filePath, 'utf-8');
const { data: frontmatter } = matter(fileContent);

const errors = validateFunction(frontmatter);
if (errors) {
console.log(`Errors in file ${relativeFilePath}:`);
errors.forEach(error => console.log(` - ${error}`));
process.exitCode = 1;
}
}
resolve();
}
});
});
const { data: frontmatter } = matter(content);
const errors = validateFunction(frontmatter);

Check warning on line 104 in scripts/markdown/check-markdown.js

View check run for this annotation

Codecov / codecov/patch

scripts/markdown/check-markdown.js#L103-L104

Added lines #L103 - L104 were not covered by tests

// Add task with concurrency limit
tasks.push(limit(() => task));
if (errors) {
console.log(`Errors in file ${relativePath}:`);
errors.forEach(error => console.log(` - ${error}`));
process.exitCode = 1;

Check warning on line 109 in scripts/markdown/check-markdown.js

View check run for this annotation

Codecov / codecov/patch

scripts/markdown/check-markdown.js#L106-L109

Added lines #L106 - L109 were not covered by tests
}
resolve();

Check warning on line 111 in scripts/markdown/check-markdown.js

View check run for this annotation

Codecov / codecov/patch

scripts/markdown/check-markdown.js#L111

Added line #L111 was not covered by tests
});
});
}

/**
* Recursively processes Markdown files in a folder with a concurrency limit.
* @param {string} folderPath - The path to the folder to process.
* @param {Function} validateFunction - The function used to validate the frontmatter.
* @param {string} [relativePath=''] - The relative path for logging purposes.
* @returns {Promise<void>}
*/
async function processMarkdownFolder(folderPath, validateFunction, relativePath = '') {
const files = await fs.promises.readdir(folderPath);
const tasks = files.map(async (file) => {
const filePath = path.join(folderPath, file);
const relativeFilePath = path.join(relativePath, file);

Check warning on line 127 in scripts/markdown/check-markdown.js

View check run for this annotation

Codecov / codecov/patch

scripts/markdown/check-markdown.js#L124-L127

Added lines #L124 - L127 were not covered by tests

if (relativeFilePath.includes('reference/specification')) {
return; // Skip the specified folder

Check warning on line 130 in scripts/markdown/check-markdown.js

View check run for this annotation

Codecov / codecov/patch

scripts/markdown/check-markdown.js#L129-L130

Added lines #L129 - L130 were not covered by tests
}

// Wait for all tasks to complete
Promise.all(tasks).then(() => console.log('All files processed.'));
const stats = await fs.promises.stat(filePath);
if (stats.isDirectory()) {
await processMarkdownFolder(filePath, validateFunction, relativeFilePath);
} else if (path.extname(file) === '.md') {
await limit(() => processMarkdownFile(filePath, validateFunction, relativeFilePath));

Check warning on line 137 in scripts/markdown/check-markdown.js

View check run for this annotation

Codecov / codecov/patch

scripts/markdown/check-markdown.js#L133-L137

Added lines #L133 - L137 were not covered by tests
}
});

await Promise.all(tasks);

Check warning on line 141 in scripts/markdown/check-markdown.js

View check run for this annotation

Codecov / codecov/patch

scripts/markdown/check-markdown.js#L141

Added line #L141 was not covered by tests
}

// Define folder paths
const docsFolderPath = path.resolve(__dirname, '../../markdown/docs');
const blogsFolderPath = path.resolve(__dirname, '../../markdown/blog');

// Call the function with concurrency control
checkMarkdownFiles(docsFolderPath, validateDocs, '', 5); // Limit concurrency to 5
checkMarkdownFiles(blogsFolderPath, validateBlogs, '', 5); // Limit concurrency to 5
// Process folders with concurrency
(async () => {
try {
await Promise.all([

Check warning on line 151 in scripts/markdown/check-markdown.js

View check run for this annotation

Codecov / codecov/patch

scripts/markdown/check-markdown.js#L149-L151

Added lines #L149 - L151 were not covered by tests
processMarkdownFolder(docsFolderPath, validateDocs),
processMarkdownFolder(blogsFolderPath, validateBlogs),
]);
} catch (err) {
console.error(err.message);
process.exitCode = 1;

Check warning on line 157 in scripts/markdown/check-markdown.js

View check run for this annotation

Codecov / codecov/patch

scripts/markdown/check-markdown.js#L156-L157

Added lines #L156 - L157 were not covered by tests
}
})();

0 comments on commit c65c5e2

Please sign in to comment.