Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@yoshinorin
Copy link
Member

@yoshinorin yoshinorin commented Oct 11, 2025

The following issues will likely be fixed:

What does it do?

This PR fixes an issue where updated post assets were not being copied in hot processing. This issue introduced in #5473.

Cause

The processAsset function had three issues.

1. Path separator mismatch:

As @D-Sketon pointed out in PR #5473 comment, the original code used OS-specific sep (backslash \ on Windows) when extracting the asset directory path. This caused the path matching to fail on Windows.

2. Path format inconsistency:

The extracted asset directory path was in relative format with forward slashes (e.g., source/_posts/bar), but post.asset_dir is an OS-specific
absolute path (e.g., C:\Users\...\source\_posts\bar\ on Windows). This format mismatch prevented retrieving the correct post.

3. Incorrect Post.findOne() usage

Post.findOne() with both query function and object syntax returned incorrect results. It either returned the wrong post or null, preventing
assets from being associated with the correct post. I have not investigated why Post.findOne() doesn't work correctly here.

Solution

  • Use posix.sep (/) consistently when extracting the asset directory from the normalized id
  • Convert the relative path to an OS-specific absolute path for comparison with post.asset_dir
  • Replace Post.findOne() with Post.filter() to ensure correct post lookup

Screenshots

N/A

Pull request tasks

  • Add test cases for the changes.
  • Passed the CI test.

@github-actions
Copy link

How to test

git clone -b fix/generate-asset-when-hotreload https://github.com/hexojs/hexo.git
cd hexo
npm install
npm test

@coveralls
Copy link

coveralls commented Oct 11, 2025

Pull Request Test Coverage Report for Build 18782179721

Details

  • 18 of 18 (100.0%) changed or added relevant lines in 1 file are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.001%) to 99.527%

Totals Coverage Status
Change from base Build 18782167202: 0.001%
Covered Lines: 9882
Relevant Lines: 9929

💛 - Coveralls

@yoshinorin yoshinorin self-assigned this Oct 11, 2025
@yoshinorin yoshinorin added the bug Something isn't working label Oct 11, 2025
@yoshinorin yoshinorin marked this pull request as ready for review October 11, 2025 17:49
Examples that didn't work:
- `Post.findOne(p => p.asset_dir === absoluteAssetDirPath)` // returned wrong post
- `Post.findOne({asset_dir: absoluteAssetDirPath})` // returned null
Copy link
Member Author

@yoshinorin yoshinorin Oct 11, 2025

Choose a reason for hiding this comment

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

I have not investigated why Post.findOne() does not work as expected.

@yoshinorin yoshinorin changed the title fix(processor/post): updated post assets not being copied in hot processing fix(processor/post): updated post assets not being copied in hot processing when post_asset_folder is enabled Oct 11, 2025
@yoshinorin yoshinorin removed the bug Something isn't working label Oct 11, 2025
@D-Sketon
Copy link
Member

Q: Why does Post.findOne(p => p.asset_dir === absoluteAssetDirPath) return incorrect results?

A: The parameter of the findOne method must be an object, not a function

Q: Why does Post.findOne({asset_dir: absoluteAssetDirPath}) return null?

A: asset_dir is a virtual field. In the findOne(find) method:

find(query: object, options: Partial<Options> = {}): Query<T> | T[] {
  const filter = this.schema._execQuery(query);
  // ...
  for (let i = 0; limit && i < len; i++) {
    const key = keys[i];
    const item = data[key];  // ⚠️ This is the raw stored data, without virtual fields
    
    if (item && filter(item)) {  // ⚠️ filter runs on raw data, so asset_dir cannot be found
      arr.push(this.findById(key, options) as any);
      limit--;
    }
  }
}

Whereas in the filter(forEach) method:

forEach(iterator: ..., options?: Partial<Options>): void {
  const keys = this.dataKeys;
  let num = 0;
  for (let i = 0, len = keys.length; i < len; i++) {
    const data = this.findById(keys[i], options);  // ✅ Returns a Document object, on which virtual getters exist
    if (data) iterator(data as any, num++);
  }
}

Copy link
Member

@D-Sketon D-Sketon left a comment

Choose a reason for hiding this comment

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

works well on my windows

@yoshinorin yoshinorin merged commit 03a3a4e into master Oct 25, 2025
23 checks passed
@yoshinorin yoshinorin deleted the fix/generate-asset-when-hotreload branch October 25, 2025 04:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants