Skip to content

Commit

Permalink
Async rendering of tags within a post
Browse files Browse the repository at this point in the history
  • Loading branch information
ppwwyyxx committed Mar 30, 2022
1 parent 8d21027 commit 0ea8a53
Showing 1 changed file with 24 additions and 14 deletions.
38 changes: 24 additions & 14 deletions lib/hexo/post.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,21 @@ const isNonWhiteSpaceChar = char => char !== '\r'
&& char !== '\v'
&& char !== ' ';

function replaceAsync(string, searchValue, replacer) {
// An alternative to string.replace, but with an async replacer.
// Reference: https://github.com/dsblv/string-replace-async
var values = [];
String.prototype.replace.call(string, searchValue, function () {
values.push(replacer.apply(undefined, arguments));
return "";
});
return Promise.all(values).then(function (resolvedValues) {
return String.prototype.replace.call(string, searchValue, function () {
return resolvedValues.shift();
});
});
}

class PostRenderEscape {
constructor() {
this.stored = [];
Expand All @@ -47,11 +62,6 @@ class PostRenderEscape {
};
}

restoreAllSwigTags(str) {
const restored = str.replace(rSwigPlaceHolder, PostRenderEscape.restoreContent(this.stored));
return restored;
}

restoreCodeBlocks(str) {
return str.replace(rCodeBlockPlaceHolder, PostRenderEscape.restoreContent(this.stored));
}
Expand Down Expand Up @@ -415,17 +425,17 @@ class Post {
path: source,
engine: data.engine,
toString: true,
onRenderEnd(content) {
// Replace cache data with real contents
data.content = cacheObj.restoreAllSwigTags(content);

// Return content after replace the placeholders
if (disableNunjucks) return data.content;
}, options);
}).then(content => {
// Use replaceAsync so that tags within a post can render concurrently
return replaceAsync(content, rSwigPlaceHolder, async(match, name) => {
// Replace swig placeholder produced by `escapeAllSwigTags` with real contents stored previously
let ret = PostRenderEscape.restoreContent(cacheObj.stored)(match, name);
if (disableNunjucks) return ret;

// Render with Nunjucks
return tag.render(data.content, data);
}
}, options);
return await tag.render(ret, data);
});
}).then(content => {
data.content = cacheObj.restoreCodeBlocks(content);

Expand Down

0 comments on commit 0ea8a53

Please sign in to comment.