From 373b9c745cb5dfe25e942e720aca2cdac78e1874 Mon Sep 17 00:00:00 2001 From: segayuu Date: Fri, 13 Apr 2018 23:23:48 +0900 Subject: [PATCH] Split cache in Post.prototype.render() into classes (#3117) * Divide internal cache of Post.prototype.render into classes * move RegExp object into local scope * Combine unnecessarily divided callbacks in Post.prototype.render(). * refactor: Post.prototype.render() --- lib/hexo/post.js | 110 +++++++++++++++++++++++------------------------ 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/lib/hexo/post.js b/lib/hexo/post.js index 181faf8e39..5710908910 100644 --- a/lib/hexo/post.js +++ b/lib/hexo/post.js @@ -9,16 +9,40 @@ const { slugize, escapeRegExp } = require('hexo-util'); const fs = require('hexo-fs'); const yfm = require('hexo-front-matter'); -const rEscapeContent = /]*)>([\s\S]*?)<\/escape>/g; -const rSwigVar = /\{\{[\s\S]*?\}\}/g; -const rSwigComment = /\{#[\s\S]*?#\}/g; -const rSwigBlock = /\{%[\s\S]*?%\}/g; -const rSwigFullBlock = /\{% *(.+?)(?: *| +.*)%\}[\s\S]+?\{% *end\1 *%\}/g; -const placeholder = '\uFFFC'; -const rPlaceholder = /(?:<|<)!--\uFFFC(\d+)--(?:>|>)/g; - const preservedKeys = ['title', 'slug', 'path', 'layout', 'date', 'content']; +function PostRenderCache() { + this.cache = []; +} + +const _escapeContent = (cache, str) => { + const placeholder = '\uFFFC'; + return ``; +}; + +PostRenderCache.prototype.escapeContent = function(str) { + const rEscapeContent = /]*)>([\s\S]*?)<\/escape>/g; + return str.replace(rEscapeContent, (_, content) => _escapeContent(this.cache, content)); +}; + +PostRenderCache.prototype.loadContent = function(str) { + const rPlaceholder = /(?:<|<)!--\uFFFC(\d+)--(?:>|>)/g; + return str.replace(rPlaceholder, (_, index) => this.cache[index]); +}; + +PostRenderCache.prototype.escapeAllSwigTags = function(str) { + const rSwigVar = /\{\{[\s\S]*?\}\}/g; + const rSwigComment = /\{#[\s\S]*?#\}/g; + const rSwigBlock = /\{%[\s\S]*?%\}/g; + const rSwigFullBlock = /\{% *(.+?)(?: *| +.*)%\}[\s\S]+?\{% *end\1 *%\}/g; + + const escape = _str => _escapeContent(this.cache, _str); + return str.replace(rSwigFullBlock, escape) + .replace(rSwigBlock, escape) + .replace(rSwigComment, '') + .replace(rSwigVar, escape); +}; + function Post(context) { this.context = context; } @@ -200,36 +224,9 @@ Post.prototype.publish = function(data, replace, callback) { Post.prototype.render = function(source, data = {}, callback) { const ctx = this.context; const { config } = ctx; - const cache = []; const { tag } = ctx.extend; const ext = data.engine || (source ? pathFn.extname(source) : ''); - const isSwig = ext === 'swig'; - - let disableNunjucks = false; - - if (ext && ctx.render.renderer.get(ext)) { - - // disable Nunjucks when the renderer spcify that. - - disableNunjucks = disableNunjucks || !!ctx.render.renderer.get(ext).disableNunjucks; - - } - - function escapeContent(str) { - return ``; - } - - function tagFilter(content) { - if (disableNunjucks) return content; - // Replace cache data with real contents - content = content.replace(rPlaceholder, (...args) => cache[args[1]]); - - // Render with Nunjucks - data.content = content; - return tag.render(data.content, data); - } - let promise; if (data.content != null) { @@ -241,24 +238,29 @@ Post.prototype.render = function(source, data = {}, callback) { return Promise.reject(new Error('No input file or string!')).asCallback(callback); } + const isSwig = ext === 'swig'; + + // disable Nunjucks when the renderer spcify that. + const disableNunjucks = ext && ctx.render.renderer.get(ext) && !!ctx.render.renderer.get(ext).disableNunjucks; + + const cacheObj = new PostRenderCache(); + return promise.then(content => { data.content = content; // Run "before_post_render" filters - return ctx.execFilter('before_post_render', data, {context: ctx}).then(() => { - data.content = data.content.replace(rEscapeContent, (match, content) => escapeContent(content)); - }); + return ctx.execFilter('before_post_render', data, {context: ctx}); }).then(() => { - // Skip rendering if this is a swig file - if (isSwig) return data.content; + data.content = cacheObj.escapeContent(data.content); + + if (isSwig) { + // Render with Nunjucks if this is a swig file + return tag.render(data.content, data); + } // Escape all Swig tags if (!disableNunjucks) { - data.content = data.content - .replace(rSwigFullBlock, escapeContent) - .replace(rSwigBlock, escapeContent) - .replace(rSwigComment, '') - .replace(rSwigVar, escapeContent); + data.content = cacheObj.escapeAllSwigTags(data.content); } const options = data.markdown || {}; @@ -270,17 +272,15 @@ Post.prototype.render = function(source, data = {}, callback) { path: source, engine: data.engine, toString: true, - onRenderEnd: tagFilter - }, options); - }).then(content => { - data.content = content; + onRenderEnd(content) { + if (disableNunjucks) return content; + // Replace cache data with real contents + data.content = cacheObj.loadContent(content); - if (!isSwig) { - return data.content; - } - - // Render with Nunjucks - return tag.render(data.content, data); + // Render with Nunjucks + return tag.render(data.content, data); + } + }, options); }).then(content => { data.content = content;