Skip to content

Commit 0ea8a53

Browse files
committed
Async rendering of tags within a post
1 parent 8d21027 commit 0ea8a53

File tree

1 file changed

+24
-14
lines changed

1 file changed

+24
-14
lines changed

lib/hexo/post.js

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,21 @@ const isNonWhiteSpaceChar = char => char !== '\r'
2929
&& char !== '\v'
3030
&& char !== ' ';
3131

32+
function replaceAsync(string, searchValue, replacer) {
33+
// An alternative to string.replace, but with an async replacer.
34+
// Reference: https://github.com/dsblv/string-replace-async
35+
var values = [];
36+
String.prototype.replace.call(string, searchValue, function () {
37+
values.push(replacer.apply(undefined, arguments));
38+
return "";
39+
});
40+
return Promise.all(values).then(function (resolvedValues) {
41+
return String.prototype.replace.call(string, searchValue, function () {
42+
return resolvedValues.shift();
43+
});
44+
});
45+
}
46+
3247
class PostRenderEscape {
3348
constructor() {
3449
this.stored = [];
@@ -47,11 +62,6 @@ class PostRenderEscape {
4762
};
4863
}
4964

50-
restoreAllSwigTags(str) {
51-
const restored = str.replace(rSwigPlaceHolder, PostRenderEscape.restoreContent(this.stored));
52-
return restored;
53-
}
54-
5565
restoreCodeBlocks(str) {
5666
return str.replace(rCodeBlockPlaceHolder, PostRenderEscape.restoreContent(this.stored));
5767
}
@@ -415,17 +425,17 @@ class Post {
415425
path: source,
416426
engine: data.engine,
417427
toString: true,
418-
onRenderEnd(content) {
419-
// Replace cache data with real contents
420-
data.content = cacheObj.restoreAllSwigTags(content);
421-
422-
// Return content after replace the placeholders
423-
if (disableNunjucks) return data.content;
428+
}, options);
429+
}).then(content => {
430+
// Use replaceAsync so that tags within a post can render concurrently
431+
return replaceAsync(content, rSwigPlaceHolder, async(match, name) => {
432+
// Replace swig placeholder produced by `escapeAllSwigTags` with real contents stored previously
433+
let ret = PostRenderEscape.restoreContent(cacheObj.stored)(match, name);
434+
if (disableNunjucks) return ret;
424435

425436
// Render with Nunjucks
426-
return tag.render(data.content, data);
427-
}
428-
}, options);
437+
return await tag.render(ret, data);
438+
});
429439
}).then(content => {
430440
data.content = cacheObj.restoreCodeBlocks(content);
431441

0 commit comments

Comments
 (0)