hexo
hexo copied to clipboard
plugin issue: Tags removed by `setTags` in before_post_render filter still exists in the tag list but the page is not generated
Check List
- [X] I have already read Docs page & Troubleshooting page.
- [X] I have already searched existing issues and they are not help to me.
- [X] I examined error or warning messages and it's difficult to solve.
- [X] I am using the latest version of Hexo. (run
hexo version
to check) - [X] My Node.js is matched the required version.
Expected behavior
I need to change the posts' tags with my own filter. I find out the setTags
method when using hexo 6.3.0 and it always works before I upgrade to hexo 7.0.
This is an example code:
hexo.extend.filter.register('before_post_render', function (data) {
if (!data.tags || !data.categories) {
return data;
}
data.setTags([]);
return data;
});
In this case, some of the tags are removed completely from my website. I expect those tags to disappear.
I test this problem in my repo branch.
Actual behavior
The tag list remain the removed tags and I can not jump into the tag's page(the page was not generated).
How to reproduce?
simply a post with tag and run with the example filter code above (using the setTags
method to remove tag(s) in before_post_render filter).
Is the problem still there under Safe mode
?
this is a plugin usage problem, and I disabled my theme and my other plugins, I just using the example code, the problem still there.
Your Node.js & npm version
v18.18.0
10.2.4
Your Hexo and Plugin version
[email protected] D:\workspace\hexoProject\blog
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
`-- [email protected]
Your package.json
{
"name": "hexo-site",
"version": "0.0.0",
"private": true,
"scripts": {
"build": "hexo generate",
"clean": "hexo clean",
"deploy": "hexo deploy",
"server": "hexo server"
},
"hexo": {
"version": "7.0.0"
},
"dependencies": {
"hexo": "^7.0.0",
"hexo-filter-nofollow": "^2.0.2",
"hexo-generator-archive": "^2.0.0",
"hexo-generator-category": "^2.0.0",
"hexo-generator-feed": "^3.0.0",
"hexo-generator-index": "^3.0.0",
"hexo-generator-search": "^2.4.3",
"hexo-generator-sitemap": "^3.0.1",
"hexo-generator-tag": "^2.0.0",
"hexo-renderer-ejs": "^2.0.0",
"hexo-renderer-marked": "^6.2.0",
"hexo-renderer-pug": "^3.0.0",
"hexo-renderer-stylus": "^3.0.0",
"hexo-server": "^3.0.0",
"hexo-theme-butterfly": "^4.11.0",
"hexo-theme-landscape": "^1.0.0",
"hexo-wordcount": "^6.0.1"
}
}
Others
No response
related PR: https://github.com/hexojs/hexo/pull/5119 https://github.com/hexojs/hexo/blob/ea4f63cd2a7a6712acb8a15fc36692d8ef52a64b/lib/hexo/index.ts#L299 https://github.com/hexojs/hexo/blob/ca51e15072321577d7cf7dd133d21564a3d54da5/lib/hexo/index.js#L208-L212
related PR: #5119
https://github.com/hexojs/hexo/blob/ea4f63cd2a7a6712acb8a15fc36692d8ef52a64b/lib/hexo/index.ts#L299
https://github.com/hexojs/hexo/blob/ca51e15072321577d7cf7dd133d21564a3d54da5/lib/hexo/index.js#L208-L212
I guess I can run this code once by myself to solve the problem for now.
I tried to run this code in after_post_render
filter and it works. Should I use some other methods?
Does it need to be discussed whether this is a problem?
Here is my solution code, but I'm not entirely know how it works. When I use only the after_post_render
filter, it ran into the problem again at the second generation.
hexo.extend.filter.register('after_post_render', filterSiteTag);
hexo.locals.set('tags', reloadTag);
let _filterSiteTagOnce = false;
function filterSiteTag(data) {
if (!_filterSiteTagOnce) {
_filterSiteTagOnce = true;
this.locals.set('tags', reloadTag);
}
return data;
}
function reloadTag() {
const logger = hexo.log;
// Ignore tags with zero posts
const model = hexo.database.model('Tag');
const filtered = model.filter(tag => tag.length);
logger.info('Tag size: ' + model.length + ' -> ' + filtered.length);
return filtered;
}
I've run into a similar problem when I tried to remove posts dynamically in filters.
Here's some code to demonstrate it:
// FILE: scripts/test.js
hexo.extend.filter.register("before_generate", function () {
this._bindLocals();
// Delete the "hello-world" post which has the "removed" tag.
const posts = this.locals.get("posts");
this.locals.set("posts", posts.filter((post) => post.slug !== "hello-world"));
// The "removed" tag should contain zero posts now, since there is no post tagged with "removed".
const tags = this.locals.get("tags");
const removedTag = tags.findOne({ name: "removed" });
// The behavior in Hexo 7.0:
console.log(removedTag.length); // 1
// Which equals to:
console.log(this.database.model('PostTag').find({ tag_id: removedTag._id }).length); // 1
// The behavior in Hexo 6.3:
console.log(removedTag.posts.length); // 0
// To workaround it, undoing the change introduced in #5119 could help:
// this.locals.set("tags", () => {
// return this.database.model("Tag").filter((tag) => {
// return tag.posts.length;
// });
// });
});
I would like to know if this is working as intended or not. Should we use some other methods to manipulate posts/tags/categories in filters?
I guess 5119 is necessary, it does reduce traversal. Maybe hexo needs a better way to deal with idle tags and categories. For example, when the number of articles in a label or category become 0, delete them. Or, filter labels or categories when they no longer change.
Or, announce to users that if they want to use accurate tags and categories list, they should filter the list.
However, revert is a temporary solution, too.