-
-
Notifications
You must be signed in to change notification settings - Fork 669
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add tests for check markdown script #3378
base: master
Are you sure you want to change the base?
Changes from 11 commits
5a90f49
5373c9f
a30cef3
a9da240
1079101
86201ed
7c44f4a
c98ecdd
6e34205
4445ce5
333e0b2
8849351
1fbac7c
fada5ab
68cd3ee
998af5a
f5c8964
d92b519
d0fe33a
216a511
8a5235b
a93b45d
2732f0f
4fcdea8
e1a16c1
7401e7f
0fbdc06
02e221b
b17b83e
35d2e84
7921604
9d75691
b36972d
dff6ccc
53c86fd
92cc885
871e305
c0afa97
10c1ba5
2fa09e6
aa0e241
746dc88
4558748
29cd78c
e50392c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,4 +1,4 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const fs = require('fs'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const fs = require('fs').promises; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const matter = require('gray-matter'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const path = require('path'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -98,49 +98,44 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* @param {Function} validateFunction - The function used to validate the frontmatter. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* @param {string} [relativePath=''] - The relative path of the folder for logging purposes. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
function checkMarkdownFiles(folderPath, validateFunction, relativePath = '') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
fs.readdir(folderPath, (err, files) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (err) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
console.error('Error reading directory:', err); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
files.forEach(file => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
async function checkMarkdownFiles(folderPath, validateFunction, relativePath = '') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const files = await fs.readdir(folderPath); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for (const file of files) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const filePath = path.join(folderPath, file); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const relativeFilePath = path.join(relativePath, file); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Skip the folder 'docs/reference/specification' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (relativeFilePath.includes('reference/specification')) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
continue; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
fs.stat(filePath, (err, stats) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (err) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
console.error('Error reading file stats:', err); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const stats = await fs.stat(filePath); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Recurse if directory, otherwise validate markdown file | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (stats.isDirectory()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
await checkMarkdownFiles(filePath, validateFunction, relativeFilePath); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else if (path.extname(file) === '.md') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const fileContent = await fs.readFile(filePath, 'utf-8'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const { data: frontmatter } = matter(fileContent); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Recurse if directory, otherwise validate markdown file | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (stats.isDirectory()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
checkMarkdownFiles(filePath, validateFunction, relativeFilePath); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} 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; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const errors = validateFunction(frontmatter); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (errors) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
console.log(`Errors in file ${relativeFilePath}:`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
errors.forEach(error => console.log(` - ${error}`)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
process.exitCode = 1; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} catch (err) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
console.error('Error processing files:', err); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Enhance error handling and optimize async operations. Several improvements could be made to this function:
Consider these improvements: async function checkMarkdownFiles(folderPath, validateFunction, relativePath = '') {
try {
const files = await fs.readdir(folderPath);
+ const filePromises = files.map(async file => {
const filePath = path.join(folderPath, file);
const relativeFilePath = path.join(relativePath, file);
if (relativeFilePath.includes('reference/specification')) {
return;
}
- const stats = await fs.stat(filePath);
+ try {
+ const stats = await fs.stat(filePath);
- if (stats.isDirectory()) {
- await checkMarkdownFiles(filePath, validateFunction, relativeFilePath);
- } else if (path.extname(file) === '.md') {
- const fileContent = await fs.readFile(filePath, 'utf-8');
- const { data: frontmatter } = matter(fileContent);
+ if (stats.isDirectory()) {
+ await checkMarkdownFiles(filePath, validateFunction, relativeFilePath);
+ } else if (path.extname(file) === '.md') {
+ const fileContent = await fs.readFile(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;
+ const errors = validateFunction(frontmatter);
+ if (errors) {
+ console.log(`Errors in file ${relativeFilePath}:`);
+ errors.forEach(error => console.log(` - ${error}`));
+ process.exitCode = 1;
+ }
}
+ } catch (err) {
+ console.error(`Error processing file ${relativeFilePath}:`, err);
+ throw err;
}
- }
+ });
+ await Promise.all(filePromises);
} catch (err) {
- console.error('Error processing files:', err);
+ console.error(`Error in directory ${folderPath}:`, err);
+ throw err;
}
} 📝 Committable suggestion
Suggested change
🧰 Tools🪛 GitHub Check: codecov/patch[warning] 110-110: scripts/markdown/check-markdown.js#L110 🪛 eslint[error] 102-102: Delete (prettier/prettier) [error] 103-103: Replace (prettier/prettier) [error] 104-104: Delete (prettier/prettier) [error] 104-129: iterators/generators require regenerator-runtime, which is too heavyweight for this guide to allow them. Separately, loops should be avoided in favor of array iterations. (no-restricted-syntax) [error] 105-105: Replace (prettier/prettier) [error] 106-106: Delete (prettier/prettier) [error] 108-108: Replace (prettier/prettier) [error] 109-109: Delete (prettier/prettier) [error] 110-110: Replace (prettier/prettier) [error] 110-110: Unexpected use of continue statement. (no-continue) [error] 111-111: Delete (prettier/prettier) [error] 113-113: Replace (prettier/prettier) [error] 113-113: Unexpected (no-await-in-loop) [error] 115-115: Delete (prettier/prettier) [error] 116-116: Replace (prettier/prettier) [error] 117-117: Delete (prettier/prettier) [error] 117-117: Unexpected (no-await-in-loop) [error] 118-118: Replace (prettier/prettier) [error] 119-119: Replace (prettier/prettier) [error] 119-119: Unexpected (no-await-in-loop) [error] 120-120: Delete (prettier/prettier) [error] 122-122: Replace (prettier/prettier) [error] 123-123: Replace (prettier/prettier) [error] 124-124: Delete (prettier/prettier) [error] 125-125: Replace (prettier/prettier) [error] 126-126: Replace (prettier/prettier) [error] 127-127: Replace (prettier/prettier) [error] 128-128: Replace (prettier/prettier) [error] 129-129: Replace (prettier/prettier) [error] 130-130: Delete (prettier/prettier) [error] 131-131: Delete (prettier/prettier) [error] 132-132: Delete (prettier/prettier) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @vishvamsinh28 Can you apply this suggestion? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @akshatnema Done |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const docsFolderPath = path.resolve(__dirname, '../../markdown/docs'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const blogsFolderPath = path.resolve(__dirname, '../../markdown/blog'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
checkMarkdownFiles(docsFolderPath, validateDocs); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
checkMarkdownFiles(blogsFolderPath, validateBlogs); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
module.exports = { validateBlogs, validateDocs, checkMarkdownFiles } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add error handling for main script execution While the Consider wrapping the main execution in an async function with error handling: -checkMarkdownFiles(docsFolderPath, validateDocs);
-checkMarkdownFiles(blogsFolderPath, validateBlogs);
+async function main() {
+ try {
+ await Promise.all([
+ checkMarkdownFiles(docsFolderPath, validateDocs),
+ checkMarkdownFiles(blogsFolderPath, validateBlogs)
+ ]);
+ } catch (error) {
+ console.error('Failed to validate markdown files:', error);
+ process.exit(1);
+ }
+}
+
+main(); 📝 Committable suggestion
Suggested change
🧰 Tools🪛 eslint (1.23.1)[error] 149-149: Insert (prettier/prettier) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @vishvamsinh28 Apply this suggestion as it will improve the performance of the script There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
const fs = require('fs').promises; | ||
const path = require('path'); | ||
const os = require('os'); | ||
const { | ||
validateBlogs, | ||
validateDocs, | ||
checkMarkdownFiles | ||
} = require('../../scripts/markdown/check-markdown'); | ||
|
||
describe('Frontmatter Validator', () => { | ||
let tempDir; | ||
let mockConsoleError; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix variable shadowing of mockConsoleError. The Apply this fix: it('logs error to console when an error occurs in checkMarkdownFiles', async () => {
const invalidFolderPath = path.join(tempDir, 'non-existent-folder');
- const mockConsoleError = jest.spyOn(console, 'error').mockImplementation();
await checkMarkdownFiles(invalidFolderPath, validateBlogs);
expect(mockConsoleError.mock.calls[0][0]).toContain('Error processing files:');
- mockConsoleError.mockRestore();
}); Also applies to: 75-82 🧰 Tools🪛 eslint[error] 11-11: Delete (prettier/prettier) [error] 12-12: Delete (prettier/prettier) |
||
beforeEach(async () => { | ||
mockConsoleError = jest.spyOn(console, 'error').mockImplementation(); | ||
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'test-config')); | ||
}); | ||
|
||
afterEach(async () => { | ||
mockConsoleError.mockRestore(); | ||
await fs.rm(tempDir, { recursive: true, force: true }); | ||
}); | ||
|
||
it('validates authors array and returns specific errors', async () => { | ||
const frontmatter = { | ||
title: 'Test Blog', | ||
date: '2024-01-01', | ||
type: 'blog', | ||
tags: ['test'], | ||
cover: 'cover.jpg', | ||
authors: [{ name: 'John' }, { photo: 'jane.jpg' }, { name: 'Bob', photo: 'bob.jpg', link: 'not-a-url' }] | ||
}; | ||
|
||
const errors = validateBlogs(frontmatter); | ||
expect(errors).toEqual(expect.arrayContaining([ | ||
'Author at index 0 is missing a photo', | ||
'Author at index 1 is missing a name', | ||
'Invalid URL for author at index 2: not-a-url' | ||
])); | ||
}); | ||
|
||
it('validates docs frontmatter for required fields', async () => { | ||
const frontmatter = { title: 123, weight: 'not-a-number' }; | ||
const errors = validateDocs(frontmatter); | ||
expect(errors).toEqual(expect.arrayContaining([ | ||
'Title is missing or not a string', | ||
'Weight is missing or not a number' | ||
])); | ||
}); | ||
|
||
it('checks for errors in markdown files in a directory', async () => { | ||
await fs.writeFile(path.join(tempDir, 'invalid.md'), `---\ntitle: Invalid Blog\n---`); | ||
const mockConsoleLog = jest.spyOn(console, 'log').mockImplementation(); | ||
|
||
await checkMarkdownFiles(tempDir, validateBlogs); | ||
|
||
expect(mockConsoleLog).toHaveBeenCalledWith(expect.stringContaining('Errors in file invalid.md:')); | ||
mockConsoleLog.mockRestore(); | ||
}); | ||
|
||
it('returns multiple validation errors for invalid blog frontmatter', async () => { | ||
const frontmatter = { | ||
title: 123, | ||
date: 'invalid-date', | ||
type: 'blog', | ||
tags: 'not-an-array', | ||
cover: ['not-a-string'], | ||
authors: { name: 'John Doe' } | ||
}; | ||
const errors = validateBlogs(frontmatter); | ||
|
||
expect(errors.length).toBeGreaterThan(3); | ||
}); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Enhance test assertions for multiple validation errors. The test only checks the number of errors but not their specific content. This could allow incorrect error messages to pass the test. it('returns multiple validation errors for invalid blog frontmatter', async () => {
const frontmatter = {
title: 123,
date: 'invalid-date',
type: 'blog',
tags: 'not-an-array',
cover: ['not-a-string'],
authors: { name: 'John Doe' }
};
const errors = validateBlogs(frontmatter);
- expect(errors.length).toBeGreaterThan(3);
+ expect(errors).toEqual(expect.arrayContaining([
+ 'Title must be a string',
+ 'Date must be a valid date string',
+ 'Tags must be an array',
+ 'Cover must be a string',
+ 'Authors must be an array'
+ ]));
});
🧰 Tools🪛 eslint[error] 62-62: Delete (prettier/prettier) [error] 63-63: Delete (prettier/prettier) [error] 64-64: Delete (prettier/prettier) [error] 65-65: Replace (prettier/prettier) [error] 66-66: Delete (prettier/prettier) [error] 67-67: Replace (prettier/prettier) [error] 68-68: Replace (prettier/prettier) [error] 69-69: Delete (prettier/prettier) [error] 70-70: Delete (prettier/prettier) [error] 71-71: Delete (prettier/prettier) [error] 73-73: Delete (prettier/prettier) [error] 74-74: Delete (prettier/prettier) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @vishvamsinh28, thank you for making the changes! If you found this review helpful, would you consider giving us a shout-out on X? |
||
|
||
it('logs error to console when an error occurs in checkMarkdownFiles', async () => { | ||
const invalidFolderPath = path.join(tempDir, 'non-existent-folder'); | ||
const mockConsoleError = jest.spyOn(console, 'error').mockImplementation(); | ||
|
||
await checkMarkdownFiles(invalidFolderPath, validateBlogs); | ||
|
||
expect(mockConsoleError.mock.calls[0][0]).toContain('Error processing files:'); | ||
mockConsoleError.mockRestore(); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
Switching to async file operations could impact performance
Based on the analysis of the codebase:
Promise.all
Given that:
Promise.all
could lead to too many open file handlesThe switch to async operations could potentially degrade performance and system resource usage. Consider keeping the synchronous file operations.
🔗 Analysis chain
Consider performance implications of async file operations
Previous experience with this codebase suggests that synchronous file operations (
fs.readFileSync
) might be more suitable for processing large markdown files. While the switch tofs.promises
follows modern JavaScript practices, it could potentially impact performance when dealing with numerous files.Let's check the typical file sizes and counts in the markdown directories:
Consider benchmarking both approaches (sync vs async) with your typical markdown file load to make an informed decision.
The previous results only showed files in node_modules. We need to check the actual documentation files that this script processes and understand the implementation pattern to make an informed decision about sync vs async operations.
The previous results show the implementation uses parallel processing with
Promise.all
on file operations, but we need to understand the actual directory structure and how the script is invoked to make a final decision about the performance implications.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
Length of output: 619
Script:
Length of output: 4036
Script:
Length of output: 28230
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok 👍 , so how can we improve this script. Currently we believe that making this script asynchronous and checking multiple markdown files in parallel runs will improve the performance of script. Do you have any better alternative?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@akshatnema, I understand your aim to improve the script's performance by making it asynchronous and processing multiple markdown files in parallel. Converting to async operations can indeed enhance performance, but without proper concurrency control, it might lead to resource exhaustion due to too many simultaneous file operations.
One way to mitigate this is by limiting the number of concurrent asynchronous operations. You can achieve this by using a concurrency control library like
p-limit
. Here's how you might modify the script:In this example:
p-limit
to limit the number of concurrent async operations. Adjust the concurrency limit (10
in the example) based on performance testing.Alternatively, if the number of files is manageable, processing files sequentially using a
for...of
loop might suffice:This sequential approach reduces complexity and resource usage at the cost of potentially longer execution time.
Suggestions:
Let me know if you'd like further assistance or have questions about implementing these changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But the limit of resource will be internally managed by Nodejs, am I right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@akshatnema, you bring up a valid point. Node.js does manage asynchronous operations efficiently through its event loop, and it handles many aspects of resource management internally. However, when it comes to file system operations, especially with a large number of files, there are underlying operating system limits to consider—such as the maximum number of file descriptors that can be open simultaneously.
While Node.js abstracts much of the complexity, initiating a vast number of asynchronous file operations without any concurrency control can lead to errors like
EMFILE: too many open files
. This happens because the OS has a limit on how many files can be open at once, and Node.js doesn't automatically throttle the rate of file system calls to stay within these limits.By implementing a concurrency limit (e.g., using the
p-limit
library), we can control the number of simultaneous file operations, preventing resource exhaustion while still benefiting from asynchronous processing. This approach helps maintain optimal performance without overloading the system's resources.In essence, while Node.js handles asynchronous execution, it's important for us to manage the concurrency of resource-intensive operations like file I/O to avoid hitting OS-imposed limits.
Let me know if you have any questions or need assistance with implementing this approach.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@akshatnema, understood. I'll open a new GitHub issue to track the enhancement regarding the concurrency limit.
Additionally, to incorporate the new tests for
check-markdown.js
into the CI pipeline, we should update the workflow file to ensure these tests are executed during continuous integration. Here's a suggested update to the workflow file:This addition of the Run Markdown Validation Tests step will execute the new tests you've added for
check-markdown.js
during the CI process. Adjust the command if your test script or directory structure differs.Let me know if you need any further assistance with this!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, workflow should be updated here - https://github.com/asyncapi/website/blob/master/.github/workflows/if-nodejs-pr-testing.yml#L84, to include secrets for the environment variable added.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@akshatnema, understood.
To update the workflow at
.github/workflows/if-nodejs-pr-testing.yml
to include the secrets for the environment variable, you can modify the workflow file as follows:Notes:
env
section under thebuild
job, theCONCURRENCY_LIMIT
environment variable will be available to all steps within the job.CONCURRENCY_LIMIT
secret is added to your repository's secrets in GitHub settings. You can do this by navigating to Settings > Secrets and variables > Actions and adding a new repository secret namedCONCURRENCY_LIMIT
.check-markdown.js
can now access theCONCURRENCY_LIMIT
environment variable viaprocess.env.CONCURRENCY_LIMIT
.Let me know if this addresses the issue or if you need any further assistance!
✏️ Learnings added
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kindly create an issue for this, describing whole scenario in detail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@akshatnema, I've created the issue as requested, including a detailed description.
You can find it here: Limit concurrency in markdown file processing to improve performance.
Let me know if there's anything else I can assist with.
🔗 Analysis chain
@akshatnema, understood. I've prepared a GitHub issue to track this enhancement in detail.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
Length of output: 809