Skip to content
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 build post list script #3284

Open
wants to merge 79 commits into
base: master
Choose a base branch
from

Conversation

vishvamsinh28
Copy link
Contributor

@vishvamsinh28 vishvamsinh28 commented Oct 11, 2024

This script adds tests for build-post-list.js script

Summary by CodeRabbit

  • New Features

    • Enhanced flexibility in building post lists with updated parameters for improved configurability.
    • Introduced a new test suite for validating the buildPostList and slugifyToC functions.
    • Added a new constant TEST_CONTENT for structured test data across different sections.
    • Added a new function for setting up test directories and files.
  • Bug Fixes

    • Improved error handling to ensure proper feedback when no post directories are provided.
  • Documentation

    • Updated import statements for clarity and consistency across scripts.

Copy link

netlify bot commented Oct 11, 2024

Deploy Preview for asyncapi-website ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit 8f00a15
🔍 Latest deploy log https://app.netlify.com/sites/asyncapi-website/deploys/67626adf9dc32300083441a4
😎 Deploy Preview https://deploy-preview-3284--asyncapi-website.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link

coderabbitai bot commented Oct 17, 2024

Warning

Rate limit exceeded

@vishvamsinh28 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 18 minutes and 35 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between a795ce0 and 8f00a15.

📒 Files selected for processing (1)
  • scripts/build-post-list.js (7 hunks)

Walkthrough

The pull request introduces significant modifications to the buildPostList function in scripts/build-post-list.js, enhancing its flexibility by updating its parameters and improving error handling. The postDirectories array has been removed, and the function now accepts three parameters: postDirectories, basePath, and writeFilePath. Error handling has been added to ensure proper input validation. The walkDirectories function has also been updated to utilize the new parameters effectively. Additionally, a comprehensive suite of unit tests has been added to validate the new functionality.

Changes

File Change Summary
scripts/build-post-list.js Updated buildPostList function to accept postDirectories, basePath, and writeFilePath. Removed postDirectories array. Added error handling and modified walkDirectories function.
tests/build-post-list.test.js Introduced a comprehensive suite of unit tests for buildPostList and slugifyToC, covering various scenarios and ensuring robust validation.
scripts/index.js Changed import and invocation of buildPostList to use destructuring and include new parameters.
tests/index.test.js Updated import statement for buildPostList to use destructuring syntax instead of default import.
tests/fixtures/buildPostListData.js Added a new constant TEST_CONTENT containing structured data for testing buildPostList.
tests/helper/buildPostListSetup.js Introduced a new file with asynchronous functions setupTestDirectories and generateTempDirPath to create test directories and files based on predefined content.

Possibly related PRs

  • feat: added test for build-rss.js #3101: The changes in the main PR involve refactoring the buildPostList function to use asynchronous operations, which is a similar approach to the asynchronous updates made in the rssFeed function in build-rss.js.
  • fix: file write errors for tools and newsroom video #3297: The modifications in the build-tools.js script to use fs-extra for asynchronous file operations relate closely to the changes made in the buildPostList function, which also transitioned to asynchronous file handling.
  • feat: add tests for dashboard script #3344: The addition of tests for the build-dashboard.js script, which includes asynchronous file operations, is relevant to the changes made in the buildPostList function that also transitioned to asynchronous operations.
  • feat: add tests for check markdown script #3378: The main PR's focus on validating markdown files through the check-markdown.js script is directly related to the tests added in this PR, which aim to ensure the correctness of markdown frontmatter processing.

Suggested labels

ready-to-merge

Suggested reviewers

  • derberg
  • magicmatatjahu
  • devilkiller-ag
  • sambhavgupta0705
  • anshgoyalevil
  • akshatnema
  • Mayaleeeee
  • asyncapi-bot-eve

🐇 In the meadow where bunnies play,
A new script blooms, bright as the day.
With paths to write and errors caught,
A post list built, oh what a thought!
So hop along, let’s cheer and sing,
For code that dances, and joy it brings! 🌼


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@asyncapi-bot
Copy link
Contributor

asyncapi-bot commented Oct 17, 2024

⚡️ Lighthouse report for the changes in this PR:

Category Score
🔴 Performance 40
🟢 Accessibility 98
🟢 Best practices 92
🟢 SEO 100
🔴 PWA 33

Lighthouse ran on https://deploy-preview-3284--asyncapi-website.netlify.app/

Copy link

codecov bot commented Oct 17, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 98.66%. Comparing base (e1e4662) to head (8f00a15).

Additional details and impacted files
@@             Coverage Diff             @@
##           master    #3284       +/-   ##
===========================================
+ Coverage   86.59%   98.66%   +12.06%     
===========================================
  Files          21       21               
  Lines         664      674       +10     
===========================================
+ Hits          575      665       +90     
+ Misses         89        9       -80     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Outside diff range and nitpick comments (9)
scripts/index.js (3)

11-15: LGTM! Consider extracting postDirectories for improved maintainability.

The new postDirectories array provides a clear and flexible way to define the directories to be processed by buildPostList. This change enhances the configurability of the script.

For improved maintainability, consider extracting this array to a separate configuration file. This would allow easier updates to the directory list without modifying the main script. For example:

const { postDirectories } = require('../config/build-config.js');

16-17: LGTM! Consider using resolve for basePath as well.

The introduction of basePath and writeFilePath variables improves the flexibility of the script by allowing easy configuration of input and output paths.

For consistency, consider using resolve for basePath as well:

const basePath = resolve(__dirname, '..', 'pages');

This ensures that the path is always resolved correctly, regardless of the current working directory.


19-19: LGTM! Consider adding error handling.

The updated buildPostList function call correctly uses the new parameters, providing more flexibility in the post list building process.

Consider adding error handling to manage potential failures in the buildPostList function:

try {
  await buildPostList(postDirectories, basePath, writeFilePath);
} catch (error) {
  console.error('Error building post list:', error);
  // Optionally, you might want to throw the error or handle it in a way that's appropriate for your application
}

This will help in identifying and debugging any issues that may occur during the post list building process.

tests/build-post-list.test.js (5)

37-53: LGTM with suggestion: Consider enhancing assertion specificity

The test case effectively verifies the basic functionality of buildPostList. It checks for the existence of the output file and the presence of expected properties in the output.

To further improve the test, consider adding more specific assertions about the content of the output. For example, you could check for the exact number of entries in each category or verify specific fields of the blog entry beyond just the title.


55-82: LGTM with suggestion: Enhance negative test cases

These test cases effectively cover important scenarios: handling directories with only section files and processing multiple release notes. The assertions verify the presence of expected entries in the output.

To make these tests more robust, consider adding negative assertions. For example, in the "handles multiple release notes correctly" test, you could also verify that no unexpected release notes are present in the output.


84-101: LGTM with suggestions: Enhance error handling test and expand slugifyToC tests

The error handling test and slugifyToC tests are good additions to the test suite. However, there are opportunities for improvement:

  1. For the error handling test, consider asserting on the specific type of error thrown, not just that an error is thrown.

  2. The slugifyToC tests cover various input scenarios well. Consider adding a test case for a regular heading without an ID to ensure the function behaves correctly in this common scenario.

Example:

it('handles regular headings without ids', () => {
  const input = '## My Regular Heading';
  expect(slugifyToC(input)).toBe('my-regular-heading');
});

148-189: LGTM with suggestion: Enhance error message assertions

These additional error handling tests are valuable additions to the test suite, covering important scenarios such as unreadable directories, unparseable front matter, and the case where no post directories are provided.

To further improve these tests, consider making the error message assertions more specific. Instead of just checking for a partial match with "Error while building post list", you could assert on more detailed error messages that provide information about the specific error condition. This would ensure that the function is not only throwing errors but also providing helpful error messages for debugging.

Example:

expect(error.message).toMatch(/Error while building post list: Unable to read directory/);

1-191: Great job on the comprehensive test suite!

This test suite for the buildPostList and slugifyToC functions is well-structured and covers a wide range of scenarios, including both happy paths and error cases. The use of beforeEach and afterEach hooks for setup and teardown is commendable.

To further enhance the test suite, consider adding the following:

  1. Performance test: Add a test case with a large number of files to ensure the function performs well under load.
  2. Edge case: Test with very long file names or paths to ensure there are no issues with path length limits.
  3. Internationalization: If relevant, add tests with non-ASCII characters in file names and content to ensure proper handling of international content.

These additions would make an already strong test suite even more robust.

scripts/build-post-list.js (1)

39-40: Remove commented out code

There is a commented-out console.log statement at line 39. If it's no longer needed, consider removing it to keep the code clean.

Apply this diff to remove the commented code:

- // console.log(inspect(result, { depth: null, colors: true }))
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between ec62c5e and 0db7bc9.

📒 Files selected for processing (4)
  • scripts/build-post-list.js (6 hunks)
  • scripts/index.js (1 hunks)
  • tests/build-post-list.test.js (1 hunks)
  • tests/index.test.js (1 hunks)
🧰 Additional context used
🔇 Additional comments (8)
tests/index.test.js (2)

Line range hint 1-35: LGTM! The changes are consistent throughout the file.

The updated import statement for buildPostList is the only change in this file, and it's correctly reflected in the rest of the code. The test cases and mocks use buildPostList directly, which is consistent with the new named import. The overall structure and functionality of the tests remain intact.


2-2: LGTM! Verify the corresponding export in the source file.

The change from default import to named import is a good practice and improves code clarity. This change suggests that buildPostList is now exported as a named export in the build-post-list.js file.

To ensure consistency, please verify that the export in scripts/build-post-list.js matches this import style. You can run the following script to check:

✅ Verification successful

Export Style Verified

The scripts/build-post-list.js file correctly exports buildPostList as a named export:

module.exports = {slugifyToC, buildPostList}
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the export style of buildPostList in the source file

# Test: Search for the export of buildPostList. Expect: Named export
rg --type javascript 'exports?.buildPostList|module\.exports.*buildPostList' scripts/build-post-list.js

Length of output: 140


Script:

#!/bin/bash
# Description: Verify the export style of buildPostList in the source file without specifying file type

# Test: Search for the export of buildPostList. Expect: Named export
rg 'exports?.buildPostList|module\.exports.*buildPostList' scripts/build-post-list.js

Length of output: 132

scripts/index.js (2)

4-19: Summary: Good refactoring, ensure consistency across the codebase.

The changes to scripts/index.js significantly improve the flexibility and configurability of the post list building process. The introduction of postDirectories, basePath, and writeFilePath variables, along with the updated buildPostList function call, allow for easier maintenance and future extensions.

To ensure consistency across the codebase:

  1. Verify that all files importing buildPostList have been updated to use the new named import syntax.
  2. Check if there are any other scripts or components that might be affected by these changes and update them accordingly.
  3. Update any documentation or comments related to the post list building process to reflect these new configurations.

Run the following script to identify potential areas that might need updates:

#!/bin/bash
# Description: Identify potential areas affected by the changes

# Test 1: Find all files that import from build-post-list.js
echo "Files importing from build-post-list.js:"
rg --type js "from ['\"].*build-post-list['\"]"

# Test 2: Find all files that mention buildPostList
echo "Files mentioning buildPostList:"
rg --type js "buildPostList"

# Test 3: Check for any hardcoded paths related to blog, docs, or about pages
echo "Files with hardcoded paths:"
rg --type js "pages/(blog|docs|about)"

Review the output of this script to ensure all affected areas are properly updated.


4-4: Verify the export change in build-post-list.js and update other imports.

The import statement for buildPostList has been changed from a default import to a named import. This suggests a corresponding change in the build-post-list.js file.

Please run the following script to verify the export in build-post-list.js and check for any other import statements in the codebase that might need updating:

Ensure that all occurrences are updated to use the new named import syntax.

✅ Verification successful

Export and Imports Verified Successfully.

The build-post-list.js file correctly exports buildPostList as a named export, and all import statements in the codebase, including scripts/index.js, have been appropriately updated. No further issues were detected.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the export in build-post-list.js and check for other imports

# Test 1: Check the export in build-post-list.js
echo "Checking export in build-post-list.js:"
rg --type js "export.*buildPostList" scripts/build-post-list.js

# Test 2: Check for other import statements in the codebase
echo "Checking for other import statements:"
rg --type js "import.*buildPostList.*from ['\"]./build-post-list['\"]" --glob '!scripts/index.js'

Length of output: 2201

tests/build-post-list.test.js (2)

1-35: LGTM: Well-structured test setup

The import statements and describe block setup are well-organized. The use of beforeEach and afterEach hooks to create and clean up a temporary directory structure ensures isolated and repeatable tests. This approach follows testing best practices.


103-146: LGTM: Comprehensive coverage of specification file handling

These tests effectively verify that the buildPostList function correctly handles various types of specification files that should not be processed. The tests cover files without a title, files with "next-spec" in the filename, and files with "explorer" in the filename. The consistent approach across these tests and the verification of the absence of these entries in the output demonstrate thorough testing of this functionality.

scripts/build-post-list.js (2)

163-163: Ensure imports are updated after exporting buildPostList

Now that buildPostList is exported, make sure all modules that import it are updated accordingly.

Run the following script to find all import statements of build-post-list:

#!/bin/bash
# Description: Find all import statements of `build-post-list`.

# Expectation: Imports should destructure `buildPostList` from the module.

rg --type js "require\(.+build-post-list.+\)" -A 2

29-43: Ensure all calls to buildPostList are updated

The buildPostList function now accepts postDirectories, basePath, and writeFilePath as parameters. Ensure that all places where buildPostList is called have been updated to use the new signature.

Run the following script to find all calls to buildPostList and verify their parameters:

✅ Verification successful

All calls to buildPostList have been updated to use the new signature with three arguments.

  • tests/build-post-list.test.js
  • scripts/index.js
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all calls to `buildPostList` in the codebase.

# Expectation: Calls should use the new signature with three arguments.

rg --type js "buildPostList\(" -A 2

Length of output: 714


Script:

#!/bin/bash
# Description: Find all direct calls to `buildPostList` in the JavaScript codebase.

# Improved search pattern to capture function calls with varying whitespace and argument structures.
rg --type js "\bbuildPostList\s*\(" -A 2

Length of output: 2505

scripts/build-post-list.js Outdated Show resolved Hide resolved
scripts/build-post-list.js Outdated Show resolved Hide resolved
scripts/build-post-list.js Outdated Show resolved Hide resolved
scripts/build-post-list.js Outdated Show resolved Hide resolved
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (3)
tests/build-post-list.test.js (3)

37-53: Consider adding more specific assertions

While this test case covers the basic functionality of buildPostList, it could be enhanced by adding more specific assertions about the content of the output. For example, you could check for the exact number of entries in each category (docs, blog, about) and verify the structure of individual entries.

Here's an example of how you could add more specific assertions:

expect(output.docs).toHaveLength(1);
expect(output.blog).toHaveLength(1);
expect(output.about).toHaveLength(1);

const docEntry = output.docs[0];
expect(docEntry).toHaveProperty('title', 'Docs Home');
expect(docEntry).toHaveProperty('slug', '/docs');
expect(docEntry).toHaveProperty('excerpt');

84-101: Enhance error handling test and add a case for slugifyToC

The error handling test is good, but it could be more specific:

  1. For the error handling test, consider asserting the specific type of error thrown:

    await expect(buildPostList([invalidDir], tempDir, writeFilePath)).rejects.toThrow(Error);
  2. Add a test case for slugifyToC with a regular heading without an ID:

    it('handles regular headings without ids', () => {
      const input = '## My Regular Heading';
      expect(slugifyToC(input)).toBe('my-regular-heading');
    });

These additions will improve the test coverage and make the error handling more robust.


148-187: Enhance error handling tests

While these additional error handling tests cover important scenarios, they could be improved for more precise error checking:

  1. Instead of catching the error and checking its message, use expect().rejects.toThrow() for asynchronous functions:

    it('throws an error if the directory cannot be read', async () => {
      const invalidDir = [join(tempDir, 'non-existent-dir'), '/invalid'];
      await expect(buildPostList([invalidDir], tempDir, writeFilePath))
        .rejects.toThrow(/Error while building post list/);
    });
  2. Apply the same pattern to the other two error tests.

  3. Consider adding more specific error message checks if the buildPostList function throws different error messages for different scenarios.

These changes will make the tests more robust and easier to maintain.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 0db7bc9 and 55e970d.

📒 Files selected for processing (1)
  • tests/build-post-list.test.js (1 hunks)
🧰 Additional context used
🔇 Additional comments (4)
tests/build-post-list.test.js (4)

1-35: LGTM: Well-structured test setup

The import statements and describe block setup are well-organized. The use of beforeEach and afterEach hooks ensures a clean test environment for each test case, which is a good practice for maintaining test isolation.


55-82: LGTM: Good coverage of edge cases

These test cases effectively cover important scenarios:

  1. Handling directories with only section files.
  2. Processing multiple release notes correctly.

The tests are well-structured and include specific assertions to verify the correct behavior of the buildPostList function in these scenarios.


103-146: LGTM: Comprehensive tests for specification file filtering

These test cases effectively cover the filtering of specification files:

  1. Files without a title
  2. Files with "next-spec" in the filename
  3. Files with "explorer" in the filename

The tests are well-structured and include appropriate assertions to verify that these files are not processed by the buildPostList function. This ensures that only the intended files are included in the final output.


1-189: Overall: Well-structured and comprehensive test suite

This test file provides a thorough and well-organized suite of tests for the buildPostList and slugifyToC functions. Key strengths include:

  1. Comprehensive coverage of happy paths, edge cases, and error scenarios.
  2. Consistent structure throughout the file.
  3. Good use of beforeEach and afterEach hooks for test isolation.
  4. Effective testing of file filtering logic.

While there are some minor suggestions for improvements (as noted in previous comments), the overall quality of the test suite is high. It should provide robust validation of the functions' behavior and help catch potential regressions in future development.

@vishvamsinh28 vishvamsinh28 marked this pull request as draft October 17, 2024 08:06
@vishvamsinh28
Copy link
Contributor Author

Tests are passing on Ubuntu but failing on Windows. I will keep it as a draft until I find a solution for it.

@vishvamsinh28 vishvamsinh28 marked this pull request as ready for review October 18, 2024 05:39
@vishvamsinh28 vishvamsinh28 force-pushed the buildPostTest branch 2 times, most recently from 98f835b to ecf927e Compare October 18, 2024 07:32
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (2)
scripts/build-post-list.js (2)

29-43: Improved flexibility and error handling in buildPostList

The changes to the buildPostList function are well-implemented:

  1. The function now accepts parameters, enhancing its configurability and reusability.
  2. Error handling for empty postDirectories has been added, which is a good practice.
  3. The use of a writeFilePath parameter allows for more flexible output options.

These changes align well with the PR objectives of adding tests, as they make the function more testable.

However, the error handling in the catch block could be improved to preserve the original error stack trace.

Consider updating the error handling to preserve the original stack trace:

  } catch (error) {
-    throw new Error(`Error while building post list: ${error.message}`);
+    throw new Error('Error while building post list', { cause: error });
  }

This change will provide more context for debugging while preserving the original error information.


125-128: Improve variable naming consistency in release notes handling

While the logic for extracting version information from release notes file names has been updated, the variable naming could be improved for consistency and clarity.

Consider updating the variable names to follow the camelCase convention used elsewhere in the code:

- const fileName_without_extension = file.slice(0, -4)
+ const fileNameWithoutExtension = file.slice(0, -4)

This change will improve code consistency and readability.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between ed194bd and ad8e114.

📒 Files selected for processing (2)
  • scripts/build-post-list.js (7 hunks)
  • tests/build-post-list.test.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/build-post-list.test.js
🧰 Additional context used
🔇 Additional comments (6)
scripts/build-post-list.js (6)

2-2: Improved cross-platform compatibility

The addition of join and sep from the path module enhances the code's ability to handle file paths consistently across different operating systems. This is a positive change that aligns with best practices for cross-platform Node.js applications.


47-47: Improved consistency in walkDirectories function

The addition of basePath to the walkDirectories function signature and its recursive call ensures consistent handling of the base path throughout the directory traversal process. This change enhances the function's flexibility and aligns well with the modifications made to buildPostList.

Also applies to: 83-83


55-57: Enhanced cross-platform compatibility in file path handling

The updates to file path handling using join and sep, as well as the platform-independent index file check, significantly improve the code's cross-platform compatibility. These changes ensure consistent behavior across different operating systems and align with Node.js best practices for file system operations.

Also applies to: 98-98


57-57: Improved slug generation for cross-platform consistency

The update to slug generation now uses the basePath parameter and normalizes separators to forward slashes. This change ensures consistent slug generation across different platforms, further enhancing the code's cross-platform compatibility.


162-163: Improved module API with updated exports

The module exports have been updated to include both slugifyToC and buildPostList functions. This change enhances the module's API by making both functions available for external use, which aligns well with the PR objectives of adding tests for the build-post-list.js script. This modification will facilitate easier testing and potential reuse of these functions in other parts of the project.


Line range hint 1-163: Overall assessment of changes to build-post-list.js

The modifications to this file are well-implemented and align closely with the PR objectives of adding tests for the build-post-list.js script. Key improvements include:

  1. Enhanced cross-platform compatibility through better file path handling.
  2. Improved function flexibility with parameterized inputs.
  3. Better error handling, particularly in the buildPostList function.
  4. Updated module exports for easier testing and potential reuse.

These changes contribute positively to the codebase by improving testability, maintainability, and cross-platform consistency. The script is now better equipped to handle various input scenarios, which should facilitate more comprehensive testing.

There are a few minor suggestions for improvement, such as preserving the original error stack trace and maintaining consistent variable naming conventions. Addressing these points will further enhance the overall quality of the code.

@vishvamsinh28 vishvamsinh28 marked this pull request as draft October 18, 2024 09:11
@vishvamsinh28 vishvamsinh28 marked this pull request as ready for review October 22, 2024 12:58
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (1)
tests/build-post-list.test.js (1)

62-64: Remove unnecessary console.log statements in tests

The console.log statements at lines 62, 64, and 72 are unnecessary and can clutter the test output. Consider removing them to keep the test output clean.

Apply this diff to remove the console.log statements:

-    console.log("output before ", output);
-    console.log("output after ", output);
-    console.log("blog entry ", blogEntry);

Also applies to: 72-72

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between f5c9fdb and 42b6be3.

📒 Files selected for processing (1)
  • tests/build-post-list.test.js (1 hunks)
🧰 Additional context used

tests/build-post-list.test.js Outdated Show resolved Hide resolved
tests/build-post-list.test.js Outdated Show resolved Hide resolved
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (4)
tests/index.test.js (1)

Line range hint 16-33: Consider updating the test for buildPostList.

The test suite currently only checks if buildPostList is called, but doesn't verify its parameters. Since buildPostList now accepts three parameters (postDirectories, basePath, and writeFilePath), consider updating the test to ensure it's called with the correct arguments.

Here's a suggested update to the test:

test('should call all functions in the correct order', async () => {
  await start();

  expect(buildPostList).toHaveBeenCalledWith(
    expect.any(Array), // postDirectories
    expect.any(String), // basePath
    expect.any(String)  // writeFilePath
  );

  // ... rest of the test remains the same
});

This change will provide more robust verification of the buildPostList function usage.

scripts/index.js (2)

11-17: LGTM: New variables improve configurability.

The introduction of postDirectories, basePath, and writeFilePath variables enhances the flexibility of the post list building process. This is a good improvement.

Consider adding a brief comment explaining the structure of the postDirectories array for improved readability:

// Each item in postDirectories is a pair of [directoryPath, urlPath]
const postDirectories = [
  ['pages/blog', '/blog'],
  ['pages/docs', '/docs'],
  ['pages/about', '/about']
];

Line range hint 1-70: Overall assessment: Changes improve flexibility and maintainability.

The modifications to scripts/index.js align well with the PR objectives. They support the new functionality being tested in the build-post-list.js script by updating the import statement and function call. These changes enhance the flexibility and configurability of the post list building process.

Consider documenting the new parameter structure for buildPostList in a README or inline documentation to help future developers understand the configuration options quickly.

scripts/build-post-list.js (1)

71-72: LGTM: Improved handling of nested sections

The changes in how parent and sectionId are set, along with the updated recursive call to walkDirectories, improve the handling of nested sections. This makes the code more robust when dealing with different directory structures.

For added clarity, consider adding a comment explaining the logic behind using slugElements.length - 2 and slugElements.length - 1 for parent and sectionId respectively.

Also applies to: 82-82

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 42b6be3 and 7ae14bd.

📒 Files selected for processing (4)
  • scripts/build-post-list.js (7 hunks)
  • scripts/index.js (1 hunks)
  • tests/build-post-list.test.js (1 hunks)
  • tests/index.test.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/build-post-list.test.js
🧰 Additional context used
🔇 Additional comments (10)
tests/index.test.js (2)

Line range hint 1-33: Overall, the changes look good with room for improvement.

The import statement has been correctly updated to reflect the changes in the buildPostList function. However, the test suite could be enhanced to verify the new function signature. Consider implementing the suggested changes to improve test coverage and ensure consistency with the updated buildPostList function.


2-2: LGTM! Import statement updated correctly.

The change from default import to named import is correct and consistent with the changes in the buildPostList function.

To ensure consistency, let's verify if the start function has been updated to use the new buildPostList parameters:

✅ Verification successful

Verified! The start function correctly uses buildPostList with the updated parameters.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if the start function uses the new buildPostList parameters

# Test: Search for buildPostList usage in the start function
rg -A 5 'function start' scripts/index.js | rg 'buildPostList'

Length of output: 62


Script:

#!/bin/bash
# Description: Verify that buildPostList is called with three parameters in scripts/index.js

# Search for buildPostList function calls with exactly three arguments
ast-grep --pattern 'buildPostList($_, $_, $_)' scripts/index.js

Length of output: 150

scripts/index.js (2)

4-4: LGTM: Import statement updated correctly.

The change to use destructuring for importing buildPostList is consistent with modern JavaScript practices and improves code readability.


19-19: LGTM: Function call updated correctly.

The buildPostList function call has been correctly updated to include the new parameters, which is consistent with the changes in the function's signature.

To ensure that the buildPostList function in the build-post-list.js file correctly handles these new parameters, please run the following verification script:

This script will help verify that the function signature has been updated correctly and that there are no remaining calls to buildPostList without parameters.

scripts/build-post-list.js (6)

2-2: LGTM: Cleaned up imports

Good job on cleaning up the imports by only importing the basename function from the path module. This is a best practice that helps keep the code clean and potentially improves performance.


20-26: Improved readability, but consider removing empty else block

The changes to the addItem function improve readability with better whitespace. However, the empty else { } block at line 26 is still present and serves no purpose. Consider removing it as suggested in the previous review.


29-43: Improved function signature and error handling, but consider preserving error stack trace

The changes to the buildPostList function are good improvements:

  • The updated function signature allows for more flexibility.
  • The new error handling for empty postDirectories is a good addition.
  • Writing to a specified writeFilePath enhances the function's configurability.

However, as mentioned in a previous review, consider preserving the original error stack trace when rethrowing errors. You can do this by either using throw error or using the cause property to retain the error's context.


47-47: LGTM: Updated walkDirectories function signature

The addition of the basePath parameter to the walkDirectories function signature is a good change. It aligns with the updates in the buildPostList function and allows for more flexible handling of directory paths.


99-105: Consider renaming variables and improving consistency

The changes in this section make minor adjustments to the logic for handling specification references. However, as mentioned in a previous review, the variable fileName is still being reused, which could lead to confusion. Consider renaming the inner fileName to something like versionName for clarity.

Also, for consistency, consider using template literals for string concatenation in line 105:

details.title = `${capitalize(fileName.slice(1))}`

Also applies to: 110-110


125-128: Improved exports, but consider refining file name handling

The export of slugifyToC and buildPostList functions is a good practice for modularity. However, there are a couple of points to consider:

  1. As mentioned in a previous review, instead of manually slicing the file name to remove the extension, consider using path.basename and path.extname for safer and more reliable handling of file names and extensions.

  2. The logic for extracting the version from the file name could be simplified and made more robust. Consider using a regular expression to extract the version number directly:

const versionMatch = file.match(/release-notes-(.+)\.md$/);
if (versionMatch) {
  const version = versionMatch[1];
  releaseNotes.push(version);
}

This approach would be more resilient to changes in file naming conventions.

Also applies to: 162-163

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (7)
scripts/build-post-list.js (4)

Line range hint 1-17: Consider refactoring global state management

The result object is maintained as global state, which could lead to issues in concurrent scenarios or when running multiple builds. While the tests currently depend on this global state, consider creating a tracking issue to refactor this in the future.

🧰 Tools
🪛 eslint

[error] 1-1: Insert ;

(prettier/prettier)


[error] 2-2: Insert ;

(prettier/prettier)


[error] 3-3: Insert ;

(prettier/prettier)


[error] 4-4: Insert ;

(prettier/prettier)


[error] 5-5: 'slugify' is assigned a value but never used.

(no-unused-vars)


[error] 5-5: Insert ;

(prettier/prettier)


28-49: Add JSDoc documentation for the buildPostList function

Consider adding JSDoc documentation to describe the function's parameters, return type, and possible errors.

+/**
+ * Builds a list of posts from the specified directories and writes it to a file
+ * @param {Array<Array<string>>} postDirectories - Array of [directory, slug] tuples
+ * @param {string} basePath - Base path for resolving relative paths
+ * @param {string} writeFilePath - Path where the output JSON will be written
+ * @throws {Error} If required parameters are missing or if any operation fails
+ * @returns {Promise<void>}
+ */
 async function buildPostList(postDirectories, basePath, writeFilePath) {
🧰 Tools
🪛 eslint

[error] 29-30: Delete

(prettier/prettier)


[error] 41-41: Insert ;

(prettier/prettier)


[error] 42-42: 'walkDirectories' was used before it was defined.

(no-use-before-define)


[error] 42-42: Insert ;

(prettier/prettier)


[error] 43-43: Replace "docs"].filter((p)·=>·p.slug.startsWith('/docs/'))) with 'docs'].filter((p)·=>·p.slug.startsWith('/docs/')));

(prettier/prettier)


[error] 43-43: ["docs"] is better written in dot notation.

(dot-notation)


[error] 44-44: Replace "docsTree"]·=·treePosts with 'docsTree']·=·treePosts;

(prettier/prettier)


[error] 44-44: ["docsTree"] is better written in dot notation.

(dot-notation)


[error] 45-45: Replace "docs"]·=·addDocButtons(result["docs"],·treePosts) with 'docs']·=·addDocButtons(result['docs'],·treePosts);

(prettier/prettier)


[error] 45-45: ["docs"] is better written in dot notation.

(dot-notation)


[error] 45-45: ["docs"] is better written in dot notation.

(dot-notation)


[error] 46-46: Insert ;

(prettier/prettier)


Line range hint 52-145: Consider breaking down the walkDirectories function

The function is quite long and handles multiple responsibilities. Consider extracting the file processing logic into separate functions for better maintainability:

  • processDirectory
  • processSectionFile
  • processContentFile
🧰 Tools
🪛 eslint

[error] 99-99: Insert ;

(prettier/prettier)


[error] 100-100: Insert ;

(prettier/prettier)


[error] 101-101: Insert ;

(prettier/prettier)


[error] 102-102: Insert ;

(prettier/prettier)


[error] 103-103: Insert ;

(prettier/prettier)


[error] 104-104: Insert ;

(prettier/prettier)


[error] 106-106: Replace · with ;

(prettier/prettier)


[error] 107-107: Insert ;

(prettier/prettier)


[error] 108-108: Unary operator '--' used.

(no-plusplus)


[error] 108-108: Insert ;

(prettier/prettier)


[error] 111-111: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 111-111: Insert ;

(prettier/prettier)


[error] 113-113: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 113-113: Insert ;

(prettier/prettier)


[error] 117-117: Insert ;

(prettier/prettier)


147-165: Add JSDoc documentation for the slugifyToC function

Consider adding JSDoc documentation to explain the function's purpose and behavior.

+/**
+ * Extracts heading IDs from markdown headings
+ * @param {string} str - The heading text containing potential ID
+ * @returns {string} The extracted ID or empty string if no valid ID found
+ */
 function slugifyToC(str) {
🧰 Tools
🪛 Biome (1.9.4)

[error] 153-153: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 158-158: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🪛 eslint

[error] 154-154: Use array destructuring.

(prefer-destructuring)


[error] 159-159: Use array destructuring.

(prefer-destructuring)

tests/build-post-list.test.js (3)

6-27: Consider using a custom test environment

The setup and teardown of the temporary directory could be moved to a custom Jest environment to reduce boilerplate in test files.

🧰 Tools
🪛 eslint

[error] 17-17: Delete ,

(prettier/prettier)


[error] 20-21: Delete

(prettier/prettier)


28-93: Group related test cases using nested describe blocks

Consider organizing related test cases into nested describe blocks for better readability:

 describe('buildPostList', () => {
+  describe('File Operations', () => {
     it('writes the file successfully', ...);
     it('writes valid JSON content', ...);
+  });
+
+  describe('Content Structure', () => {
     it('correctly structures docs entries', ...);
     it('correctly structures blog entries', ...);
+  });
🧰 Tools
🪛 eslint

[error] 33-33: Delete ··

(prettier/prettier)


[error] 48-48: Delete ,

(prettier/prettier)


[error] 53-53: Delete ,

(prettier/prettier)


[error] 58-58: Delete ,

(prettier/prettier)


[error] 59-59: Delete ,

(prettier/prettier)


[error] 60-60: Delete ,

(prettier/prettier)


[error] 72-72: Delete ,

(prettier/prettier)


[error] 73-73: Delete ,

(prettier/prettier)


[error] 74-74: Delete ,

(prettier/prettier)


[error] 81-81: Delete ,

(prettier/prettier)


[error] 82-82: Delete ,

(prettier/prettier)


[error] 83-83: Delete ,

(prettier/prettier)


[error] 88-90: Replace ⏎······(item)·=>·item.slug·===·'/blog/release-notes-2.1.0',⏎···· with (item)·=>·item.slug·===·'/blog/release-notes-2.1.0'

(prettier/prettier)


229-264: Add test cases for edge cases in slugifyToC

The test coverage for slugifyToC is good, but consider adding these edge cases:

  • Headings with multiple IDs of the same type
  • Very long heading IDs
  • Unicode characters in heading IDs
🧰 Tools
🪛 eslint

[error] 243-243: Delete ····

(prettier/prettier)


[error] 249-249: Delete ····

(prettier/prettier)

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 89f7fbc and c951b91.

📒 Files selected for processing (2)
  • scripts/build-post-list.js (7 hunks)
  • tests/build-post-list.test.js (1 hunks)
🧰 Additional context used
📓 Learnings (1)
scripts/build-post-list.js (2)
Learnt from: vishvamsinh28
PR: asyncapi/website#3284
File: scripts/build-post-list.js:28-46
Timestamp: 2024-11-12T06:59:33.852Z
Learning: In the `scripts/build-post-list.js` JavaScript file, tests rely on the `result` object being a global variable. Moving it inside the `buildPostList` function causes tests to fail; therefore, keep `result` as a global variable.
Learnt from: vishvamsinh28
PR: asyncapi/website#3284
File: scripts/build-post-list.js:49-53
Timestamp: 2024-11-12T06:59:33.851Z
Learning: In `scripts/build-post-list.js`, the `walkDirectories` function depends on sequential execution because it mutates `resultObj`. Parallelizing the loop with `Promise.all` causes tests to fail.
🪛 eslint
scripts/build-post-list.js

[error] 1-1: Insert ;

(prettier/prettier)


[error] 2-2: Insert ;

(prettier/prettier)


[error] 20-21: Replace ⏎····result["docs"].push(details) with ·result['docs'].push(details);

(prettier/prettier)


[error] 21-21: ["docs"] is better written in dot notation.

(dot-notation)


[error] 22-23: Replace ⏎····result["blog"].push(details) with ·result['blog'].push(details);

(prettier/prettier)


[error] 23-23: ["blog"] is better written in dot notation.

(dot-notation)


[error] 24-25: Replace ⏎····result["about"].push(details) with ·result['about'].push(details);

(prettier/prettier)


[error] 25-25: ["about"] is better written in dot notation.

(dot-notation)


[error] 29-30: Delete

(prettier/prettier)


[error] 41-41: Insert ;

(prettier/prettier)


[error] 42-42: 'walkDirectories' was used before it was defined.

(no-use-before-define)


[error] 42-42: Insert ;

(prettier/prettier)


[error] 43-43: Replace "docs"].filter((p)·=>·p.slug.startsWith('/docs/'))) with 'docs'].filter((p)·=>·p.slug.startsWith('/docs/')));

(prettier/prettier)


[error] 43-43: ["docs"] is better written in dot notation.

(dot-notation)


[error] 44-44: Replace "docsTree"]·=·treePosts with 'docsTree']·=·treePosts;

(prettier/prettier)


[error] 44-44: ["docsTree"] is better written in dot notation.

(dot-notation)


[error] 45-45: Replace "docs"]·=·addDocButtons(result["docs"],·treePosts) with 'docs']·=·addDocButtons(result['docs'],·treePosts);

(prettier/prettier)


[error] 45-45: ["docs"] is better written in dot notation.

(dot-notation)


[error] 45-45: ["docs"] is better written in dot notation.

(dot-notation)


[error] 46-46: Insert ;

(prettier/prettier)


[error] 52-52: This line has a length of 125. Maximum allowed is 120.

(max-len)


[error] 52-52: Replace directories,·resultObj,·basePath,·sectionTitle,·sectionId,·rootSectionId,·sectionWeight·=·0 with ⏎··directories,⏎··resultObj,⏎··basePath,⏎··sectionTitle,⏎··sectionId,⏎··rootSectionId,⏎··sectionWeight·=·0⏎

(prettier/prettier)


[error] 53-53: 'dir' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 54-54: 'directory' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 55-55: 'sectionSlug' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 56-56: 'files' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 56-56: Unexpected await inside a loop.

(no-await-in-loop)


[error] 56-56: Insert ;

(prettier/prettier)


[error] 58-58: 'file' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 61-61: Insert ;

(prettier/prettier)


[error] 62-62: Unexpected string concatenation.

(prefer-template)


[error] 62-62: Insert ;

(prettier/prettier)


[error] 63-63: Insert ;

(prettier/prettier)


[error] 65-65: Unexpected await inside a loop.

(no-await-in-loop)


[error] 65-65: 'isDirectory' was used before it was defined.

(no-use-before-define)


[error] 66-66: Unexpected await inside a loop.

(no-await-in-loop)


[error] 68-68: Unexpected await inside a loop.

(no-await-in-loop)


[error] 68-68: Insert ;

(prettier/prettier)


[error] 77-77: Insert ;

(prettier/prettier)


[error] 78-78: Insert ;

(prettier/prettier)


[error] 88-88: This line has a length of 135. Maximum allowed is 120.

(max-len)


[error] 88-88: Unexpected await inside a loop.

(no-await-in-loop)


[error] 88-88: Replace [[fileName,·slug]],·resultObj,·basePath,·details.title,·details.sectionId,·rootId,·details.sectionWeight) with ⏎··········[[fileName,·slug]],⏎··········resultObj,⏎··········basePath,⏎··········details.title,⏎··········details.sectionId,⏎··········rootId,⏎··········details.sectionWeight⏎········);

(prettier/prettier)


[error] 89-89: Unexpected string concatenation.

(prefer-template)


[error] 90-90: Unexpected await inside a loop.

(no-await-in-loop)


[error] 90-90: Insert ;

(prettier/prettier)


[error] 102-102: Insert ;

(prettier/prettier)


[error] 103-103: Insert ;

(prettier/prettier)


[error] 104-104: Insert ;

(prettier/prettier)


[error] 106-106: Replace · with ;

(prettier/prettier)


[error] 107-107: Insert ;

(prettier/prettier)


[error] 108-108: Unary operator '--' used.

(no-plusplus)


[error] 108-108: Insert ;

(prettier/prettier)


[error] 111-111: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 111-111: Insert ;

(prettier/prettier)


[error] 113-113: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 113-113: Insert ;

(prettier/prettier)


[error] 131-131: Replace "release-notes")·&&·dir[1]·===·"/blog" with 'release-notes')·&&·dir[1]·===·'/blog'

(prettier/prettier)


[error] 132-132: Insert ;

(prettier/prettier)


[error] 134-134: Replace "-")·+·1) with '-')·+·1);

(prettier/prettier)


[error] 136-136: This line has a length of 164. Maximum allowed is 120.

(max-len)


[error] 154-154: Use array destructuring.

(prefer-destructuring)


[error] 159-159: Use array destructuring.

(prefer-destructuring)


[error] 168-168: Insert ;

(prettier/prettier)


[error] 172-172: Insert ;

(prettier/prettier)


[error] 175-175: Insert ;

(prettier/prettier)

tests/build-post-list.test.js

[error] 3-3: Insert ;

(prettier/prettier)


[error] 17-17: Delete ,

(prettier/prettier)


[error] 20-21: Delete

(prettier/prettier)


[error] 33-33: Delete ··

(prettier/prettier)


[error] 48-48: Delete ,

(prettier/prettier)


[error] 53-53: Delete ,

(prettier/prettier)


[error] 58-58: Delete ,

(prettier/prettier)


[error] 59-59: Delete ,

(prettier/prettier)


[error] 60-60: Delete ,

(prettier/prettier)


[error] 72-72: Delete ,

(prettier/prettier)


[error] 73-73: Delete ,

(prettier/prettier)


[error] 74-74: Delete ,

(prettier/prettier)


[error] 81-81: Delete ,

(prettier/prettier)


[error] 82-82: Delete ,

(prettier/prettier)


[error] 83-83: Delete ,

(prettier/prettier)


[error] 88-90: Replace ⏎······(item)·=>·item.slug·===·'/blog/release-notes-2.1.0',⏎···· with (item)·=>·item.slug·===·'/blog/release-notes-2.1.0'

(prettier/prettier)


[error] 99-99: Delete ,

(prettier/prettier)


[error] 110-110: Delete ,

(prettier/prettier)


[error] 117-117: Delete ,

(prettier/prettier)


[error] 124-126: Replace ⏎······(item)·=>·item.slug·===·'/blog/release-notes-2.1.0',⏎···· with (item)·=>·item.slug·===·'/blog/release-notes-2.1.0'

(prettier/prettier)


[error] 127-129: Replace ⏎······(item)·=>·item.slug·===·'/blog/release-notes-2.1.1',⏎···· with (item)·=>·item.slug·===·'/blog/release-notes-2.1.1'

(prettier/prettier)


[error] 140-142: Replace ⏎······buildPostList([invalidDir],·tempDir,·writeFilePath),⏎····).rejects.toThrow(/Error·while·building·post·list:·ENOENT/ with buildPostList([invalidDir],·tempDir,·writeFilePath)).rejects.toThrow(⏎······/Error·while·building·post·list:·ENOENT/⏎····

(prettier/prettier)


[error] 147-150: Replace ⏎······join(specDir,·'v2.1.0-no-title.mdx'),⏎······'---\n---\nContent·of·specification·without·a·title.',⏎···· with join(specDir,·'v2.1.0-no-title.mdx'),·'---\n---\nContent·of·specification·without·a·title.'

(prettier/prettier)


[error] 155-157: Replace ⏎······item.slug.includes('/reference/specification/v2.1.0-no-title'),⏎···· with ·item.slug.includes('/reference/specification/v2.1.0-no-title')

(prettier/prettier)


[error] 166-166: Delete ,

(prettier/prettier)


[error] 172-174: Replace ⏎······item.slug.includes('/reference/specification/v2.1.0-next-spec.1'),⏎···· with ·item.slug.includes('/reference/specification/v2.1.0-next-spec.1')

(prettier/prettier)


[error] 181-184: Replace ⏎······join(specDir,·'explorer.mdx'),⏎······'---\n---\nContent·of·explorer·specification.',⏎···· with join(specDir,·'explorer.mdx'),·'---\n---\nContent·of·explorer·specification.'

(prettier/prettier)


[error] 189-191: Replace ⏎······item.slug.includes('/reference/specification/explorer'),⏎···· with ·item.slug.includes('/reference/specification/explorer')

(prettier/prettier)


[error] 197-200: Replace ⏎······join(tempDir,·'docs',·'invalid.mdx'),⏎······'---\ninvalid·front·matter\n---\nContent',⏎···· with join(tempDir,·'docs',·'invalid.mdx'),·'---\ninvalid·front·matter\n---\nContent'

(prettier/prettier)


[error] 202-204: Replace ⏎······buildPostList(postDirectories,·tempDir,·writeFilePath),⏎····).rejects.toThrow(/Error·while·building·post·list/ with buildPostList(postDirectories,·tempDir,·writeFilePath)).rejects.toThrow(⏎······/Error·while·building·post·list/⏎····

(prettier/prettier)


[error] 208-210: Replace ⏎······/Error·while·building·post·list/,⏎···· with /Error·while·building·post·list/

(prettier/prettier)


[error] 214-216: Replace ⏎······buildPostList(postDirectories,·undefined,·writeFilePath),⏎···· with buildPostList(postDirectories,·undefined,·writeFilePath)

(prettier/prettier)


[error] 217-217: Replace "Error·while·building·post·list:·basePath·is·required", with 'Error·while·building·post·list:·basePath·is·required'

(prettier/prettier)


[error] 222-224: Replace ⏎······buildPostList(postDirectories,·tempDir,·undefined),⏎···· with buildPostList(postDirectories,·tempDir,·undefined)

(prettier/prettier)


[error] 225-225: Replace "Error·while·building·post·list:·writeFilePath·is·required", with 'Error·while·building·post·list:·writeFilePath·is·required'

(prettier/prettier)


[error] 243-243: Delete ····

(prettier/prettier)


[error] 249-249: Delete ····

(prettier/prettier)

🪛 Biome (1.9.4)
scripts/build-post-list.js

[error] 153-153: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 158-158: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
scripts/build-post-list.js (3)

39-44: Improve error message clarity

The error message construction could be more explicit about the context.

-      throw new Error(`${missing.join(' and ')} ${missing.length > 1 ? 'are' : 'is'} required`);
+      throw new Error(`Error while building post list: ${missing.join(' and ')} ${missing.length > 1 ? 'are' : 'is'} required`);

96-96: Fix line length for better readability

This line exceeds the maximum length of 120 characters.

-        await walkDirectories([[fileName, slug]], resultObj, basePath, details.title, details.sectionId, rootId, details.sectionWeight)
+        await walkDirectories(
+          [[fileName, slug]],
+          resultObj,
+          basePath,
+          details.title,
+          details.sectionId,
+          rootId,
+          details.sectionWeight
+        )
🧰 Tools
🪛 eslint

[error] 96-96: This line has a length of 135. Maximum allowed is 120.

(max-len)


[error] 96-96: Unexpected await inside a loop.

(no-await-in-loop)


[error] 96-96: Replace [[fileName,·slug]],·resultObj,·basePath,·details.title,·details.sectionId,·rootId,·details.sectionWeight) with ⏎··········[[fileName,·slug]],⏎··········resultObj,⏎··········basePath,⏎··········details.title,⏎··········details.sectionId,⏎··········rootId,⏎··········details.sectionWeight⏎········);

(prettier/prettier)


164-173: Use optional chaining for safer property access

The code can be simplified using optional chaining.

-  const headingIdMatch = str.match(/[\s]*\{#([a-zA-Z0-9\-_]+)\}/);
-  if (headingIdMatch && headingIdMatch[1].trim()) {
+  const headingIdMatch = str.match(/[\s]*\{#([a-zA-Z0-9\-_]+)\}/);
+  if (headingIdMatch?.[1]?.trim()) {
     slug = headingIdMatch[1];
   } else {
     const anchorTagMatch = str.match(/[\s]*<a[\s]+name="([a-zA-Z0-9\-_]+)"/);
-    if (anchorTagMatch && anchorTagMatch[1].trim()) {
+    if (anchorTagMatch?.[1]?.trim()) {
       slug = anchorTagMatch[1];
     }
   }
🧰 Tools
🪛 Biome (1.9.4)

[error] 166-166: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 171-171: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🪛 eslint

[error] 167-167: Use array destructuring.

(prefer-destructuring)


[error] 172-172: Use array destructuring.

(prefer-destructuring)

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c951b91 and 19f7c4f.

📒 Files selected for processing (1)
  • scripts/build-post-list.js (7 hunks)
🧰 Additional context used
📓 Learnings (1)
scripts/build-post-list.js (2)
Learnt from: vishvamsinh28
PR: asyncapi/website#3284
File: scripts/build-post-list.js:28-46
Timestamp: 2024-11-12T06:59:33.852Z
Learning: In the `scripts/build-post-list.js` JavaScript file, tests rely on the `result` object being a global variable. Moving it inside the `buildPostList` function causes tests to fail; therefore, keep `result` as a global variable.
Learnt from: vishvamsinh28
PR: asyncapi/website#3284
File: scripts/build-post-list.js:49-53
Timestamp: 2024-11-12T06:59:33.851Z
Learning: In `scripts/build-post-list.js`, the `walkDirectories` function depends on sequential execution because it mutates `resultObj`. Parallelizing the loop with `Promise.all` causes tests to fail.
🪛 eslint
scripts/build-post-list.js

[error] 1-1: Insert ;

(prettier/prettier)


[error] 2-2: Insert ;

(prettier/prettier)


[error] 20-21: Replace ⏎····result["docs"].push(details) with ·result['docs'].push(details);

(prettier/prettier)


[error] 21-21: ["docs"] is better written in dot notation.

(dot-notation)


[error] 22-23: Replace ⏎····result["blog"].push(details) with ·result['blog'].push(details);

(prettier/prettier)


[error] 23-23: ["blog"] is better written in dot notation.

(dot-notation)


[error] 24-25: Replace ⏎····result["about"].push(details) with ·result['about'].push(details);

(prettier/prettier)


[error] 25-25: ["about"] is better written in dot notation.

(dot-notation)


[error] 38-39: Delete

(prettier/prettier)


[error] 49-49: Insert ;

(prettier/prettier)


[error] 50-50: 'walkDirectories' was used before it was defined.

(no-use-before-define)


[error] 50-50: Insert ;

(prettier/prettier)


[error] 51-51: Replace "docs"].filter((p)·=>·p.slug.startsWith('/docs/'))) with 'docs'].filter((p)·=>·p.slug.startsWith('/docs/')));

(prettier/prettier)


[error] 51-51: ["docs"] is better written in dot notation.

(dot-notation)


[error] 52-52: Replace "docsTree"]·=·treePosts with 'docsTree']·=·treePosts;

(prettier/prettier)


[error] 52-52: ["docsTree"] is better written in dot notation.

(dot-notation)


[error] 53-53: Replace "docs"]·=·addDocButtons(result["docs"],·treePosts) with 'docs']·=·addDocButtons(result['docs'],·treePosts);

(prettier/prettier)


[error] 53-53: ["docs"] is better written in dot notation.

(dot-notation)


[error] 53-53: ["docs"] is better written in dot notation.

(dot-notation)


[error] 54-54: Insert ;

(prettier/prettier)


[error] 60-60: This line has a length of 125. Maximum allowed is 120.

(max-len)


[error] 60-60: Replace directories,·resultObj,·basePath,·sectionTitle,·sectionId,·rootSectionId,·sectionWeight·=·0 with ⏎··directories,⏎··resultObj,⏎··basePath,⏎··sectionTitle,⏎··sectionId,⏎··rootSectionId,⏎··sectionWeight·=·0⏎

(prettier/prettier)


[error] 61-61: 'dir' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 62-62: 'directory' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 63-63: 'sectionSlug' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 64-64: 'files' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 64-64: Unexpected await inside a loop.

(no-await-in-loop)


[error] 64-64: Insert ;

(prettier/prettier)


[error] 66-66: 'file' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 69-69: Insert ;

(prettier/prettier)


[error] 70-70: Unexpected string concatenation.

(prefer-template)


[error] 70-70: Insert ;

(prettier/prettier)


[error] 71-71: Insert ;

(prettier/prettier)


[error] 73-73: Unexpected await inside a loop.

(no-await-in-loop)


[error] 73-73: 'isDirectory' was used before it was defined.

(no-use-before-define)


[error] 74-74: Unexpected await inside a loop.

(no-await-in-loop)


[error] 76-76: Unexpected await inside a loop.

(no-await-in-loop)


[error] 76-76: Insert ;

(prettier/prettier)


[error] 85-85: Insert ;

(prettier/prettier)


[error] 86-86: Insert ;

(prettier/prettier)


[error] 96-96: This line has a length of 135. Maximum allowed is 120.

(max-len)


[error] 96-96: Unexpected await inside a loop.

(no-await-in-loop)


[error] 96-96: Replace [[fileName,·slug]],·resultObj,·basePath,·details.title,·details.sectionId,·rootId,·details.sectionWeight) with ⏎··········[[fileName,·slug]],⏎··········resultObj,⏎··········basePath,⏎··········details.title,⏎··········details.sectionId,⏎··········rootId,⏎··········details.sectionWeight⏎········);

(prettier/prettier)


[error] 97-97: Unexpected string concatenation.

(prefer-template)


[error] 98-98: Unexpected await inside a loop.

(no-await-in-loop)


[error] 98-98: Insert ;

(prettier/prettier)


[error] 110-110: Insert ;

(prettier/prettier)


[error] 111-111: Insert ;

(prettier/prettier)


[error] 112-112: Insert ;

(prettier/prettier)


[error] 114-114: Replace · with ;

(prettier/prettier)


[error] 115-115: Insert ;

(prettier/prettier)


[error] 116-116: Unary operator '--' used.

(no-plusplus)


[error] 116-116: Insert ;

(prettier/prettier)


[error] 119-119: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 119-119: Insert ;

(prettier/prettier)


[error] 121-121: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 121-121: Insert ;

(prettier/prettier)


[error] 139-139: Replace "release-notes")·&&·dir[1]·===·"/blog" with 'release-notes')·&&·dir[1]·===·'/blog'

(prettier/prettier)


[error] 140-140: Insert ;

(prettier/prettier)


[error] 142-142: Replace "-")·+·1) with '-')·+·1);

(prettier/prettier)


[error] 144-144: This line has a length of 164. Maximum allowed is 120.

(max-len)


[error] 167-167: Use array destructuring.

(prefer-destructuring)


[error] 172-172: Use array destructuring.

(prefer-destructuring)


[error] 181-181: Insert ;

(prettier/prettier)


[error] 185-185: Insert ;

(prettier/prettier)


[error] 188-188: Insert ;

(prettier/prettier)

🪛 Biome (1.9.4)
scripts/build-post-list.js

[error] 166-166: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 171-171: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (2)
scripts/build-post-list.js (2)

1-2: LGTM! Good choice using fs-extra

The switch to fs-extra is a good improvement as it provides Promise-based APIs and automatic directory creation, making the code more robust and easier to maintain.

🧰 Tools
🪛 eslint

[error] 1-1: Insert ;

(prettier/prettier)


[error] 2-2: Insert ;

(prettier/prettier)


180-188: LGTM! Good async conversion

The conversion of isDirectory to async and the addition of slugifyToC to exports are appropriate changes that align with the module's async nature.

🧰 Tools
🪛 eslint

[error] 181-181: Insert ;

(prettier/prettier)


[error] 185-185: Insert ;

(prettier/prettier)


[error] 188-188: Insert ;

(prettier/prettier)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
scripts/build-post-list.js (3)

20-26: Use dot notation for object property access

Consider using dot notation instead of bracket notation for better readability and consistency.

-  if (details.slug.startsWith('/docs'))
-    result["docs"].push(details)
-  else if (details.slug.startsWith('/blog'))
-    result["blog"].push(details)
-  else if (details.slug.startsWith('/about'))
-    result["about"].push(details)
+  if (details.slug.startsWith('/docs'))
+    result.docs.push(details)
+  else if (details.slug.startsWith('/blog'))
+    result.blog.push(details)
+  else if (details.slug.startsWith('/about'))
+    result.about.push(details)
🧰 Tools
🪛 eslint

[error] 20-21: Replace ⏎····result["docs"].push(details) with ·result['docs'].push(details);

(prettier/prettier)


[error] 21-21: ["docs"] is better written in dot notation.

(dot-notation)


[error] 22-23: Replace ⏎····result["blog"].push(details) with ·result['blog'].push(details);

(prettier/prettier)


[error] 23-23: ["blog"] is better written in dot notation.

(dot-notation)


[error] 24-25: Replace ⏎····result["about"].push(details) with ·result['about'].push(details);

(prettier/prettier)


[error] 25-25: ["about"] is better written in dot notation.

(dot-notation)


28-56: Consider using specific error types

The error handling is good, but consider creating specific error types for different failure scenarios. This would make it easier for consumers to handle different types of errors differently.

Example implementation:

class PostListError extends Error {
  constructor(message, type) {
    super(message);
    this.name = 'PostListError';
    this.type = type;
  }
}

// Usage in your error handling:
if (!basePath || !writeFilePath) {
  throw new PostListError(
    `Error while building post list: ${missing.join(' and ')} ${missing.length > 1 ? 'are' : 'is'} required`,
    'MISSING_PARAMS'
  );
}
🧰 Tools
🪛 eslint

[error] 38-39: Delete

(prettier/prettier)


[error] 43-43: Replace Error·while·building·post·list:·${missing.join('·and·')}·${missing.length·>·1·?·'are'·:·'is'}·required with ⏎········Error·while·building·post·list:·${missing.join('·and·')}·${missing.length·>·1·?·'are'·:·'is'}·required⏎······

(prettier/prettier)


[error] 49-49: Insert ;

(prettier/prettier)


[error] 50-50: 'walkDirectories' was used before it was defined.

(no-use-before-define)


[error] 50-50: Insert ;

(prettier/prettier)


[error] 51-51: Replace "docs"].filter((p)·=>·p.slug.startsWith('/docs/'))) with 'docs'].filter((p)·=>·p.slug.startsWith('/docs/')));

(prettier/prettier)


[error] 51-51: ["docs"] is better written in dot notation.

(dot-notation)


[error] 52-52: Replace "docsTree"]·=·treePosts with 'docsTree']·=·treePosts;

(prettier/prettier)


[error] 52-52: ["docsTree"] is better written in dot notation.

(dot-notation)


[error] 53-53: Replace "docs"]·=·addDocButtons(result["docs"],·treePosts) with 'docs']·=·addDocButtons(result['docs'],·treePosts);

(prettier/prettier)


[error] 53-53: ["docs"] is better written in dot notation.

(dot-notation)


[error] 53-53: ["docs"] is better written in dot notation.

(dot-notation)


[error] 54-54: Insert ;

(prettier/prettier)


104-104: Format long line for better readability

The line exceeds the maximum length of 120 characters. Consider breaking it into multiple lines.

-        await walkDirectories([[fileName, slug]], resultObj, basePath, details.title, details.sectionId, rootId, details.sectionWeight)
+        await walkDirectories(
+          [[fileName, slug]],
+          resultObj,
+          basePath,
+          details.title,
+          details.sectionId,
+          rootId,
+          details.sectionWeight
+        )
🧰 Tools
🪛 eslint

[error] 104-104: This line has a length of 135. Maximum allowed is 120.

(max-len)


[error] 104-104: Unexpected await inside a loop.

(no-await-in-loop)


[error] 104-104: Replace [[fileName,·slug]],·resultObj,·basePath,·details.title,·details.sectionId,·rootId,·details.sectionWeight) with ⏎··········[[fileName,·slug]],⏎··········resultObj,⏎··········basePath,⏎··········details.title,⏎··········details.sectionId,⏎··········rootId,⏎··········details.sectionWeight⏎········);

(prettier/prettier)

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 19f7c4f and 893ac66.

📒 Files selected for processing (1)
  • scripts/build-post-list.js (7 hunks)
🧰 Additional context used
📓 Learnings (1)
scripts/build-post-list.js (2)
Learnt from: vishvamsinh28
PR: asyncapi/website#3284
File: scripts/build-post-list.js:28-46
Timestamp: 2024-11-12T06:59:33.852Z
Learning: In the `scripts/build-post-list.js` JavaScript file, tests rely on the `result` object being a global variable. Moving it inside the `buildPostList` function causes tests to fail; therefore, keep `result` as a global variable.
Learnt from: vishvamsinh28
PR: asyncapi/website#3284
File: scripts/build-post-list.js:49-53
Timestamp: 2024-11-12T06:59:33.851Z
Learning: In `scripts/build-post-list.js`, the `walkDirectories` function depends on sequential execution because it mutates `resultObj`. Parallelizing the loop with `Promise.all` causes tests to fail.
🪛 eslint
scripts/build-post-list.js

[error] 1-1: Insert ;

(prettier/prettier)


[error] 2-2: Insert ;

(prettier/prettier)


[error] 20-21: Replace ⏎····result["docs"].push(details) with ·result['docs'].push(details);

(prettier/prettier)


[error] 21-21: ["docs"] is better written in dot notation.

(dot-notation)


[error] 22-23: Replace ⏎····result["blog"].push(details) with ·result['blog'].push(details);

(prettier/prettier)


[error] 23-23: ["blog"] is better written in dot notation.

(dot-notation)


[error] 24-25: Replace ⏎····result["about"].push(details) with ·result['about'].push(details);

(prettier/prettier)


[error] 25-25: ["about"] is better written in dot notation.

(dot-notation)


[error] 38-39: Delete

(prettier/prettier)


[error] 43-43: Replace Error·while·building·post·list:·${missing.join('·and·')}·${missing.length·>·1·?·'are'·:·'is'}·required with ⏎········Error·while·building·post·list:·${missing.join('·and·')}·${missing.length·>·1·?·'are'·:·'is'}·required⏎······

(prettier/prettier)


[error] 49-49: Insert ;

(prettier/prettier)


[error] 50-50: 'walkDirectories' was used before it was defined.

(no-use-before-define)


[error] 50-50: Insert ;

(prettier/prettier)


[error] 51-51: Replace "docs"].filter((p)·=>·p.slug.startsWith('/docs/'))) with 'docs'].filter((p)·=>·p.slug.startsWith('/docs/')));

(prettier/prettier)


[error] 51-51: ["docs"] is better written in dot notation.

(dot-notation)


[error] 52-52: Replace "docsTree"]·=·treePosts with 'docsTree']·=·treePosts;

(prettier/prettier)


[error] 52-52: ["docsTree"] is better written in dot notation.

(dot-notation)


[error] 53-53: Replace "docs"]·=·addDocButtons(result["docs"],·treePosts) with 'docs']·=·addDocButtons(result['docs'],·treePosts);

(prettier/prettier)


[error] 53-53: ["docs"] is better written in dot notation.

(dot-notation)


[error] 53-53: ["docs"] is better written in dot notation.

(dot-notation)


[error] 54-54: Insert ;

(prettier/prettier)


[error] 69-69: 'dir' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 70-70: 'directory' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 71-71: 'sectionSlug' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 72-72: 'files' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 72-72: Unexpected await inside a loop.

(no-await-in-loop)


[error] 72-72: Insert ;

(prettier/prettier)


[error] 74-74: 'file' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 77-77: Insert ;

(prettier/prettier)


[error] 78-78: Unexpected string concatenation.

(prefer-template)


[error] 78-78: Insert ;

(prettier/prettier)


[error] 79-79: Insert ;

(prettier/prettier)


[error] 81-81: Unexpected await inside a loop.

(no-await-in-loop)


[error] 81-81: 'isDirectory' was used before it was defined.

(no-use-before-define)


[error] 82-82: Unexpected await inside a loop.

(no-await-in-loop)


[error] 84-84: Unexpected await inside a loop.

(no-await-in-loop)


[error] 84-84: Insert ;

(prettier/prettier)


[error] 93-93: Insert ;

(prettier/prettier)


[error] 94-94: Insert ;

(prettier/prettier)


[error] 104-104: This line has a length of 135. Maximum allowed is 120.

(max-len)


[error] 104-104: Unexpected await inside a loop.

(no-await-in-loop)


[error] 104-104: Replace [[fileName,·slug]],·resultObj,·basePath,·details.title,·details.sectionId,·rootId,·details.sectionWeight) with ⏎··········[[fileName,·slug]],⏎··········resultObj,⏎··········basePath,⏎··········details.title,⏎··········details.sectionId,⏎··········rootId,⏎··········details.sectionWeight⏎········);

(prettier/prettier)


[error] 105-105: Unexpected string concatenation.

(prefer-template)


[error] 106-106: Unexpected await inside a loop.

(no-await-in-loop)


[error] 106-106: Insert ;

(prettier/prettier)


[error] 118-118: Insert ;

(prettier/prettier)


[error] 119-119: Insert ;

(prettier/prettier)


[error] 120-120: Insert ;

(prettier/prettier)


[error] 122-122: Replace · with ;

(prettier/prettier)


[error] 123-123: Insert ;

(prettier/prettier)


[error] 124-124: Unary operator '--' used.

(no-plusplus)


[error] 124-124: Insert ;

(prettier/prettier)


[error] 127-127: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 127-127: Insert ;

(prettier/prettier)


[error] 129-129: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 129-129: Insert ;

(prettier/prettier)


[error] 147-147: Replace "release-notes")·&&·dir[1]·===·"/blog" with 'release-notes')·&&·dir[1]·===·'/blog'

(prettier/prettier)


[error] 148-148: Insert ;

(prettier/prettier)


[error] 150-150: Replace "-")·+·1) with '-')·+·1);

(prettier/prettier)


[error] 152-152: This line has a length of 164. Maximum allowed is 120.

(max-len)


[error] 175-175: Use array destructuring.

(prefer-destructuring)


[error] 180-180: Use array destructuring.

(prefer-destructuring)


[error] 189-189: Insert ;

(prettier/prettier)


[error] 193-193: Insert ;

(prettier/prettier)


[error] 196-196: Insert ;

(prettier/prettier)

🔇 Additional comments (2)
scripts/build-post-list.js (2)

163-185: Well-structured heading ID extraction

The function is well-documented and properly handles different heading ID formats with good input validation.

🧰 Tools
🪛 eslint

[error] 175-175: Use array destructuring.

(prefer-destructuring)


[error] 180-180: Use array destructuring.

(prefer-destructuring)


188-196: Good async conversion and export structure

The conversion of isDirectory to async and the use of named exports improves the module's consistency and maintainability.

🧰 Tools
🪛 eslint

[error] 189-189: Insert ;

(prettier/prettier)


[error] 193-193: Insert ;

(prettier/prettier)


[error] 196-196: Insert ;

(prettier/prettier)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
scripts/build-post-list.js (4)

51-53: Use dot notation for object access

Replace bracket notation with dot notation for better readability and consistency.

-const treePosts = buildNavTree(result["docs"].filter((p) => p.slug.startsWith('/docs/')))
-result["docsTree"] = treePosts
-result["docs"] = addDocButtons(result["docs"], treePosts)
+const treePosts = buildNavTree(result.docs.filter((p) => p.slug.startsWith('/docs/')))
+result.docsTree = treePosts
+result.docs = addDocButtons(result.docs, treePosts)
🧰 Tools
🪛 eslint

[error] 51-51: Replace "docs"].filter((p)·=>·p.slug.startsWith('/docs/'))) with 'docs'].filter((p)·=>·p.slug.startsWith('/docs/')));

(prettier/prettier)


[error] 51-51: ["docs"] is better written in dot notation.

(dot-notation)


[error] 52-52: Replace "docsTree"]·=·treePosts with 'docsTree']·=·treePosts;

(prettier/prettier)


[error] 52-52: ["docsTree"] is better written in dot notation.

(dot-notation)


[error] 53-53: Replace "docs"]·=·addDocButtons(result["docs"],·treePosts) with 'docs']·=·addDocButtons(result['docs'],·treePosts);

(prettier/prettier)


[error] 53-53: ["docs"] is better written in dot notation.

(dot-notation)


[error] 53-53: ["docs"] is better written in dot notation.

(dot-notation)


70-72: Use const for variables that aren't reassigned

These variables aren't reassigned after initialization, so they should use const.

-    let directory = posix.normalize(dir[0]);
-    let sectionSlug = dir[1] || '';
-    let files = await readdir(directory)
+    const directory = posix.normalize(dir[0]);
+    const sectionSlug = dir[1] || '';
+    const files = await readdir(directory)
🧰 Tools
🪛 eslint

[error] 70-70: 'directory' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 71-71: 'sectionSlug' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 72-72: 'files' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 72-72: Unexpected await inside a loop.

(no-await-in-loop)


[error] 72-72: Insert ;

(prettier/prettier)


104-104: Split long line for better readability

This line exceeds the maximum length of 120 characters.

-        await walkDirectories([[fileName, slug]], resultObj, basePath, details.title, details.sectionId, rootId, details.sectionWeight)
+        await walkDirectories(
+          [[fileName, slug]],
+          resultObj,
+          basePath,
+          details.title,
+          details.sectionId,
+          rootId,
+          details.sectionWeight
+        )
🧰 Tools
🪛 eslint

[error] 104-104: This line has a length of 135. Maximum allowed is 120.

(max-len)


[error] 104-104: Unexpected await inside a loop.

(no-await-in-loop)


[error] 104-104: Replace [[fileName,·slug]],·resultObj,·basePath,·details.title,·details.sectionId,·rootId,·details.sectionWeight) with ⏎··········[[fileName,·slug]],⏎··········resultObj,⏎··········basePath,⏎··········details.title,⏎··········details.sectionId,⏎··········rootId,⏎··········details.sectionWeight⏎········);

(prettier/prettier)


163-185: Consider additional improvements to slugifyToC

The function is well-implemented, but could be enhanced:

  1. Use destructuring for regex matches
  2. Add validation for malformed heading IDs
 function slugifyToC(str) {
   if (typeof str !== 'string') return '';
   let slug = '';

   // Match heading IDs like {# myHeadingId}
   const headingIdMatch = str.match(/[\s]*\{#([a-zA-Z0-9\-_]+)\}/);
-  if (headingIdMatch?.[1]?.trim()) {
-    slug = headingIdMatch[1];
+  const [, headingId] = headingIdMatch || [];
+  if (headingId?.trim()) {
+    slug = headingId;
   } else {
     // Match heading IDs like {<a name="myHeadingId"/>}
     const anchorTagMatch = str.match(/[\s]*<a[\s]+name="([a-zA-Z0-9\-_]+)"/);
-    if (anchorTagMatch?.[1]?.trim()) {
-      slug = anchorTagMatch[1];
+    const [, anchorId] = anchorTagMatch || [];
+    if (anchorId?.trim()) {
+      slug = anchorId;
     }
   }

   return slug;
 }
🧰 Tools
🪛 eslint

[error] 175-175: Use array destructuring.

(prefer-destructuring)


[error] 180-180: Use array destructuring.

(prefer-destructuring)

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 893ac66 and 069128a.

📒 Files selected for processing (1)
  • scripts/build-post-list.js (7 hunks)
🧰 Additional context used
📓 Learnings (1)
scripts/build-post-list.js (2)
Learnt from: vishvamsinh28
PR: asyncapi/website#3284
File: scripts/build-post-list.js:28-46
Timestamp: 2024-11-12T06:59:33.852Z
Learning: In the `scripts/build-post-list.js` JavaScript file, tests rely on the `result` object being a global variable. Moving it inside the `buildPostList` function causes tests to fail; therefore, keep `result` as a global variable.
Learnt from: vishvamsinh28
PR: asyncapi/website#3284
File: scripts/build-post-list.js:49-53
Timestamp: 2024-11-12T06:59:33.851Z
Learning: In `scripts/build-post-list.js`, the `walkDirectories` function depends on sequential execution because it mutates `resultObj`. Parallelizing the loop with `Promise.all` causes tests to fail.
🪛 eslint
scripts/build-post-list.js

[error] 1-1: Insert ;

(prettier/prettier)


[error] 2-2: Insert ;

(prettier/prettier)


[error] 20-21: Replace ⏎····result.docs.push(details) with ·result.docs.push(details);

(prettier/prettier)


[error] 22-23: Replace ⏎····result.blog.push(details) with ·result.blog.push(details);

(prettier/prettier)


[error] 24-25: Replace ⏎····result.about.push(details) with ·result.about.push(details);

(prettier/prettier)


[error] 37-38: Delete

(prettier/prettier)


[error] 43-43: Replace Error·while·building·post·list:·${missing.join('·and·')}·${missing.length·>·1·?·'are'·:·'is'}·required with ⏎········Error·while·building·post·list:·${missing.join('·and·')}·${missing.length·>·1·?·'are'·:·'is'}·required⏎······

(prettier/prettier)


[error] 49-49: Insert ;

(prettier/prettier)


[error] 50-50: 'walkDirectories' was used before it was defined.

(no-use-before-define)


[error] 50-50: Insert ;

(prettier/prettier)


[error] 51-51: Replace "docs"].filter((p)·=>·p.slug.startsWith('/docs/'))) with 'docs'].filter((p)·=>·p.slug.startsWith('/docs/')));

(prettier/prettier)


[error] 51-51: ["docs"] is better written in dot notation.

(dot-notation)


[error] 52-52: Replace "docsTree"]·=·treePosts with 'docsTree']·=·treePosts;

(prettier/prettier)


[error] 52-52: ["docsTree"] is better written in dot notation.

(dot-notation)


[error] 53-53: Replace "docs"]·=·addDocButtons(result["docs"],·treePosts) with 'docs']·=·addDocButtons(result['docs'],·treePosts);

(prettier/prettier)


[error] 53-53: ["docs"] is better written in dot notation.

(dot-notation)


[error] 53-53: ["docs"] is better written in dot notation.

(dot-notation)


[error] 54-54: Insert ;

(prettier/prettier)


[error] 69-69: 'dir' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 70-70: 'directory' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 71-71: 'sectionSlug' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 72-72: 'files' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 72-72: Unexpected await inside a loop.

(no-await-in-loop)


[error] 72-72: Insert ;

(prettier/prettier)


[error] 74-74: 'file' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 77-77: Insert ;

(prettier/prettier)


[error] 78-78: Unexpected string concatenation.

(prefer-template)


[error] 78-78: Insert ;

(prettier/prettier)


[error] 79-79: Insert ;

(prettier/prettier)


[error] 81-81: Unexpected await inside a loop.

(no-await-in-loop)


[error] 81-81: 'isDirectory' was used before it was defined.

(no-use-before-define)


[error] 82-82: Unexpected await inside a loop.

(no-await-in-loop)


[error] 84-84: Unexpected await inside a loop.

(no-await-in-loop)


[error] 84-84: Insert ;

(prettier/prettier)


[error] 93-93: Insert ;

(prettier/prettier)


[error] 94-94: Insert ;

(prettier/prettier)


[error] 104-104: This line has a length of 135. Maximum allowed is 120.

(max-len)


[error] 104-104: Unexpected await inside a loop.

(no-await-in-loop)


[error] 104-104: Replace [[fileName,·slug]],·resultObj,·basePath,·details.title,·details.sectionId,·rootId,·details.sectionWeight) with ⏎··········[[fileName,·slug]],⏎··········resultObj,⏎··········basePath,⏎··········details.title,⏎··········details.sectionId,⏎··········rootId,⏎··········details.sectionWeight⏎········);

(prettier/prettier)


[error] 105-105: Unexpected string concatenation.

(prefer-template)


[error] 106-106: Unexpected await inside a loop.

(no-await-in-loop)


[error] 106-106: Insert ;

(prettier/prettier)


[error] 118-118: Insert ;

(prettier/prettier)


[error] 119-119: Insert ;

(prettier/prettier)


[error] 120-120: Insert ;

(prettier/prettier)


[error] 122-122: Replace · with ;

(prettier/prettier)


[error] 123-123: Insert ;

(prettier/prettier)


[error] 124-124: Unary operator '--' used.

(no-plusplus)


[error] 124-124: Insert ;

(prettier/prettier)


[error] 127-127: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 127-127: Insert ;

(prettier/prettier)


[error] 129-129: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 129-129: Insert ;

(prettier/prettier)


[error] 147-147: Replace "release-notes")·&&·dir[1]·===·"/blog" with 'release-notes')·&&·dir[1]·===·'/blog'

(prettier/prettier)


[error] 148-148: Insert ;

(prettier/prettier)


[error] 150-150: Replace "-")·+·1) with '-')·+·1);

(prettier/prettier)


[error] 152-152: This line has a length of 164. Maximum allowed is 120.

(max-len)


[error] 175-175: Use array destructuring.

(prefer-destructuring)


[error] 180-180: Use array destructuring.

(prefer-destructuring)


[error] 189-189: Insert ;

(prettier/prettier)


[error] 193-193: Insert ;

(prettier/prettier)


[error] 196-196: Insert ;

(prettier/prettier)

🔇 Additional comments (5)
scripts/build-post-list.js (5)

1-2: LGTM: Good choice using fs-extra!

The switch to fs-extra is a good improvement as it provides more robust file operations with built-in directory creation and better error handling.

🧰 Tools
🪛 eslint

[error] 1-1: Insert ;

(prettier/prettier)


[error] 2-2: Insert ;

(prettier/prettier)


28-35: LGTM: Well-documented function signature!

The JSDoc documentation clearly describes the function parameters, return type, and possible errors.


39-48: LGTM: Thorough parameter validation!

The validation logic is well-implemented with clear error messages for missing parameters.

🧰 Tools
🪛 eslint

[error] 43-43: Replace Error·while·building·post·list:·${missing.join('·and·')}·${missing.length·>·1·?·'are'·:·'is'}·required with ⏎········Error·while·building·post·list:·${missing.join('·and·')}·${missing.length·>·1·?·'are'·:·'is'}·required⏎······

(prettier/prettier)


60-68: LGTM: Clear parameter organization!

The function parameters are well-organized with a clear separation of concerns.


196-196: Verify usage of exported functions

The module now exports both slugifyToC and buildPostList. Let's verify their usage.

✅ Verification successful

Both exported functions are used correctly in the codebase

  • buildPostList is imported and used in scripts/index.js for the main functionality
  • slugifyToC is used internally in build-post-list.js as a slugify function for the table of contents
  • Both functions have comprehensive test coverage in tests/build-post-list.test.js
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check usage of exported functions
# Test: Search for imports of these functions
rg -l "require.*build-post-list'\)?$" | xargs rg "(?:slugifyToC|buildPostList)"

Length of output: 3515

🧰 Tools
🪛 eslint

[error] 196-196: Insert ;

(prettier/prettier)

@akshatnema
Copy link
Member

@coderabbitai review

Copy link

coderabbitai bot commented Dec 17, 2024

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
scripts/build-post-list.js (4)

39-44: Simplify error message construction

The current error message construction is overly complex. Consider using template literals more effectively.

-      const missing = [];
-      if (!basePath) missing.push('basePath');
-      if (!writeFilePath) missing.push('writeFilePath');
-      throw new Error(`Error while building post list: ${missing.join(' and ')} ${missing.length > 1 ? 'are' : 'is'} required`);
+      const missing = [
+        !basePath && 'basePath',
+        !writeFilePath && 'writeFilePath'
+      ].filter(Boolean);
+      throw new Error(`Error while building post list: ${missing.join(' and ')} ${missing.length > 1 ? 'are' : 'is'} required`);
🧰 Tools
🪛 eslint

[error] 43-43: Replace Error·while·building·post·list:·${missing.join('·and·')}·${missing.length·>·1·?·'are'·:·'is'}·required with ⏎········Error·while·building·post·list:·${missing.join('·and·')}·${missing.length·>·1·?·'are'·:·'is'}·required⏎······

(prettier/prettier)


70-72: Consider batching file operations

Multiple sequential await calls in loops can impact performance. Consider using Promise.all for file operations where order doesn't matter.

-    const files = await readdir(directory)
+    const files = await Promise.all([
+      readdir(directory),
+      pathExists(directory)
+    ]).then(([files]) => files)
🧰 Tools
🪛 eslint

[error] 72-72: Unexpected await inside a loop.

(no-await-in-loop)


[error] 72-72: Insert ;

(prettier/prettier)


121-130: Improve version name handling logic

The version name extraction and title generation could be more robust. Consider using a regular expression for better pattern matching.

-          const fileBaseName = basename(details.slug)  // ex. v2.0.0 | v2.1.0-next-spec.1
-          const versionName = fileBaseName.split('-')[0] // v2.0.0 | v2.1.0
+          const versionMatch = basename(details.slug).match(/^(v\d+\.\d+\.\d+)/)
+          const versionName = versionMatch ? versionMatch[1] : basename(details.slug)
🧰 Tools
🪛 eslint

[error] 122-122: Replace · with ;

(prettier/prettier)


[error] 123-123: Insert ;

(prettier/prettier)


[error] 124-124: Unary operator '--' used.

(no-plusplus)


[error] 124-124: Insert ;

(prettier/prettier)


[error] 127-127: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 127-127: Insert ;

(prettier/prettier)


[error] 129-129: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 129-129: Insert ;

(prettier/prettier)


169-183: Consider combining regex patterns

The function uses separate regex patterns for different heading ID formats. Consider combining them for better maintainability.

-  const headingIdMatch = str.match(/[\s]*\{#([a-zA-Z0-9\-_]+)\}/);
-  const [, headingId] = headingIdMatch || [];
-  if (headingId?.trim()) {
-    slug = headingId;
-  } else {
-    const anchorTagMatch = str.match(/[\s]*<a[\s]+name="([a-zA-Z0-9\-_]+)"/);
-    const [, anchorId] = anchorTagMatch || [];
-    if (anchorId?.trim()) {
-      slug = anchorId;
-    }
-  }
+  const idMatch = str.match(/[\s]*(?:\{#([a-zA-Z0-9\-_]+)\}|<a[\s]+name="([a-zA-Z0-9\-_]+)")/);
+  const [, headingId, anchorId] = idMatch || [];
+  slug = (headingId || anchorId || '').trim();
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 069128a and a4403bd.

📒 Files selected for processing (1)
  • scripts/build-post-list.js (7 hunks)
🧰 Additional context used
🪛 eslint
scripts/build-post-list.js

[error] 1-1: Insert ;

(prettier/prettier)


[error] 2-2: Insert ;

(prettier/prettier)


[error] 20-21: Replace ⏎····result.docs.push(details) with ·result.docs.push(details);

(prettier/prettier)


[error] 22-23: Replace ⏎····result.blog.push(details) with ·result.blog.push(details);

(prettier/prettier)


[error] 24-25: Replace ⏎····result.about.push(details) with ·result.about.push(details);

(prettier/prettier)


[error] 38-39: Delete

(prettier/prettier)


[error] 43-43: Replace Error·while·building·post·list:·${missing.join('·and·')}·${missing.length·>·1·?·'are'·:·'is'}·required with ⏎········Error·while·building·post·list:·${missing.join('·and·')}·${missing.length·>·1·?·'are'·:·'is'}·required⏎······

(prettier/prettier)


[error] 49-49: Insert ;

(prettier/prettier)


[error] 50-50: 'walkDirectories' was used before it was defined.

(no-use-before-define)


[error] 50-50: Insert ;

(prettier/prettier)


[error] 51-51: Insert ;

(prettier/prettier)


[error] 52-52: Insert ;

(prettier/prettier)


[error] 53-53: Insert ;

(prettier/prettier)


[error] 54-54: Insert ;

(prettier/prettier)


[error] 69-69: 'dir' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 72-72: Unexpected await inside a loop.

(no-await-in-loop)


[error] 72-72: Insert ;

(prettier/prettier)


[error] 74-74: 'file' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 77-77: Insert ;

(prettier/prettier)


[error] 78-78: Unexpected string concatenation.

(prefer-template)


[error] 78-78: Insert ;

(prettier/prettier)


[error] 79-79: Insert ;

(prettier/prettier)


[error] 81-81: Unexpected await inside a loop.

(no-await-in-loop)


[error] 81-81: 'isDirectory' was used before it was defined.

(no-use-before-define)


[error] 82-82: Unexpected await inside a loop.

(no-await-in-loop)


[error] 84-84: Unexpected await inside a loop.

(no-await-in-loop)


[error] 84-84: Insert ;

(prettier/prettier)


[error] 93-93: Insert ;

(prettier/prettier)


[error] 94-94: Insert ;

(prettier/prettier)


[error] 104-104: This line has a length of 135. Maximum allowed is 120.

(max-len)


[error] 104-104: Unexpected await inside a loop.

(no-await-in-loop)


[error] 104-104: Replace [[fileName,·slug]],·resultObj,·basePath,·details.title,·details.sectionId,·rootId,·details.sectionWeight) with ⏎··········[[fileName,·slug]],⏎··········resultObj,⏎··········basePath,⏎··········details.title,⏎··········details.sectionId,⏎··········rootId,⏎··········details.sectionWeight⏎········);

(prettier/prettier)


[error] 105-105: Unexpected string concatenation.

(prefer-template)


[error] 106-106: Unexpected await inside a loop.

(no-await-in-loop)


[error] 106-106: Insert ;

(prettier/prettier)


[error] 118-118: Insert ;

(prettier/prettier)


[error] 119-119: Insert ;

(prettier/prettier)


[error] 120-120: Insert ;

(prettier/prettier)


[error] 122-122: Replace · with ;

(prettier/prettier)


[error] 123-123: Insert ;

(prettier/prettier)


[error] 124-124: Unary operator '--' used.

(no-plusplus)


[error] 124-124: Insert ;

(prettier/prettier)


[error] 127-127: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 127-127: Insert ;

(prettier/prettier)


[error] 129-129: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 129-129: Insert ;

(prettier/prettier)


[error] 147-147: Replace "release-notes")·&&·dir[1]·===·"/blog" with 'release-notes')·&&·dir[1]·===·'/blog'

(prettier/prettier)


[error] 148-148: Insert ;

(prettier/prettier)


[error] 150-150: Replace "-")·+·1) with '-')·+·1);

(prettier/prettier)


[error] 152-152: This line has a length of 164. Maximum allowed is 120.

(max-len)


[error] 191-191: Insert ;

(prettier/prettier)


[error] 195-195: Insert ;

(prettier/prettier)


[error] 198-198: Insert ;

(prettier/prettier)

🔇 Additional comments (3)
scripts/build-post-list.js (3)

1-2: LGTM: Good choice using fs-extra

The switch to fs-extra is beneficial as it provides more robust file operations with built-in promise support and better error handling.

🧰 Tools
🪛 eslint

[error] 1-1: Insert ;

(prettier/prettier)


[error] 2-2: Insert ;

(prettier/prettier)


28-35: LGTM: Well-documented function signature

The JSDoc documentation clearly describes the function parameters, return type, and possible errors.


198-198: Verify usage of exported functions

The module now exports both slugifyToC and buildPostList. Let's verify that all consumers are updated to use the named imports.

✅ Verification successful

All module imports are correctly using named imports

The verification shows that all three files importing the module are using proper named imports:

  • tests/build-post-list.test.js imports both buildPostList and slugifyToC
  • tests/index.test.js imports buildPostList
  • scripts/index.js imports buildPostList

The exports are being used correctly throughout the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for require statements importing this module
rg "require.*build-post-list" --type js

Length of output: 306

🧰 Tools
🪛 eslint

[error] 198-198: Insert ;

(prettier/prettier)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (6)
scripts/build-post-list.js (6)

39-45: Simplify error message construction

The error message construction can be simplified for better maintainability.

-    if (!basePath || !writeFilePath) {
-      const missing = [
-        !basePath && 'basePath',
-        !writeFilePath && 'writeFilePath'
-        ].filter(Boolean);
-        throw new Error(`Error while building post list: ${missing.join(' and ')} ${missing.length > 1 ? 'are' : 'is'} required`);
-    }
+    if (!basePath) {
+      throw new Error('Error while building post list: basePath is required');
+    }
+    if (!writeFilePath) {
+      throw new Error('Error while building post list: writeFilePath is required');
+    }
🧰 Tools
🪛 eslint

[error] 40-43: Replace ⏎········!basePath·&&·'basePath',⏎········!writeFilePath·&&·'writeFilePath'⏎········ with !basePath·&&·'basePath',·!writeFilePath·&&·'writeFilePath'

(prettier/prettier)


[error] 44-44: Replace ··throw·new·Error(Error·while·building·post·list:·${missing.join('·and·')}·${missing.length·>·1·?·'are'·:·'is'}·required`` with throw·new·Error(⏎········Error·while·building·post·list:·${missing.join('·and·')}·${missing.length·>·1·?·'are'·:·'is'}·required`⏎······`

(prettier/prettier)


73-76: Simplify Promise.all usage

The current implementation is unnecessarily complex with its destructuring pattern.

-    const files = await Promise.all([
-      readdir(directory),
-      pathExists(directory)
-      ]).then(([files]) => files)
+    if (!(await pathExists(directory))) {
+      return [];
+    }
+    const files = await readdir(directory);
🧰 Tools
🪛 eslint

[error] 73-76: Unexpected await inside a loop.

(no-await-in-loop)


[error] 73-76: Replace ⏎······readdir(directory),⏎······pathExists(directory)⏎······]).then(([files])·=>·files) with readdir(directory),·pathExists(directory)]).then(([files])·=>·files);

(prettier/prettier)


[error] 76-76: 'files' is already declared in the upper scope on line 73 column 11.

(no-shadow)


125-134: Extract version handling logic

The version name handling logic is complex and could be extracted into a separate function for better maintainability.

+function getVersionDetails(slug) {
+  const fileBaseName = basename(slug);
+  const versionName = fileBaseName.split('-')[0];
+  return {
+    title: versionName.startsWith('v') 
+      ? capitalize(versionName.slice(1))
+      : capitalize(versionName),
+    weight: specWeight--
+  };
+}

-          const fileBaseName = basename(details.slug)
-          const versionName = fileBaseName.split('-')[0]
-          details.weight = specWeight--
-
-          if (versionName.startsWith('v')) {
-            details.title = capitalize(versionName.slice(1))
-          } else {
-            details.title = capitalize(versionName)
-          }
+          const versionDetails = getVersionDetails(details.slug);
+          details.title = versionDetails.title;
+          details.weight = versionDetails.weight;
🧰 Tools
🪛 eslint

[error] 126-126: Replace · with ;

(prettier/prettier)


[error] 127-127: Insert ;

(prettier/prettier)


[error] 128-128: Unary operator '--' used.

(no-plusplus)


[error] 128-128: Insert ;

(prettier/prettier)


[error] 131-131: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 131-131: Insert ;

(prettier/prettier)


[error] 133-133: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 133-133: Insert ;

(prettier/prettier)


167-182: Enhance slugifyToC robustness

The function could be more robust with constant regex and additional edge case handling.

+const HEADING_ID_REGEX = /[\s]*(?:\{#([a-zA-Z0-9\-_]+)\}|<a[\s]+name="([a-zA-Z0-9\-_]+)")/;

 function slugifyToC(str) {
   if (typeof str !== 'string') return '';
+  if (!str.trim()) return '';
   let slug = '';

   // Match heading IDs like {# myHeadingId}
-  const idMatch = str.match(/[\s]*(?:\{#([a-zA-Z0-9\-_]+)\}|<a[\s]+name="([a-zA-Z0-9\-_]+)")/);
+  const idMatch = str.match(HEADING_ID_REGEX);
   const [, headingId, anchorId] = idMatch || [];
   slug = (headingId || anchorId || '').trim();

   // If no valid ID is found, return an empty string
   return slug;
 }

151-158: Simplify release notes handling

The current implementation has redundant comments and complex string operations.

-        if (file.startsWith("release-notes") && dir[1] === "/blog") {
-          const fileNameWithoutExtension = basename(file, extname(file))
-          // removes the file extension. For example, release-notes-2.1.0.md -> release-notes-2.1.0
-          const version = fileNameWithoutExtension.slice(fileNameWithoutExtension.lastIndexOf("-") + 1)
-
-          // gets the version from the name of the releaseNote .md file (from /blog). For example, version = 2.1.0 if fileNameWithoutExtension = release-notes-2.1.0
-          releaseNotes.push(version)
-          // releaseNotes is the list of all available releaseNotes
+        if (file.startsWith('release-notes') && dir[1] === '/blog') {
+          const version = basename(file, extname(file)).split('-').pop();
+          releaseNotes.push(version);
         }
🧰 Tools
🪛 eslint

[error] 151-151: Replace "release-notes")·&&·dir[1]·===·"/blog" with 'release-notes')·&&·dir[1]·===·'/blog'

(prettier/prettier)


[error] 152-152: Insert ;

(prettier/prettier)


[error] 154-154: Replace "-")·+·1) with '-')·+·1);

(prettier/prettier)


[error] 156-156: This line has a length of 164. Maximum allowed is 120.

(max-len)


[error] 157-157: Insert ;

(prettier/prettier)


Line range hint 9-17: Consider reducing global state

The use of global variables (result, specWeight, releaseNotes) could lead to issues in concurrent scenarios and makes the code harder to test and maintain.

Consider:

  1. Moving these variables into a class or context object
  2. Passing them as parameters where needed
  3. Using a state management pattern if needed in a larger application context

This would improve testability and make the code more maintainable.

🧰 Tools
🪛 eslint

[error] 16-16: Insert ;

(prettier/prettier)


[error] 17-17: Insert ;

(prettier/prettier)


[error] 20-21: Replace ⏎····result.docs.push(details) with ·result.docs.push(details);

(prettier/prettier)


[error] 22-23: Replace ⏎····result.blog.push(details) with ·result.blog.push(details);

(prettier/prettier)


[error] 24-25: Replace ⏎····result.about.push(details) with ·result.about.push(details);

(prettier/prettier)


[error] 38-39: Delete

(prettier/prettier)


[error] 40-43: Replace ⏎········!basePath·&&·'basePath',⏎········!writeFilePath·&&·'writeFilePath'⏎········ with !basePath·&&·'basePath',·!writeFilePath·&&·'writeFilePath'

(prettier/prettier)


[error] 44-44: Replace ··throw·new·Error(Error·while·building·post·list:·${missing.join('·and·')}·${missing.length·>·1·?·'are'·:·'is'}·required`` with throw·new·Error(⏎········Error·while·building·post·list:·${missing.join('·and·')}·${missing.length·>·1·?·'are'·:·'is'}·required`⏎······`

(prettier/prettier)


[error] 50-50: Insert ;

(prettier/prettier)


[error] 51-51: 'walkDirectories' was used before it was defined.

(no-use-before-define)


[error] 51-51: Insert ;

(prettier/prettier)


[error] 52-52: Insert ;

(prettier/prettier)


[error] 53-53: Insert ;

(prettier/prettier)


[error] 54-54: Insert ;

(prettier/prettier)


[error] 55-55: Insert ;

(prettier/prettier)


[error] 70-70: 'dir' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 73-76: Unexpected await inside a loop.

(no-await-in-loop)


[error] 73-76: Replace ⏎······readdir(directory),⏎······pathExists(directory)⏎······]).then(([files])·=>·files) with readdir(directory),·pathExists(directory)]).then(([files])·=>·files);

(prettier/prettier)


[error] 76-76: 'files' is already declared in the upper scope on line 73 column 11.

(no-shadow)


[error] 78-78: 'file' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 81-81: Insert ;

(prettier/prettier)


[error] 82-82: Unexpected string concatenation.

(prefer-template)


[error] 82-82: Insert ;

(prettier/prettier)


[error] 83-83: Insert ;

(prettier/prettier)


[error] 85-85: Unexpected await inside a loop.

(no-await-in-loop)


[error] 85-85: 'isDirectory' was used before it was defined.

(no-use-before-define)


[error] 86-86: Unexpected await inside a loop.

(no-await-in-loop)


[error] 88-88: Unexpected await inside a loop.

(no-await-in-loop)


[error] 88-88: Insert ;

(prettier/prettier)


[error] 89-89: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 89-89: Insert ;

(prettier/prettier)

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a4403bd and fcff3ed.

📒 Files selected for processing (1)
  • scripts/build-post-list.js (7 hunks)
🧰 Additional context used
🪛 eslint
scripts/build-post-list.js

[error] 1-1: Insert ;

(prettier/prettier)


[error] 2-2: Insert ;

(prettier/prettier)


[error] 20-21: Replace ⏎····result.docs.push(details) with ·result.docs.push(details);

(prettier/prettier)


[error] 22-23: Replace ⏎····result.blog.push(details) with ·result.blog.push(details);

(prettier/prettier)


[error] 24-25: Replace ⏎····result.about.push(details) with ·result.about.push(details);

(prettier/prettier)


[error] 38-39: Delete

(prettier/prettier)


[error] 40-43: Replace ⏎········!basePath·&&·'basePath',⏎········!writeFilePath·&&·'writeFilePath'⏎········ with !basePath·&&·'basePath',·!writeFilePath·&&·'writeFilePath'

(prettier/prettier)


[error] 44-44: Replace ··throw·new·Error(Error·while·building·post·list:·${missing.join('·and·')}·${missing.length·>·1·?·'are'·:·'is'}·required`` with throw·new·Error(⏎········Error·while·building·post·list:·${missing.join('·and·')}·${missing.length·>·1·?·'are'·:·'is'}·required`⏎······`

(prettier/prettier)


[error] 50-50: Insert ;

(prettier/prettier)


[error] 51-51: 'walkDirectories' was used before it was defined.

(no-use-before-define)


[error] 51-51: Insert ;

(prettier/prettier)


[error] 52-52: Insert ;

(prettier/prettier)


[error] 53-53: Insert ;

(prettier/prettier)


[error] 54-54: Insert ;

(prettier/prettier)


[error] 55-55: Insert ;

(prettier/prettier)


[error] 70-70: 'dir' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 73-76: Unexpected await inside a loop.

(no-await-in-loop)


[error] 73-76: Replace ⏎······readdir(directory),⏎······pathExists(directory)⏎······]).then(([files])·=>·files) with readdir(directory),·pathExists(directory)]).then(([files])·=>·files);

(prettier/prettier)


[error] 76-76: 'files' is already declared in the upper scope on line 73 column 11.

(no-shadow)


[error] 78-78: 'file' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 81-81: Insert ;

(prettier/prettier)


[error] 82-82: Unexpected string concatenation.

(prefer-template)


[error] 82-82: Insert ;

(prettier/prettier)


[error] 83-83: Insert ;

(prettier/prettier)


[error] 85-85: Unexpected await inside a loop.

(no-await-in-loop)


[error] 85-85: 'isDirectory' was used before it was defined.

(no-use-before-define)


[error] 86-86: Unexpected await inside a loop.

(no-await-in-loop)


[error] 88-88: Unexpected await inside a loop.

(no-await-in-loop)


[error] 88-88: Insert ;

(prettier/prettier)


[error] 97-97: Insert ;

(prettier/prettier)


[error] 98-98: Insert ;

(prettier/prettier)


[error] 108-108: This line has a length of 135. Maximum allowed is 120.

(max-len)


[error] 108-108: Unexpected await inside a loop.

(no-await-in-loop)


[error] 108-108: Replace [[fileName,·slug]],·resultObj,·basePath,·details.title,·details.sectionId,·rootId,·details.sectionWeight) with ⏎··········[[fileName,·slug]],⏎··········resultObj,⏎··········basePath,⏎··········details.title,⏎··········details.sectionId,⏎··········rootId,⏎··········details.sectionWeight⏎········);

(prettier/prettier)


[error] 109-109: Unexpected string concatenation.

(prefer-template)


[error] 110-110: Unexpected await inside a loop.

(no-await-in-loop)


[error] 110-110: Insert ;

(prettier/prettier)


[error] 122-122: Insert ;

(prettier/prettier)


[error] 123-123: Insert ;

(prettier/prettier)


[error] 124-124: Insert ;

(prettier/prettier)


[error] 126-126: Replace · with ;

(prettier/prettier)


[error] 127-127: Insert ;

(prettier/prettier)


[error] 128-128: Unary operator '--' used.

(no-plusplus)


[error] 128-128: Insert ;

(prettier/prettier)


[error] 131-131: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 131-131: Insert ;

(prettier/prettier)


[error] 133-133: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 133-133: Insert ;

(prettier/prettier)


[error] 151-151: Replace "release-notes")·&&·dir[1]·===·"/blog" with 'release-notes')·&&·dir[1]·===·'/blog'

(prettier/prettier)


[error] 152-152: Insert ;

(prettier/prettier)


[error] 154-154: Replace "-")·+·1) with '-')·+·1);

(prettier/prettier)


[error] 156-156: This line has a length of 164. Maximum allowed is 120.

(max-len)


[error] 186-186: Insert ;

(prettier/prettier)


[error] 190-190: Insert ;

(prettier/prettier)


[error] 193-193: Insert ;

(prettier/prettier)

🔇 Additional comments (1)
scripts/build-post-list.js (1)

1-1: LGTM: Good choice using fs-extra!

The switch to fs-extra is a solid improvement as it provides enhanced file system operations and better handles edge cases like creating directories that don't exist.

🧰 Tools
🪛 eslint

[error] 1-1: Insert ;

(prettier/prettier)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🔭 Outside diff range comments (1)
scripts/build-post-list.js (1)

Line range hint 123-142: Extract version handling logic into a separate function

The version handling logic is complex and would be more maintainable as a separate function.

+function processSpecificationVersion(details, fileBaseName) {
+  const versionName = fileBaseName.split('-')[0];
+  details.weight = specWeight--;
+
+  details.title = versionName.startsWith('v') 
+    ? capitalize(versionName.slice(1))
+    : capitalize(versionName);
+
+  if (releaseNotes.includes(details.title)) {
+    details.releaseNoteLink = `/blog/release-notes-${details.title}`;
+  }
+
+  if (fileBaseName.includes('next-spec') || fileBaseName.includes('next-major-spec')) {
+    details.isPrerelease = true;
+    details.title += " (Pre-release)";
+  }
+  if (fileBaseName.includes('explorer')) {
+    details.title += " - Explorer";
+  }
+  return details;
+}
🧰 Tools
🪛 eslint

[error] 117-117: Insert ;

(prettier/prettier)


[error] 118-118: Insert ;

(prettier/prettier)


[error] 119-119: Insert ;

(prettier/prettier)


[error] 120-120: Insert ;

(prettier/prettier)


[error] 121-121: Insert ;

(prettier/prettier)


[error] 122-122: Insert ;

(prettier/prettier)


[error] 124-124: Replace · with ;

(prettier/prettier)


[error] 125-125: Insert ;

(prettier/prettier)


[error] 126-126: Unary operator '--' used.

(no-plusplus)


[error] 126-126: Insert ;

(prettier/prettier)


[error] 129-129: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 129-129: Insert ;

(prettier/prettier)


[error] 131-131: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 131-131: Insert ;

(prettier/prettier)


[error] 135-135: Insert ;

(prettier/prettier)

🧹 Nitpick comments (5)
scripts/build-post-list.js (5)

19-25: Consider adding input validation and reducing global state dependency

While the function is cleaner now, it could be improved by:

  1. Validating the details parameter
  2. Making the function pure by accepting the result object as a parameter
-const addItem = (details) => {
+const addItem = (details, resultObj) => {
+  if (!details || !details.slug) {
+    throw new Error('Invalid details object');
+  }
   if (details.slug.startsWith('/docs'))
-    result.docs.push(details)
+    resultObj.docs.push(details)
   else if (details.slug.startsWith('/blog'))
-    result.blog.push(details)
+    resultObj.blog.push(details)
   else if (details.slug.startsWith('/about'))
-    result.about.push(details)
+    resultObj.about.push(details)
 };
🧰 Tools
🪛 eslint

[error] 19-20: Replace ⏎····result.docs.push(details) with ·result.docs.push(details);

(prettier/prettier)


[error] 21-22: Replace ⏎····result.blog.push(details) with ·result.blog.push(details);

(prettier/prettier)


[error] 23-24: Replace ⏎····result.about.push(details) with ·result.about.push(details);

(prettier/prettier)


27-55: Enhance error handling with more specific messages and type validation

The error handling is good, but could be improved by:

  1. Adding type validation for parameters
  2. Making error messages more specific about the expected types
 async function buildPostList(postDirectories, basePath, writeFilePath) {
   try {
+    if (!Array.isArray(postDirectories)) {
+      throw new Error('Error while building post list: postDirectories must be an array');
+    }
+    if (typeof basePath !== 'string') {
+      throw new Error('Error while building post list: basePath must be a string');
+    }
+    if (typeof writeFilePath !== 'string') {
+      throw new Error('Error while building post list: writeFilePath must be a string');
+    }
     if (!basePath) {
🧰 Tools
🪛 eslint

[error] 36-37: Delete

(prettier/prettier)


[error] 48-48: Insert ;

(prettier/prettier)


[error] 49-49: 'walkDirectories' was used before it was defined.

(no-use-before-define)


[error] 49-49: Insert ;

(prettier/prettier)


[error] 50-50: Insert ;

(prettier/prettier)


[error] 51-51: Insert ;

(prettier/prettier)


[error] 52-52: Insert ;

(prettier/prettier)


[error] 53-53: Insert ;

(prettier/prettier)


71-74: Optimize file existence check

The Promise.all usage here is good, but we're still awaiting it inside a loop. Consider batching the file operations.

-    const files = await Promise.all([
-      readdir(directory),
-      pathExists(directory)
-    ]).then(([files]) => files)
+    if (!(await pathExists(directory))) {
+      return;
+    }
+    const files = await readdir(directory);
🧰 Tools
🪛 eslint

[error] 71-74: Unexpected await inside a loop.

(no-await-in-loop)


[error] 71-74: Replace ⏎······readdir(directory),⏎······pathExists(directory)⏎····]).then(([files])·=>·files) with readdir(directory),·pathExists(directory)]).then(([files])·=>·files);

(prettier/prettier)


[error] 74-74: 'files' is already declared in the upper scope on line 71 column 11.

(no-shadow)


160-178: Consider caching and more restrictive regex for heading IDs

The function is well-documented, but could be optimized:

  1. Add caching for frequently used headings
  2. Make the regex more restrictive to prevent potential issues
+const slugCache = new Map();
 function slugifyToC(str) {
   if (typeof str !== 'string') return '';
   if (!str.trim()) return '';
+  
+  const cached = slugCache.get(str);
+  if (cached) return cached;
+
   let slug = '';
   const idMatch = str.match(HEADING_ID_REGEX);
   const [, headingId, anchorId] = idMatch || [];
   slug = (headingId || anchorId || '').trim();
+  
+  slugCache.set(str, slug);
   return slug;
 }

181-189: Optimize helper functions for better performance

Consider these improvements to the helper functions:

  1. Cache directory checks for frequently accessed paths
  2. Optimize capitalize function for better performance
+const directoryCache = new Map();
 async function isDirectory(dir) {
+  if (directoryCache.has(dir)) {
+    return directoryCache.get(dir);
+  }
-  return (await stat(dir)).isDirectory()
+  const result = (await stat(dir)).isDirectory();
+  directoryCache.set(dir, result);
+  return result;
 }

 function capitalize(text) {
-  return text.replace(/(?:^|\s|-)([a-z])/g, (_, char) => char.toUpperCase())
+  return text.split(/[\s-]/)
+    .map(word => word.charAt(0).toUpperCase() + word.slice(1))
+    .join(' ');
 }
🧰 Tools
🪛 eslint

[error] 182-182: Insert ;

(prettier/prettier)


[error] 186-186: Insert ;

(prettier/prettier)


[error] 189-189: Insert ;

(prettier/prettier)

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fcff3ed and 48010df.

📒 Files selected for processing (1)
  • scripts/build-post-list.js (7 hunks)
🧰 Additional context used
🪛 eslint
scripts/build-post-list.js

[error] 1-1: Insert ;

(prettier/prettier)


[error] 2-2: Insert ;

(prettier/prettier)


[error] 19-20: Replace ⏎····result.docs.push(details) with ·result.docs.push(details);

(prettier/prettier)


[error] 21-22: Replace ⏎····result.blog.push(details) with ·result.blog.push(details);

(prettier/prettier)


[error] 23-24: Replace ⏎····result.about.push(details) with ·result.about.push(details);

(prettier/prettier)


[error] 36-37: Delete

(prettier/prettier)


[error] 48-48: Insert ;

(prettier/prettier)


[error] 49-49: 'walkDirectories' was used before it was defined.

(no-use-before-define)


[error] 49-49: Insert ;

(prettier/prettier)


[error] 50-50: Insert ;

(prettier/prettier)


[error] 51-51: Insert ;

(prettier/prettier)


[error] 52-52: Insert ;

(prettier/prettier)


[error] 53-53: Insert ;

(prettier/prettier)


[error] 68-68: 'dir' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 71-74: Unexpected await inside a loop.

(no-await-in-loop)


[error] 71-74: Replace ⏎······readdir(directory),⏎······pathExists(directory)⏎····]).then(([files])·=>·files) with readdir(directory),·pathExists(directory)]).then(([files])·=>·files);

(prettier/prettier)


[error] 74-74: 'files' is already declared in the upper scope on line 71 column 11.

(no-shadow)


[error] 76-76: 'file' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 79-79: Insert ;

(prettier/prettier)


[error] 80-80: Unexpected string concatenation.

(prefer-template)


[error] 80-80: Insert ;

(prettier/prettier)


[error] 81-81: Insert ;

(prettier/prettier)


[error] 83-83: Unexpected await inside a loop.

(no-await-in-loop)


[error] 83-83: 'isDirectory' was used before it was defined.

(no-use-before-define)


[error] 84-84: Unexpected await inside a loop.

(no-await-in-loop)


[error] 86-86: Unexpected await inside a loop.

(no-await-in-loop)


[error] 86-86: Insert ;

(prettier/prettier)


[error] 95-95: Insert ;

(prettier/prettier)


[error] 96-96: Insert ;

(prettier/prettier)


[error] 106-106: This line has a length of 135. Maximum allowed is 120.

(max-len)


[error] 106-106: Unexpected await inside a loop.

(no-await-in-loop)


[error] 106-106: Replace [[fileName,·slug]],·resultObj,·basePath,·details.title,·details.sectionId,·rootId,·details.sectionWeight) with ⏎··········[[fileName,·slug]],⏎··········resultObj,⏎··········basePath,⏎··········details.title,⏎··········details.sectionId,⏎··········rootId,⏎··········details.sectionWeight⏎········);

(prettier/prettier)


[error] 107-107: Unexpected string concatenation.

(prefer-template)


[error] 108-108: Unexpected await inside a loop.

(no-await-in-loop)


[error] 108-108: Insert ;

(prettier/prettier)


[error] 120-120: Insert ;

(prettier/prettier)


[error] 121-121: Insert ;

(prettier/prettier)


[error] 122-122: Insert ;

(prettier/prettier)


[error] 124-124: Replace · with ;

(prettier/prettier)


[error] 125-125: Insert ;

(prettier/prettier)


[error] 126-126: Unary operator '--' used.

(no-plusplus)


[error] 126-126: Insert ;

(prettier/prettier)


[error] 129-129: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 129-129: Insert ;

(prettier/prettier)


[error] 131-131: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 131-131: Insert ;

(prettier/prettier)


[error] 182-182: Insert ;

(prettier/prettier)


[error] 186-186: Insert ;

(prettier/prettier)


[error] 189-189: Insert ;

(prettier/prettier)

🔇 Additional comments (1)
scripts/build-post-list.js (1)

1-2: LGTM: Good choice using fs-extra!

The switch to fs-extra is a good improvement as it provides better Promise-based APIs and handles edge cases like creating parent directories automatically.

🧰 Tools
🪛 eslint

[error] 1-1: Insert ;

(prettier/prettier)


[error] 2-2: Insert ;

(prettier/prettier)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
scripts/build-post-list.js (3)

27-55: Enhance error messages with more context

The error handling and input validation are good improvements. However, the error messages could be more specific to help with debugging.

Consider this improvement:

-      throw new Error('Error while building post list: basePath is required');
+      throw new Error('Error while building post list: basePath is required. Please provide a valid base path for resolving relative paths.');
-      throw new Error('Error while building post list: writeFilePath is required');
+      throw new Error('Error while building post list: writeFilePath is required. Please provide a valid path where the output JSON will be written.');
-      throw new Error('Error while building post list: No post directories provided');
+      throw new Error('Error while building post list: No post directories provided. Please provide an array of [directory, slug] tuples.');
🧰 Tools
🪛 eslint

[error] 37-38: Delete

(prettier/prettier)


[error] 48-48: Insert ;

(prettier/prettier)


[error] 49-49: 'walkDirectories' was used before it was defined.

(no-use-before-define)


[error] 49-49: Insert ;

(prettier/prettier)


[error] 50-50: Insert ;

(prettier/prettier)


[error] 51-51: Insert ;

(prettier/prettier)


[error] 52-52: Insert ;

(prettier/prettier)


[error] 53-53: Insert ;

(prettier/prettier)


123-131: Consider extracting version name handling logic

The version name handling logic is complex and could be extracted into a separate function for better maintainability.

Consider creating a separate function:

+ function getVersionDetails(slug) {
+   const fileBaseName = basename(slug);
+   const versionName = fileBaseName.split('-')[0];
+   return {
+     title: versionName.startsWith('v') ? 
+       capitalize(versionName.slice(1)) : 
+       capitalize(versionName),
+     weight: specWeight--
+   };
+ }

  if (details.slug.includes('/reference/specification/') && !details.title) {
-   const fileBaseName = basename(details.slug)
-   const versionName = fileBaseName.split('-')[0]
-   details.weight = specWeight--
-   if (versionName.startsWith('v')) {
-     details.title = capitalize(versionName.slice(1))
-   } else {
-     details.title = capitalize(versionName)
-   }
+   const versionDetails = getVersionDetails(details.slug);
+   details.title = versionDetails.title;
+   details.weight = versionDetails.weight;
  }
🧰 Tools
🪛 eslint

[error] 124-124: Replace · with ;

(prettier/prettier)


[error] 125-125: Insert ;

(prettier/prettier)


[error] 126-126: Unary operator '--' used.

(no-plusplus)


[error] 126-126: Insert ;

(prettier/prettier)


[error] 129-129: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 129-129: Insert ;

(prettier/prettier)


[error] 131-131: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 131-131: Insert ;

(prettier/prettier)


160-178: Consider improving regex readability

The heading ID regex is complex and could benefit from being more readable with named capture groups and comments.

Consider this improvement:

- const HEADING_ID_REGEX = /[\s]*(?:\{#([a-zA-Z0-9\-_]+)\}|<a[\s]+name="([a-zA-Z0-9\-_]+)")/;
+ // Matches heading IDs in two formats:
+ // 1. {#my-heading-id}
+ // 2. <a name="my-heading-id">
+ const HEADING_ID_REGEX = /[\s]*(?:
+   \{#(?<markdownId>[a-zA-Z0-9\-_]+)\}|
+   <a[\s]+name="(?<htmlId>[a-zA-Z0-9\-_]+)"
+ )/x;
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 48010df and 440670c.

📒 Files selected for processing (1)
  • scripts/build-post-list.js (7 hunks)
🧰 Additional context used
🪛 eslint
scripts/build-post-list.js

[error] 1-1: Insert ;

(prettier/prettier)


[error] 2-2: Insert ;

(prettier/prettier)


[error] 19-20: Replace ⏎····result.docs.push(details) with ·result.docs.push(details);

(prettier/prettier)


[error] 21-22: Replace ⏎····result.blog.push(details) with ·result.blog.push(details);

(prettier/prettier)


[error] 23-24: Replace ⏎····result.about.push(details) with ·result.about.push(details);

(prettier/prettier)


[error] 37-38: Delete

(prettier/prettier)


[error] 48-48: Insert ;

(prettier/prettier)


[error] 49-49: 'walkDirectories' was used before it was defined.

(no-use-before-define)


[error] 49-49: Insert ;

(prettier/prettier)


[error] 50-50: Insert ;

(prettier/prettier)


[error] 51-51: Insert ;

(prettier/prettier)


[error] 52-52: Insert ;

(prettier/prettier)


[error] 53-53: Insert ;

(prettier/prettier)


[error] 68-68: 'dir' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 71-74: Unexpected await inside a loop.

(no-await-in-loop)


[error] 71-74: Replace ⏎······readdir(directory),⏎······pathExists(directory)⏎····]).then(([files])·=>·files) with readdir(directory),·pathExists(directory)]).then(([files])·=>·files);

(prettier/prettier)


[error] 74-74: 'files' is already declared in the upper scope on line 71 column 11.

(no-shadow)


[error] 76-76: 'file' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 79-79: Insert ;

(prettier/prettier)


[error] 80-80: Unexpected string concatenation.

(prefer-template)


[error] 80-80: Insert ;

(prettier/prettier)


[error] 81-81: Insert ;

(prettier/prettier)


[error] 83-83: Unexpected await inside a loop.

(no-await-in-loop)


[error] 83-83: 'isDirectory' was used before it was defined.

(no-use-before-define)


[error] 84-84: Unexpected await inside a loop.

(no-await-in-loop)


[error] 86-86: Unexpected await inside a loop.

(no-await-in-loop)


[error] 86-86: Insert ;

(prettier/prettier)


[error] 95-95: Insert ;

(prettier/prettier)


[error] 96-96: Insert ;

(prettier/prettier)


[error] 106-106: This line has a length of 135. Maximum allowed is 120.

(max-len)


[error] 106-106: Unexpected await inside a loop.

(no-await-in-loop)


[error] 106-106: Replace [[fileName,·slug]],·resultObj,·basePath,·details.title,·details.sectionId,·rootId,·details.sectionWeight) with ⏎··········[[fileName,·slug]],⏎··········resultObj,⏎··········basePath,⏎··········details.title,⏎··········details.sectionId,⏎··········rootId,⏎··········details.sectionWeight⏎········);

(prettier/prettier)


[error] 107-107: Unexpected string concatenation.

(prefer-template)


[error] 108-108: Unexpected await inside a loop.

(no-await-in-loop)


[error] 108-108: Insert ;

(prettier/prettier)


[error] 120-120: Insert ;

(prettier/prettier)


[error] 121-121: Insert ;

(prettier/prettier)


[error] 122-122: Insert ;

(prettier/prettier)


[error] 124-124: Replace · with ;

(prettier/prettier)


[error] 125-125: Insert ;

(prettier/prettier)


[error] 126-126: Unary operator '--' used.

(no-plusplus)


[error] 126-126: Insert ;

(prettier/prettier)


[error] 129-129: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 129-129: Insert ;

(prettier/prettier)


[error] 131-131: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 131-131: Insert ;

(prettier/prettier)


[error] 182-182: Insert ;

(prettier/prettier)


[error] 186-186: Insert ⏎····

(prettier/prettier)


[error] 187-187: Replace word with (word)

(prettier/prettier)


[error] 191-191: Insert ;

(prettier/prettier)

🔇 Additional comments (2)
scripts/build-post-list.js (2)

1-2: LGTM! Good choice using fs-extra

The switch to fs-extra is a good improvement as it provides more robust file operations with better error handling, particularly for ensuring parent directories exist during write operations.

🧰 Tools
🪛 eslint

[error] 1-1: Insert ;

(prettier/prettier)


[error] 2-2: Insert ;

(prettier/prettier)


71-74: LGTM! Good use of Promise.all

Using Promise.all for parallel file operations is a good performance optimization.

🧰 Tools
🪛 eslint

[error] 71-74: Unexpected await inside a loop.

(no-await-in-loop)


[error] 71-74: Replace ⏎······readdir(directory),⏎······pathExists(directory)⏎····]).then(([files])·=>·files) with readdir(directory),·pathExists(directory)]).then(([files])·=>·files);

(prettier/prettier)


[error] 74-74: 'files' is already declared in the upper scope on line 71 column 11.

(no-shadow)

@vishvamsinh28
Copy link
Contributor Author

@akshatnema applied nitpick comments

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
scripts/build-post-list.js (3)

27-36: Consider removing side effects from getVersionDetails

While extracting version logic into a separate function is good, the function has side effects by modifying the global specWeight variable. Consider passing the weight as a parameter or returning it as part of the result.

-function getVersionDetails(slug) {
+function getVersionDetails(slug, currentWeight) {
   const fileBaseName = basename(slug);
   const versionName = fileBaseName.split('-')[0];
   return {
     title: versionName.startsWith('v') ? 
       capitalize(versionName.slice(1)) : 
       capitalize(versionName),
-    weight: specWeight--
+    weight: currentWeight
   };
 }
🧰 Tools
🪛 eslint

[error] 28-28: Delete ·

(prettier/prettier)


[error] 29-29: Delete ·

(prettier/prettier)


[error] 30-30: Delete ·

(prettier/prettier)


[error] 31-33: Replace ·title:·versionName.startsWith('v')·?·⏎·······capitalize(versionName.slice(1))·:·⏎······· with title:·versionName.startsWith('v')·?·capitalize(versionName.slice(1))·:·

(prettier/prettier)


[error] 32-32: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 33-33: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 34-34: Delete ·

(prettier/prettier)


[error] 34-34: Unary operator '--' used.

(no-plusplus)


[error] 35-35: Delete ·

(prettier/prettier)


[error] 36-36: Delete ·

(prettier/prettier)


82-85: Consider batching file operations

While we can't parallelize the entire directory walk, we can still optimize individual file operations. The current approach of checking existence after reading is redundant as readdir will throw if the directory doesn't exist.

-    const files = await Promise.all([
-      readdir(directory),
-      pathExists(directory)
-    ]).then(([files]) => files)
+    const files = await readdir(directory)
🧰 Tools
🪛 eslint

[error] 82-85: Unexpected await inside a loop.

(no-await-in-loop)


[error] 82-85: Replace ⏎······readdir(directory),⏎······pathExists(directory)⏎····]).then(([files])·=>·files) with readdir(directory),·pathExists(directory)]).then(([files])·=>·files);

(prettier/prettier)


[error] 85-85: 'files' is already declared in the upper scope on line 82 column 11.

(no-shadow)


155-157: Consider using path.parse for file name parsing

Instead of multiple string operations, consider using path.parse for more reliable file name parsing.

-  const version = basename(file, extname(file)).split('-').pop();
+  const { name } = path.parse(file);
+  const version = name.split('-').pop();
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 440670c and 5d01e26.

📒 Files selected for processing (1)
  • scripts/build-post-list.js (7 hunks)
🧰 Additional context used
📓 Learnings (1)
scripts/build-post-list.js (2)
Learnt from: vishvamsinh28
PR: asyncapi/website#3284
File: scripts/build-post-list.js:28-46
Timestamp: 2024-11-12T06:59:33.852Z
Learning: In the `scripts/build-post-list.js` JavaScript file, tests rely on the `result` object being a global variable. Moving it inside the `buildPostList` function causes tests to fail; therefore, keep `result` as a global variable.
Learnt from: vishvamsinh28
PR: asyncapi/website#3284
File: scripts/build-post-list.js:49-53
Timestamp: 2024-11-12T06:59:33.851Z
Learning: In `scripts/build-post-list.js`, the `walkDirectories` function depends on sequential execution because it mutates `resultObj`. Parallelizing the loop with `Promise.all` causes tests to fail.
🪛 eslint
scripts/build-post-list.js

[error] 1-1: Insert ;

(prettier/prettier)


[error] 2-2: Insert ;

(prettier/prettier)


[error] 19-20: Replace ⏎····result.docs.push(details) with ·result.docs.push(details);

(prettier/prettier)


[error] 21-22: Replace ⏎····result.blog.push(details) with ·result.blog.push(details);

(prettier/prettier)


[error] 23-24: Replace ⏎····result.about.push(details) with ·result.about.push(details);

(prettier/prettier)


[error] 28-28: Delete ·

(prettier/prettier)


[error] 29-29: Delete ·

(prettier/prettier)


[error] 30-30: Delete ·

(prettier/prettier)


[error] 31-33: Replace ·title:·versionName.startsWith('v')·?·⏎·······capitalize(versionName.slice(1))·:·⏎······· with title:·versionName.startsWith('v')·?·capitalize(versionName.slice(1))·:·

(prettier/prettier)


[error] 32-32: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 33-33: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 34-34: Delete ·

(prettier/prettier)


[error] 34-34: Unary operator '--' used.

(no-plusplus)


[error] 35-35: Delete ·

(prettier/prettier)


[error] 36-36: Delete ·

(prettier/prettier)


[error] 48-49: Delete

(prettier/prettier)


[error] 50-50: Replace 'Error·while·building·post·list:·basePath·is·required.·Please·provide·a·valid·base·path·for·resolving·relative·paths.' with ⏎········'Error·while·building·post·list:·basePath·is·required.·Please·provide·a·valid·base·path·for·resolving·relative·paths.'⏎······

(prettier/prettier)


[error] 53-53: Replace 'Error·while·building·post·list:·writeFilePath·is·required.·Please·provide·a·valid·path·where·the·output·JSON·will·be·written.' with ⏎········'Error·while·building·post·list:·writeFilePath·is·required.·Please·provide·a·valid·path·where·the·output·JSON·will·be·written.'⏎······

(prettier/prettier)


[error] 57-57: Replace 'Error·while·building·post·list:·No·post·directories·provided.·Please·provide·an·array·of·[directory,·slug]·tuples.' with ⏎········'Error·while·building·post·list:·No·post·directories·provided.·Please·provide·an·array·of·[directory,·slug]·tuples.'⏎······

(prettier/prettier)


[error] 59-59: Insert ;

(prettier/prettier)


[error] 60-60: 'walkDirectories' was used before it was defined.

(no-use-before-define)


[error] 60-60: Insert ;

(prettier/prettier)


[error] 61-61: Insert ;

(prettier/prettier)


[error] 62-62: Insert ;

(prettier/prettier)


[error] 63-63: Insert ;

(prettier/prettier)


[error] 64-64: Insert ;

(prettier/prettier)


[error] 79-79: 'dir' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 82-85: Unexpected await inside a loop.

(no-await-in-loop)


[error] 82-85: Replace ⏎······readdir(directory),⏎······pathExists(directory)⏎····]).then(([files])·=>·files) with readdir(directory),·pathExists(directory)]).then(([files])·=>·files);

(prettier/prettier)


[error] 85-85: 'files' is already declared in the upper scope on line 82 column 11.

(no-shadow)


[error] 87-87: 'file' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 90-90: Insert ;

(prettier/prettier)


[error] 91-91: Unexpected string concatenation.

(prefer-template)


[error] 91-91: Insert ;

(prettier/prettier)


[error] 92-92: Insert ;

(prettier/prettier)


[error] 94-94: Unexpected await inside a loop.

(no-await-in-loop)


[error] 94-94: 'isDirectory' was used before it was defined.

(no-use-before-define)


[error] 95-95: Unexpected await inside a loop.

(no-await-in-loop)


[error] 97-97: Unexpected await inside a loop.

(no-await-in-loop)


[error] 97-97: Insert ;

(prettier/prettier)


[error] 106-106: Insert ;

(prettier/prettier)


[error] 107-107: Insert ;

(prettier/prettier)


[error] 117-117: This line has a length of 135. Maximum allowed is 120.

(max-len)


[error] 117-117: Unexpected await inside a loop.

(no-await-in-loop)


[error] 117-117: Replace [[fileName,·slug]],·resultObj,·basePath,·details.title,·details.sectionId,·rootId,·details.sectionWeight) with ⏎··········[[fileName,·slug]],⏎··········resultObj,⏎··········basePath,⏎··········details.title,⏎··········details.sectionId,⏎··········rootId,⏎··········details.sectionWeight⏎········);

(prettier/prettier)


[error] 118-118: Unexpected string concatenation.

(prefer-template)


[error] 119-119: Unexpected await inside a loop.

(no-await-in-loop)


[error] 119-119: Insert ;

(prettier/prettier)


[error] 131-131: Insert ;

(prettier/prettier)


[error] 132-132: Insert ;

(prettier/prettier)


[error] 133-133: Insert ;

(prettier/prettier)


[error] 135-135: Insert ;

(prettier/prettier)


[error] 191-191: Insert ;

(prettier/prettier)


[error] 195-195: Insert ⏎····

(prettier/prettier)


[error] 196-196: Replace word with (word)

(prettier/prettier)


[error] 200-200: Insert ;

(prettier/prettier)

🔇 Additional comments (4)
scripts/build-post-list.js (4)

1-2: LGTM! Good choice using fs-extra

The switch to fs-extra is a good improvement as it provides more robust file operations and automatically handles edge cases like creating directories if they don't exist.

🧰 Tools
🪛 eslint

[error] 1-1: Insert ;

(prettier/prettier)


[error] 2-2: Insert ;

(prettier/prettier)


166-187: LGTM! Well-documented regex and robust validation

The slugifyToC function improvements are excellent:

  • Clear regex with descriptive comments
  • Proper input validation
  • Explicit return types

49-58: LGTM! Comprehensive input validation with clear error messages

The input validation is thorough and provides clear, descriptive error messages that help users understand what went wrong and how to fix it.

🧰 Tools
🪛 eslint

[error] 50-50: Replace 'Error·while·building·post·list:·basePath·is·required.·Please·provide·a·valid·base·path·for·resolving·relative·paths.' with ⏎········'Error·while·building·post·list:·basePath·is·required.·Please·provide·a·valid·base·path·for·resolving·relative·paths.'⏎······

(prettier/prettier)


[error] 53-53: Replace 'Error·while·building·post·list:·writeFilePath·is·required.·Please·provide·a·valid·path·where·the·output·JSON·will·be·written.' with ⏎········'Error·while·building·post·list:·writeFilePath·is·required.·Please·provide·a·valid·path·where·the·output·JSON·will·be·written.'⏎······

(prettier/prettier)


[error] 57-57: Replace 'Error·while·building·post·list:·No·post·directories·provided.·Please·provide·an·array·of·[directory,·slug]·tuples.' with ⏎········'Error·while·building·post·list:·No·post·directories·provided.·Please·provide·an·array·of·[directory,·slug]·tuples.'⏎······

(prettier/prettier)


134-138: LGTM! Good refactoring of version details logic

The extraction of version details logic into a separate function has improved code readability and maintainability.

🧰 Tools
🪛 eslint

[error] 135-135: Insert ;

(prettier/prettier)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (6)
scripts/build-post-list.js (6)

19-25: Consider using object literal for cleaner mapping

The if-else chain can be simplified using an object literal for better maintainability.

-  if (details.slug.startsWith('/docs'))
-    result.docs.push(details)
-  else if (details.slug.startsWith('/blog'))
-    result.blog.push(details)
-  else if (details.slug.startsWith('/about'))
-    result.about.push(details)
+  const sectionMap = {
+    '/docs': 'docs',
+    '/blog': 'blog',
+    '/about': 'about'
+  };
+  const section = Object.keys(sectionMap).find(key => details.slug.startsWith(key));
+  if (section) {
+    result[sectionMap[section]].push(details);
+  }
🧰 Tools
🪛 eslint

[error] 19-20: Replace ⏎····result.docs.push(details) with ·result.docs.push(details);

(prettier/prettier)


[error] 21-22: Replace ⏎····result.blog.push(details) with ·result.blog.push(details);

(prettier/prettier)


[error] 23-24: Replace ⏎····result.about.push(details) with ·result.about.push(details);

(prettier/prettier)


27-35: Consider avoiding global state mutation

The function modifies the global specWeight variable, which could lead to issues if the function is called multiple times or in parallel. Consider passing the weight as a parameter.

-function getVersionDetails(slug) {
+function getVersionDetails(slug, currentWeight) {
   const fileBaseName = basename(slug);
   const versionName = fileBaseName.split('-')[0];
   return {
     title: versionName.startsWith('v') ?
       capitalize(versionName.slice(1)) :
       capitalize(versionName),
-    weight: specWeight--
+    weight: currentWeight
   };
 }
🧰 Tools
🪛 eslint

[error] 31-33: Replace ⏎······capitalize(versionName.slice(1))·:⏎····· with ·capitalize(versionName.slice(1))·:

(prettier/prettier)


[error] 32-32: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 33-33: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 34-34: Unary operator '--' used.

(no-plusplus)


49-58: Consider more concise error messages

The error messages are descriptive but verbose. Consider making them more concise while maintaining clarity.

-      throw new Error('Error while building post list: basePath is required. Please provide a valid base path for resolving relative paths.');
+      throw new Error('Error while building post list: basePath is required');

-      throw new Error('Error while building post list: writeFilePath is required. Please provide a valid path where the output JSON will be written.');
+      throw new Error('Error while building post list: writeFilePath is required');

-      throw new Error('Error while building post list: No post directories provided. Please provide an array of [directory, slug] tuples.');
+      throw new Error('Error while building post list: postDirectories array is empty');
🧰 Tools
🪛 eslint

[error] 50-50: Replace 'Error·while·building·post·list:·basePath·is·required.·Please·provide·a·valid·base·path·for·resolving·relative·paths.' with ⏎········'Error·while·building·post·list:·basePath·is·required.·Please·provide·a·valid·base·path·for·resolving·relative·paths.'⏎······

(prettier/prettier)


[error] 53-53: Replace 'Error·while·building·post·list:·writeFilePath·is·required.·Please·provide·a·valid·path·where·the·output·JSON·will·be·written.' with ⏎········'Error·while·building·post·list:·writeFilePath·is·required.·Please·provide·a·valid·path·where·the·output·JSON·will·be·written.'⏎······

(prettier/prettier)


[error] 57-57: Replace 'Error·while·building·post·list:·No·post·directories·provided.·Please·provide·an·array·of·[directory,·slug]·tuples.' with ⏎········'Error·while·building·post·list:·No·post·directories·provided.·Please·provide·an·array·of·[directory,·slug]·tuples.'⏎······

(prettier/prettier)


88-89: Use template literals for path construction

Using string concatenation for paths is error-prone. Consider using template literals.

-      const slug = '/' + normalize(relative(basePath, fileName)).replace(/\\/g, '/')
-      const slugElements = slug.split('/')
+      const slug = `/${normalize(relative(basePath, fileName)).replace(/\\/g, '/')}`
+      const slugElements = slug.split('/')
🧰 Tools
🪛 eslint

[error] 88-88: Unexpected string concatenation.

(prefer-template)


[error] 88-88: Insert ;

(prettier/prettier)


[error] 89-89: Insert ;

(prettier/prettier)


Line range hint 70-162: Consider breaking down the walkDirectories function

The function is quite complex with multiple responsibilities. Consider extracting the file processing logic into a separate function for better maintainability.

Example structure:

async function processFile(file, directory, basePath, options) {
  // File processing logic here
}

async function walkDirectories(directories, resultObj, basePath, options) {
  for (const dir of directories) {
    const files = await readdir(directory);
    for (const file of files) {
      await processFile(file, directory, basePath, options);
    }
  }
}
🧰 Tools
🪛 eslint

[error] 15-15: Insert ;

(prettier/prettier)


[error] 16-16: Insert ;

(prettier/prettier)


[error] 19-20: Replace ⏎····result.docs.push(details) with ·result.docs.push(details);

(prettier/prettier)


[error] 21-22: Replace ⏎····result.blog.push(details) with ·result.blog.push(details);

(prettier/prettier)


[error] 23-24: Replace ⏎····result.about.push(details) with ·result.about.push(details);

(prettier/prettier)


[error] 31-33: Replace ⏎······capitalize(versionName.slice(1))·:⏎····· with ·capitalize(versionName.slice(1))·:

(prettier/prettier)


[error] 32-32: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 33-33: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 34-34: Unary operator '--' used.

(no-plusplus)


[error] 48-49: Delete

(prettier/prettier)


[error] 50-50: Replace 'Error·while·building·post·list:·basePath·is·required.·Please·provide·a·valid·base·path·for·resolving·relative·paths.' with ⏎········'Error·while·building·post·list:·basePath·is·required.·Please·provide·a·valid·base·path·for·resolving·relative·paths.'⏎······

(prettier/prettier)


[error] 53-53: Replace 'Error·while·building·post·list:·writeFilePath·is·required.·Please·provide·a·valid·path·where·the·output·JSON·will·be·written.' with ⏎········'Error·while·building·post·list:·writeFilePath·is·required.·Please·provide·a·valid·path·where·the·output·JSON·will·be·written.'⏎······

(prettier/prettier)


[error] 57-57: Replace 'Error·while·building·post·list:·No·post·directories·provided.·Please·provide·an·array·of·[directory,·slug]·tuples.' with ⏎········'Error·while·building·post·list:·No·post·directories·provided.·Please·provide·an·array·of·[directory,·slug]·tuples.'⏎······

(prettier/prettier)


[error] 59-59: Insert ;

(prettier/prettier)


[error] 60-60: 'walkDirectories' was used before it was defined.

(no-use-before-define)


[error] 60-60: Insert ;

(prettier/prettier)


[error] 61-61: Insert ;

(prettier/prettier)


[error] 62-62: Insert ;

(prettier/prettier)


[error] 63-63: Insert ;

(prettier/prettier)


[error] 64-64: Insert ;

(prettier/prettier)


[error] 79-79: 'dir' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 82-82: Unexpected await inside a loop.

(no-await-in-loop)


[error] 82-82: Insert ;

(prettier/prettier)


[error] 84-84: 'file' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 87-87: Insert ;

(prettier/prettier)


[error] 88-88: Unexpected string concatenation.

(prefer-template)


[error] 88-88: Insert ;

(prettier/prettier)


[error] 89-89: Insert ;

(prettier/prettier)


[error] 91-91: Unexpected await inside a loop.

(no-await-in-loop)


[error] 91-91: 'isDirectory' was used before it was defined.

(no-use-before-define)


[error] 92-92: Unexpected await inside a loop.

(no-await-in-loop)


[error] 94-94: Unexpected await inside a loop.

(no-await-in-loop)


[error] 94-94: Insert ;

(prettier/prettier)


[error] 95-95: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 95-95: Insert ;

(prettier/prettier)


175-176: Consider more specific error handling

The function silently returns empty string for invalid inputs. Consider throwing errors for better debugging.

-  if (typeof str !== 'string') return '';
-  if (!str.trim()) return '';
+  if (typeof str !== 'string') {
+    throw new TypeError('slugifyToC: Input must be a string');
+  }
+  if (!str.trim()) {
+    throw new Error('slugifyToC: Input string cannot be empty');
+  }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5d01e26 and eb0e387.

📒 Files selected for processing (1)
  • scripts/build-post-list.js (7 hunks)
🧰 Additional context used
📓 Learnings (1)
scripts/build-post-list.js (2)
Learnt from: vishvamsinh28
PR: asyncapi/website#3284
File: scripts/build-post-list.js:28-46
Timestamp: 2024-11-12T06:59:33.852Z
Learning: In the `scripts/build-post-list.js` JavaScript file, tests rely on the `result` object being a global variable. Moving it inside the `buildPostList` function causes tests to fail; therefore, keep `result` as a global variable.
Learnt from: vishvamsinh28
PR: asyncapi/website#3284
File: scripts/build-post-list.js:49-53
Timestamp: 2024-11-12T06:59:33.851Z
Learning: In `scripts/build-post-list.js`, the `walkDirectories` function depends on sequential execution because it mutates `resultObj`. Parallelizing the loop with `Promise.all` causes tests to fail.
🪛 eslint
scripts/build-post-list.js

[error] 1-1: Insert ;

(prettier/prettier)


[error] 2-2: Insert ;

(prettier/prettier)


[error] 19-20: Replace ⏎····result.docs.push(details) with ·result.docs.push(details);

(prettier/prettier)


[error] 21-22: Replace ⏎····result.blog.push(details) with ·result.blog.push(details);

(prettier/prettier)


[error] 23-24: Replace ⏎····result.about.push(details) with ·result.about.push(details);

(prettier/prettier)


[error] 31-33: Replace ⏎······capitalize(versionName.slice(1))·:⏎····· with ·capitalize(versionName.slice(1))·:

(prettier/prettier)


[error] 32-32: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 33-33: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 34-34: Unary operator '--' used.

(no-plusplus)


[error] 48-49: Delete

(prettier/prettier)


[error] 50-50: Replace 'Error·while·building·post·list:·basePath·is·required.·Please·provide·a·valid·base·path·for·resolving·relative·paths.' with ⏎········'Error·while·building·post·list:·basePath·is·required.·Please·provide·a·valid·base·path·for·resolving·relative·paths.'⏎······

(prettier/prettier)


[error] 53-53: Replace 'Error·while·building·post·list:·writeFilePath·is·required.·Please·provide·a·valid·path·where·the·output·JSON·will·be·written.' with ⏎········'Error·while·building·post·list:·writeFilePath·is·required.·Please·provide·a·valid·path·where·the·output·JSON·will·be·written.'⏎······

(prettier/prettier)


[error] 57-57: Replace 'Error·while·building·post·list:·No·post·directories·provided.·Please·provide·an·array·of·[directory,·slug]·tuples.' with ⏎········'Error·while·building·post·list:·No·post·directories·provided.·Please·provide·an·array·of·[directory,·slug]·tuples.'⏎······

(prettier/prettier)


[error] 59-59: Insert ;

(prettier/prettier)


[error] 60-60: 'walkDirectories' was used before it was defined.

(no-use-before-define)


[error] 60-60: Insert ;

(prettier/prettier)


[error] 61-61: Insert ;

(prettier/prettier)


[error] 62-62: Insert ;

(prettier/prettier)


[error] 63-63: Insert ;

(prettier/prettier)


[error] 64-64: Insert ;

(prettier/prettier)


[error] 79-79: 'dir' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 82-82: Unexpected await inside a loop.

(no-await-in-loop)


[error] 82-82: Insert ;

(prettier/prettier)


[error] 84-84: 'file' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 87-87: Insert ;

(prettier/prettier)


[error] 88-88: Unexpected string concatenation.

(prefer-template)


[error] 88-88: Insert ;

(prettier/prettier)


[error] 89-89: Insert ;

(prettier/prettier)


[error] 91-91: Unexpected await inside a loop.

(no-await-in-loop)


[error] 91-91: 'isDirectory' was used before it was defined.

(no-use-before-define)


[error] 92-92: Unexpected await inside a loop.

(no-await-in-loop)


[error] 94-94: Unexpected await inside a loop.

(no-await-in-loop)


[error] 94-94: Insert ;

(prettier/prettier)


[error] 103-103: Insert ;

(prettier/prettier)


[error] 104-104: Insert ;

(prettier/prettier)


[error] 114-114: This line has a length of 135. Maximum allowed is 120.

(max-len)


[error] 114-114: Unexpected await inside a loop.

(no-await-in-loop)


[error] 114-114: Replace [[fileName,·slug]],·resultObj,·basePath,·details.title,·details.sectionId,·rootId,·details.sectionWeight) with ⏎··········[[fileName,·slug]],⏎··········resultObj,⏎··········basePath,⏎··········details.title,⏎··········details.sectionId,⏎··········rootId,⏎··········details.sectionWeight⏎········);

(prettier/prettier)


[error] 115-115: Unexpected string concatenation.

(prefer-template)


[error] 116-116: Unexpected await inside a loop.

(no-await-in-loop)


[error] 116-116: Insert ;

(prettier/prettier)


[error] 128-128: Insert ;

(prettier/prettier)


[error] 129-129: Insert ;

(prettier/prettier)


[error] 130-130: Insert ;

(prettier/prettier)


[error] 132-132: Insert ;

(prettier/prettier)


[error] 189-189: Insert ;

(prettier/prettier)


[error] 193-193: Insert ⏎····

(prettier/prettier)


[error] 194-194: Replace word with (word)

(prettier/prettier)


[error] 198-198: Insert ;

(prettier/prettier)

🔇 Additional comments (1)
scripts/build-post-list.js (1)

1-1: Good choice using fs-extra!

Using fs-extra is a good improvement as it provides more robust file operations and automatically creates directories when needed during write operations.

🧰 Tools
🪛 eslint

[error] 1-1: Insert ;

(prettier/prettier)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🔭 Outside diff range comments (1)
scripts/build-post-list.js (1)

Line range hint 74-165: Consider breaking down the complex walkDirectories function

The function is doing too much and could benefit from being split into smaller, focused functions.

Consider extracting the file processing logic:

+ async function processFile(file, directory, basePath, details) {
+   const fileName = normalize(join(directory, file));
+   if (await isDirectory(fileName)) {
+     return processDirectory(fileName, basePath, details);
+   }
+   if (file.endsWith('.mdx') && !fileName.endsWith(sep + '_section.mdx')) {
+     return processMarkdownFile(fileName, basePath, details);
+   }
+   return null;
+ }

 async function walkDirectories(
   directories,
   resultObj,
   basePath,
   sectionTitle,
   sectionId,
   rootSectionId,
   sectionWeight = 0
 ) {
   for (let dir of directories) {
     const directory = posix.normalize(dir[0]);
     const sectionSlug = dir[1] || '';
     const files = await readdir(directory);
     
     for (let file of files) {
-      // ... existing file processing logic
+      const result = await processFile(file, directory, basePath, {
+        sectionSlug,
+        sectionTitle,
+        sectionId,
+        rootSectionId,
+        sectionWeight
+      });
+      if (result) addItem(result);
     }
   }
 }
🧰 Tools
🪛 eslint

[error] 15-15: Insert ;

(prettier/prettier)


[error] 16-16: Insert ;

(prettier/prettier)


[error] 24-24: Replace (key with ((key)

(prettier/prettier)


[error] 34-36: Replace ⏎······capitalize(versionName.slice(1))·:⏎····· with ·capitalize(versionName.slice(1))·:

(prettier/prettier)


[error] 35-35: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 36-36: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 37-37: Unary operator '--' used.

(no-plusplus)


[error] 51-52: Delete

(prettier/prettier)


[error] 63-63: Insert ;

(prettier/prettier)


[error] 64-64: 'walkDirectories' was used before it was defined.

(no-use-before-define)


[error] 64-64: Insert ;

(prettier/prettier)


[error] 65-65: Insert ;

(prettier/prettier)


[error] 66-66: Insert ;

(prettier/prettier)


[error] 67-67: Insert ;

(prettier/prettier)


[error] 68-68: Insert ;

(prettier/prettier)


[error] 83-83: 'dir' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 86-86: Unexpected await inside a loop.

(no-await-in-loop)


[error] 86-86: Insert ;

(prettier/prettier)


[error] 88-88: 'file' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 91-91: Insert ;

(prettier/prettier)


[error] 92-92: Insert ;

(prettier/prettier)


[error] 93-93: Insert ;

(prettier/prettier)


[error] 95-95: Unexpected await inside a loop.

(no-await-in-loop)


[error] 95-95: 'isDirectory' was used before it was defined.

(no-use-before-define)


[error] 96-96: Unexpected await inside a loop.

(no-await-in-loop)


[error] 98-98: Unexpected await inside a loop.

(no-await-in-loop)


[error] 98-98: Insert ;

(prettier/prettier)


[error] 99-99: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 99-99: Insert ;

(prettier/prettier)

🧹 Nitpick comments (2)
scripts/build-post-list.js (2)

19-28: Consider using early return pattern

The implementation is clean with the section mapping, but could be slightly optimized.

 const addItem = (details) => {
   const sectionMap = {
     '/docs': 'docs',
     '/blog': 'blog',
     '/about': 'about'
   };
   const section = Object.keys(sectionMap).find(key => details.slug.startsWith(key));
-  if (section) {
-    result[sectionMap[section]].push(details);
-  }
+  if (!section) return;
+  result[sectionMap[section]].push(details);
 };
🧰 Tools
🪛 eslint

[error] 24-24: Replace (key with ((key)

(prettier/prettier)


49-70: Enhance error messages with more context

While the error handling is good, the error messages could be more specific about what's missing or invalid.

-      throw new Error('Error while building post list: basePath is required');
+      throw new Error('Error while building post list: basePath parameter is required for resolving file paths');

-      throw new Error('Error while building post list: writeFilePath is required');
+      throw new Error('Error while building post list: writeFilePath parameter is required for output destination');

-      throw new Error('Error while building post list: postDirectories array is empty');
+      throw new Error('Error while building post list: postDirectories array is empty, at least one directory is required');
🧰 Tools
🪛 eslint

[error] 51-52: Delete

(prettier/prettier)


[error] 63-63: Insert ;

(prettier/prettier)


[error] 64-64: 'walkDirectories' was used before it was defined.

(no-use-before-define)


[error] 64-64: Insert ;

(prettier/prettier)


[error] 65-65: Insert ;

(prettier/prettier)


[error] 66-66: Insert ;

(prettier/prettier)


[error] 67-67: Insert ;

(prettier/prettier)


[error] 68-68: Insert ;

(prettier/prettier)

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between eb0e387 and a795ce0.

📒 Files selected for processing (1)
  • scripts/build-post-list.js (7 hunks)
🧰 Additional context used
📓 Learnings (1)
scripts/build-post-list.js (2)
Learnt from: vishvamsinh28
PR: asyncapi/website#3284
File: scripts/build-post-list.js:28-46
Timestamp: 2024-11-12T06:59:33.852Z
Learning: In the `scripts/build-post-list.js` JavaScript file, tests rely on the `result` object being a global variable. Moving it inside the `buildPostList` function causes tests to fail; therefore, keep `result` as a global variable.
Learnt from: vishvamsinh28
PR: asyncapi/website#3284
File: scripts/build-post-list.js:49-53
Timestamp: 2024-11-12T06:59:33.851Z
Learning: In `scripts/build-post-list.js`, the `walkDirectories` function depends on sequential execution because it mutates `resultObj`. Parallelizing the loop with `Promise.all` causes tests to fail.
🪛 eslint
scripts/build-post-list.js

[error] 1-1: Insert ;

(prettier/prettier)


[error] 2-2: Insert ;

(prettier/prettier)


[error] 24-24: Replace (key with ((key)

(prettier/prettier)


[error] 34-36: Replace ⏎······capitalize(versionName.slice(1))·:⏎····· with ·capitalize(versionName.slice(1))·:

(prettier/prettier)


[error] 35-35: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 36-36: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 37-37: Unary operator '--' used.

(no-plusplus)


[error] 51-52: Delete

(prettier/prettier)


[error] 63-63: Insert ;

(prettier/prettier)


[error] 64-64: 'walkDirectories' was used before it was defined.

(no-use-before-define)


[error] 64-64: Insert ;

(prettier/prettier)


[error] 65-65: Insert ;

(prettier/prettier)


[error] 66-66: Insert ;

(prettier/prettier)


[error] 67-67: Insert ;

(prettier/prettier)


[error] 68-68: Insert ;

(prettier/prettier)


[error] 83-83: 'dir' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 86-86: Unexpected await inside a loop.

(no-await-in-loop)


[error] 86-86: Insert ;

(prettier/prettier)


[error] 88-88: 'file' is never reassigned. Use 'const' instead.

(prefer-const)


[error] 91-91: Insert ;

(prettier/prettier)


[error] 92-92: Insert ;

(prettier/prettier)


[error] 93-93: Insert ;

(prettier/prettier)


[error] 95-95: Unexpected await inside a loop.

(no-await-in-loop)


[error] 95-95: 'isDirectory' was used before it was defined.

(no-use-before-define)


[error] 96-96: Unexpected await inside a loop.

(no-await-in-loop)


[error] 98-98: Unexpected await inside a loop.

(no-await-in-loop)


[error] 98-98: Insert ;

(prettier/prettier)


[error] 107-107: Insert ;

(prettier/prettier)


[error] 108-108: Insert ;

(prettier/prettier)


[error] 118-118: This line has a length of 135. Maximum allowed is 120.

(max-len)


[error] 118-118: Unexpected await inside a loop.

(no-await-in-loop)


[error] 118-118: Replace [[fileName,·slug]],·resultObj,·basePath,·details.title,·details.sectionId,·rootId,·details.sectionWeight) with ⏎··········[[fileName,·slug]],⏎··········resultObj,⏎··········basePath,⏎··········details.title,⏎··········details.sectionId,⏎··········rootId,⏎··········details.sectionWeight⏎········);

(prettier/prettier)


[error] 119-119: Unexpected string concatenation.

(prefer-template)


[error] 120-120: Unexpected await inside a loop.

(no-await-in-loop)


[error] 120-120: Insert ;

(prettier/prettier)


[error] 132-132: Insert ;

(prettier/prettier)


[error] 133-133: Insert ;

(prettier/prettier)


[error] 134-134: Insert ;

(prettier/prettier)


[error] 136-136: Insert ;

(prettier/prettier)


[error] 193-193: Insert ;

(prettier/prettier)


[error] 197-197: Insert ⏎····

(prettier/prettier)


[error] 198-198: Replace word with (word)

(prettier/prettier)


[error] 202-202: Insert ;

(prettier/prettier)

🔇 Additional comments (2)
scripts/build-post-list.js (2)

1-2: LGTM: Good choice switching to fs-extra

The switch to fs-extra is a good improvement as it provides better error handling and ensures parent directories exist when writing files.

🧰 Tools
🪛 eslint

[error] 1-1: Insert ;

(prettier/prettier)


[error] 2-2: Insert ;

(prettier/prettier)


168-189: LGTM: Well-implemented heading ID extraction

The implementation is clean with:

  • Clear regex pattern with good documentation
  • Proper input validation
  • Good error handling

Comment on lines 30 to 38
function getVersionDetails(slug) {
const fileBaseName = basename(slug);
const versionName = fileBaseName.split('-')[0];
return {
title: versionName.startsWith('v') ?
capitalize(versionName.slice(1)) :
capitalize(versionName),
weight: specWeight--
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider removing dependency on global state

The function relies on the global specWeight variable which could lead to unexpected behavior if the function is called multiple times or in parallel.

Consider passing the weight as a parameter:

-function getVersionDetails(slug) {
+function getVersionDetails(slug, weight) {
   const fileBaseName = basename(slug);
   const versionName = fileBaseName.split('-')[0];
   return {
     title: versionName.startsWith('v') ?
       capitalize(versionName.slice(1)) :
       capitalize(versionName),
-    weight: specWeight--
+    weight
   };
 }

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 eslint

[error] 34-36: Replace ⏎······capitalize(versionName.slice(1))·:⏎····· with ·capitalize(versionName.slice(1))·:

(prettier/prettier)


[error] 35-35: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 36-36: 'capitalize' was used before it was defined.

(no-use-before-define)


[error] 37-37: Unary operator '--' used.

(no-plusplus)

@vishvamsinh28
Copy link
Contributor Author

@akshatnema I think we are good to go now because CodeRabbit keeps giving the same nitpick comments. If we apply those changes, the next comment suggests reverting them to the original, and this cycle continues

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
gsoc This label should be used for issues or discussions related to ideas for Google Summer of Code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants