diff --git a/layout/comment/changyan.ejs b/layout/comment/changyan.ejs deleted file mode 100644 index 09c5266..0000000 --- a/layout/comment/changyan.ejs +++ /dev/null @@ -1,14 +0,0 @@ -<% if (!has_config('comment.appid') || !has_config('comment.conf')) { %> -
- You forgot to set the appid or conf for Changyan. Please set it in _config.yml. -
-<% } else { %> -
- - -<% } %> \ No newline at end of file diff --git a/layout/comment/changyan.jsx b/layout/comment/changyan.jsx new file mode 100644 index 0000000..adcbcfd --- /dev/null +++ b/layout/comment/changyan.jsx @@ -0,0 +1,30 @@ +'use strict'; + +const { Component, Fragment } = require('inferno'); +const { cacheComponent } = require('../util/cache'); + +class ChangeYan extends Component { + render() { + const { appId, conf, path } = this.props; + if (!appId || !conf) { + return
+ You forgot to set the appid or conf for Changyan. + Please set it in _config.yml. +
; + } + const js = `window.changyan.api.config({appid: '${appId}',conf: '${conf}'});`; + return +
+ + +
; + } +} + +module.exports = cacheComponent(ChangeYan, 'comment.changyan', props => { + return { + appId: props.appid, + conf: props.conf, + path: props.page.path + }; +}); diff --git a/layout/comment/changyan.locals.js b/layout/comment/changyan.locals.js deleted file mode 100644 index b285136..0000000 --- a/layout/comment/changyan.locals.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = (ctx, locals) => { - const { page } = ctx; - return Object.assign(locals, { path: page.path }); -} \ No newline at end of file diff --git a/layout/comment/disqus.ejs b/layout/comment/disqus.ejs deleted file mode 100644 index 9587a48..0000000 --- a/layout/comment/disqus.ejs +++ /dev/null @@ -1,22 +0,0 @@ -<% if (has_config('comment.shortname')) { %> - -<% } %> -
- <% if (!has_config('comment.shortname')) { %> -
- You forgot to set the shortname for Disqus. Please set it in _config.yml. -
- <% } %> - -
\ No newline at end of file diff --git a/layout/comment/disqus.jsx b/layout/comment/disqus.jsx new file mode 100644 index 0000000..b90f676 --- /dev/null +++ b/layout/comment/disqus.jsx @@ -0,0 +1,41 @@ +'use strict'; + +const { Component, Fragment } = require('inferno'); +const { cacheComponent } = require('../util/cache'); + +class Disqus extends Component { + render() { + const { shortname, disqusId, path, permalink } = this.props; + if (!shortname) { + return
+ You forgot to set the shortname for Disqus. + Please set it in _config.yml. +
; + } + const js = `var disqus_config = function () { + this.page.url = '${permalink}'; + this.page.identifier = '${disqusId || path}'; + }; + (function() { + var d = document, s = d.createElement('script'); + s.src = '//' + '${shortname}' + '.disqus.com/embed.js'; + s.setAttribute('data-timestamp', +new Date()); + (d.head || d.body).appendChild(s); + })();`; + return +
+ +
+ +
; + } +} + +module.exports = cacheComponent(Disqus, 'comment.disqus', props => { + return { + path: props.page.path, + shortname: props.shortname, + disqusId: props.page.disqusId, + permalink: props.page.permalink + }; +}); diff --git a/layout/comment/disqus.locals.js b/layout/comment/disqus.locals.js deleted file mode 100644 index 665213f..0000000 --- a/layout/comment/disqus.locals.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = (ctx, locals) => { - const { permalink, disqusId, path } = ctx.page; - return Object.assign(locals, { permalink, disqusId, path }); -} \ No newline at end of file diff --git a/layout/comment/facebook.ejs b/layout/comment/facebook.ejs deleted file mode 100644 index 1063f6c..0000000 --- a/layout/comment/facebook.ejs +++ /dev/null @@ -1,8 +0,0 @@ - -
diff --git a/layout/comment/facebook.jsx b/layout/comment/facebook.jsx new file mode 100644 index 0000000..218b20e --- /dev/null +++ b/layout/comment/facebook.jsx @@ -0,0 +1,28 @@ +'use strict'; + +const { Component, Fragment } = require('inferno'); +const { cacheComponent } = require('../util/cache'); + +class Facebook extends Component { + render() { + const { language, permalink } = this.props; + const js = `(function(d, s, id) { + var js, fjs = d.getElementsByTagName(s)[0]; + if (d.getElementById(id)) return; + js = d.createElement(s); js.id = id; + js.src = "//connect.facebook.net/${(language || 'en').split('-').join('_')}/sdk.js#xfbml=1&version=v2.8"; + fjs.parentNode.insertBefore(js, fjs); + }(document, 'script', 'facebook-jssdk'));`; + return +
+ +
; + } +} + +module.exports = cacheComponent(Facebook, 'comment.facebook', props => { + return { + language: props.language, + permalink: props.page.permalink + }; +}); diff --git a/layout/comment/facebook.locals.js b/layout/comment/facebook.locals.js deleted file mode 100644 index d5d7ad8..0000000 --- a/layout/comment/facebook.locals.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = (ctx, locals) => { - const { permalink } = ctx.page; - return Object.assign(locals, { permalink }); -} \ No newline at end of file diff --git a/layout/comment/gitalk.ejs b/layout/comment/gitalk.ejs deleted file mode 100644 index 17cec81..0000000 --- a/layout/comment/gitalk.ejs +++ /dev/null @@ -1,24 +0,0 @@ -<% if (!has_config('comment.owner') || !has_config('comment.admin') || !has_config('comment.repo') || !has_config('comment.client_id') || - !has_config('comment.client_secret')) { %> -
- You forgot to set the owner, admin, repo, client_id, or client_secret for Gittalk. - Please set it in _config.yml. -
-<% } else { %> -
-<%- _css(cdn('gitalk', '1.4.1', 'dist/gitalk.css')) %> -<%- _js(cdn('gitalk', '1.4.1', 'dist/gitalk.min.js')) %> - -<% } %> \ No newline at end of file diff --git a/layout/comment/gitalk.jsx b/layout/comment/gitalk.jsx new file mode 100644 index 0000000..d942ed7 --- /dev/null +++ b/layout/comment/gitalk.jsx @@ -0,0 +1,66 @@ +'use strict'; + +const crypto = require('crypto'); +const { Component, Fragment } = require('inferno'); +const { cacheComponent } = require('../util/cache'); + +class Gitalk extends Component { + render() { + const { + id, + repo, + owner, + admin, + clientId, + clientSecret, + createIssueManually, + distractionFreeMode, + cdn, + url_for + } = this.props; + + if (!id || !repo || !owner || !admin || !clientId || !clientSecret) { + return
+ You forgot to set the owner, admin, repo, + client_id, or client_secret for Gittalk. + Please set it in _config.yml. +
; + } + const js = `var gitalk = new Gitalk({ + id: '${id}', + repo: '${repo}', + owner: '${owner}', + clientID: '${clientId}', + clientSecret: '${clientSecret}', + admin: ${JSON.stringify(admin)}, + createIssueManually: ${createIssueManually || false}, + distractionFreeMode: ${distractionFreeMode || false} + }) + gitalk.render('comment-container')`; + return +
+ + + +
; + } +} + +module.exports = cacheComponent(Gitalk, 'comment.gitalk', props => { + // FIXME: config name change + const id = crypto.createHash('md5').update(props.page.path).digest('hex'); + return { + id, + repo: props.repo, + owner: props.owner, + admin: props.admin, + clientId: props.clientId, + clientSecret: props.clientSecret, + createIssueManually: props.createIssueManually, + distractionFreeMode: props.distractionFreeMode, + cdn: props.cdn, + url_for: props.url_for, + // for cache purpose only + _providers: props.providers.cdn + }; +}); diff --git a/layout/comment/gitalk.locals.js b/layout/comment/gitalk.locals.js deleted file mode 100644 index 145230a..0000000 --- a/layout/comment/gitalk.locals.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = (ctx, locals) => { - const { path } = ctx.page; - return Object.assign(locals, { path }); -} \ No newline at end of file diff --git a/layout/comment/gitment.ejs b/layout/comment/gitment.ejs deleted file mode 100644 index affc597..0000000 --- a/layout/comment/gitment.ejs +++ /dev/null @@ -1,23 +0,0 @@ -<% if (!has_config('comment.owner') || !has_config('comment.repo') || !has_config('comment.client_id') || - !has_config('comment.client_secret')) { %> -
- You forgot to set the owner, repo, client_id, or client_secret for Gitment. - Please set it in _config.yml. -
-<% } else { %> -
- - - -<% } %> \ No newline at end of file diff --git a/layout/comment/gitment.jsx b/layout/comment/gitment.jsx new file mode 100644 index 0000000..0e0046d --- /dev/null +++ b/layout/comment/gitment.jsx @@ -0,0 +1,52 @@ +'use strict'; + +const crypto = require('crypto'); +const { Component, Fragment } = require('inferno'); +const { cacheComponent } = require('../util/cache'); + +class Gitment extends Component { + render() { + const { + id, + repo, + owner, + clientId, + clientSecret + } = this.props; + + if (!id || !repo || !owner || !clientId || !clientSecret) { + return
+ You forgot to set the owner, repo, client_id, + or client_secret for Gitment. + Please set it in _config.yml. +
; + } + const js = `var gitment = new Gitment({ + id: '${id}', + repo: '${repo}', + owner: '${owner}', + oauth: { + client_id: '${clientId}', + client_secret: '${clientSecret}', + }, + }) + gitment.render('comment-container')`; + return +
+ + + +
; + } +} + +module.exports = cacheComponent(Gitment, 'comment.gitment', props => { + const id = crypto.createHash('md5').update(props.page.path).digest('hex'); + return { + id, + repo: props.repo, + owner: props.owner, + clientId: props.client_id, + clientSecret: props.client_secret + }; +}); diff --git a/layout/comment/gitment.locals.js b/layout/comment/gitment.locals.js deleted file mode 100644 index 145230a..0000000 --- a/layout/comment/gitment.locals.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = (ctx, locals) => { - const { path } = ctx.page; - return Object.assign(locals, { path }); -} \ No newline at end of file diff --git a/layout/comment/isso.ejs b/layout/comment/isso.ejs deleted file mode 100644 index f0942e3..0000000 --- a/layout/comment/isso.ejs +++ /dev/null @@ -1,10 +0,0 @@ -<% if (!has_config('comment.url')) { %> -
- You forgot to set the url for Isso. Please set it in _config.yml. -
-<% } else { %> -
- -<% } %> - diff --git a/layout/comment/isso.jsx b/layout/comment/isso.jsx new file mode 100644 index 0000000..116b096 --- /dev/null +++ b/layout/comment/isso.jsx @@ -0,0 +1,26 @@ +'use strict'; + +const { Component, Fragment } = require('inferno'); +const { cacheComponent } = require('../util/cache'); + +class Isso extends Component { + render() { + const { url } = this.props; + if (!url) { + return
+ You forgot to set the url for Isso. + Please set it in _config.yml. +
; + } + return +
+ +
; + } +} + +module.exports = cacheComponent(Isso, 'comment.isso', props => { + return { + url: props.url + }; +}); diff --git a/layout/comment/isso.locals.js b/layout/comment/isso.locals.js deleted file mode 100644 index bec3126..0000000 --- a/layout/comment/isso.locals.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = (ctx, locals) => { - return locals; -} \ No newline at end of file diff --git a/layout/comment/livere.ejs b/layout/comment/livere.ejs deleted file mode 100644 index 000ec66..0000000 --- a/layout/comment/livere.ejs +++ /dev/null @@ -1,22 +0,0 @@ -<% if (!has_config('comment.uid')) { %> -
- You forgot to set the uid for LiveRe. Please set it in _config.yml. -
-<% } else { %> -
- - -
-<% } %> \ No newline at end of file diff --git a/layout/comment/livere.jsx b/layout/comment/livere.jsx new file mode 100644 index 0000000..7bfd8ca --- /dev/null +++ b/layout/comment/livere.jsx @@ -0,0 +1,37 @@ +'use strict'; + +const { Component } = require('inferno'); +const { cacheComponent } = require('../util/cache'); + +class LiveRe extends Component { + render() { + const { uid } = this.props; + if (!uid) { + return
+ You forgot to set the uid for LiveRe. + Please set it in _config.yml. +
; + } + const js = `(function(d, s) { + var j, e = d.getElementsByTagName(s)[0]; + + if (typeof LivereTower === 'function') { return; } + + j = d.createElement(s); + j.src = 'https://cdn-city.livere.com/js/embed.dist.js'; + j.async = true; + + e.parentNode.insertBefore(j, e); + })(document, 'script');`; + return
+ + +
; + } +} + +module.exports = cacheComponent(LiveRe, 'comment.livere', props => { + return { + uid: props.uid + }; +}); diff --git a/layout/comment/livere.locals.js b/layout/comment/livere.locals.js deleted file mode 100644 index bec3126..0000000 --- a/layout/comment/livere.locals.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = (ctx, locals) => { - return locals; -} \ No newline at end of file diff --git a/layout/comment/valine.ejs b/layout/comment/valine.ejs deleted file mode 100644 index 8aee88d..0000000 --- a/layout/comment/valine.ejs +++ /dev/null @@ -1,19 +0,0 @@ -<% if (!has_config('comment.app_id') || !has_config('comment.app_key')) { %> -
- You forgot to set the app_id or app_key for Valine. Please set it in _config.yml. -
-<% } else { %> -
- - - -<% } %> \ No newline at end of file diff --git a/layout/comment/valine.jsx b/layout/comment/valine.jsx new file mode 100644 index 0000000..736a096 --- /dev/null +++ b/layout/comment/valine.jsx @@ -0,0 +1,40 @@ +'use strict'; + +const { Component, Fragment } = require('inferno'); +const { cacheComponent } = require('../util/cache'); + +class Valine extends Component { + render() { + const { appId, appKey, notify, verify, placeholder } = this.props; + if (!appId || !appKey) { + return
+ You forgot to set the app_id or app_key for Valine. + Please set it in _config.yml. +
; + } + const js = `new Valine({ + el: '#valine-thread' , + notify: ${notify}, + verify: ${verify}, + app_id: '${appId}', + app_key: '${appKey}', + placeholder: '${placeholder}' + });`; + return +
+ + + +
; + } +} + +module.exports = cacheComponent(Valine, 'comment.valine', props => { + return { + appId: props.app_id, + appKey: props.app_key, + notify: props.notify, + verify: props.verify, + placeholder: props.placeholder + }; +}); diff --git a/layout/comment/valine.locals.js b/layout/comment/valine.locals.js deleted file mode 100644 index bec3126..0000000 --- a/layout/comment/valine.locals.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = (ctx, locals) => { - return locals; -} \ No newline at end of file diff --git a/layout/donate/alipay.ejs b/layout/donate/alipay.ejs deleted file mode 100644 index 5ced298..0000000 --- a/layout/donate/alipay.ejs +++ /dev/null @@ -1,14 +0,0 @@ -<% const qrcode = get_config_from_obj(service, 'qrcode'); - if (qrcode) { %> - -<% } else { %> -
- You forgot to set the qrcode for Alipay. Please set it in _config.yml. -
-<% } %> \ No newline at end of file diff --git a/layout/donate/alipay.jsx b/layout/donate/alipay.jsx new file mode 100644 index 0000000..04092b7 --- /dev/null +++ b/layout/donate/alipay.jsx @@ -0,0 +1,32 @@ +'use strict'; + +const { Component } = require('inferno'); +const { cacheComponent } = require('../util/cache'); + +class Alipay extends Component { + render() { + const { type, qrcode, __, url_for } = this.props; + if (!qrcode) { + return
+ You forgot to set the qrcode for Alipay. + Please set it in _config.yml. +
; + } + return ; + } +} + +module.exports = cacheComponent(Alipay, 'donate.alipay', props => { + return { + type: props.type, + qrcode: props.qrcode, + __: props.__, + url_for: props.url_for + }; +}); diff --git a/layout/donate/alipay.locals.js b/layout/donate/alipay.locals.js deleted file mode 100644 index bec3126..0000000 --- a/layout/donate/alipay.locals.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = (ctx, locals) => { - return locals; -} \ No newline at end of file diff --git a/layout/donate/patreon.ejs b/layout/donate/patreon.ejs deleted file mode 100644 index 9f78560..0000000 --- a/layout/donate/patreon.ejs +++ /dev/null @@ -1,13 +0,0 @@ -<% const url = get_config_from_obj(service, 'url'); - if (url) { %> - -<% } else { %> -
- You forgot to set the url Patreon. Please set it in _config.yml. -
-<% } %> \ No newline at end of file diff --git a/layout/donate/patreon.jsx b/layout/donate/patreon.jsx new file mode 100644 index 0000000..ee8d833 --- /dev/null +++ b/layout/donate/patreon.jsx @@ -0,0 +1,31 @@ +'use strict'; + +const { Component } = require('inferno'); +const { cacheComponent } = require('../util/cache'); + +class Patreon extends Component { + render() { + const { type, url, __, url_for } = this.props; + if (!url) { + return
+ You forgot to set the url Patreon. + Please set it in _config.yml. +
; + } + return ; + } +} + +module.exports = cacheComponent(Patreon, 'donate.petreon', props => { + return { + type: props.type, + url: props.url, + __: props.__, + url_for: props.url_for + }; +}); diff --git a/layout/donate/patreon.locals.js b/layout/donate/patreon.locals.js deleted file mode 100644 index bec3126..0000000 --- a/layout/donate/patreon.locals.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = (ctx, locals) => { - return locals; -} \ No newline at end of file diff --git a/layout/donate/paypal.ejs b/layout/donate/paypal.ejs deleted file mode 100644 index 4c60f4e..0000000 --- a/layout/donate/paypal.ejs +++ /dev/null @@ -1,20 +0,0 @@ - -<% const business = get_config_from_obj(service, 'business'); - const currency_code = get_config_from_obj(service, 'currency_code'); - if (business && currency_code) { %> - -
- - - -
-<% } else { %> -
- You forgot to set the business and currency_code for Paypal. Please set it in _config.yml. -
-<% } %> \ No newline at end of file diff --git a/layout/donate/paypal.jsx b/layout/donate/paypal.jsx new file mode 100644 index 0000000..2958824 --- /dev/null +++ b/layout/donate/paypal.jsx @@ -0,0 +1,39 @@ +'use strict'; + +const { Component, Fragment } = require('inferno'); +const { cacheComponent } = require('../util/cache'); + +class Paypal extends Component { + render() { + const { type, business, currencyCode, __ } = this.props; + if (!business || !currencyCode) { + return
+ You forgot to set the business or currency_code for Paypal. + Please set it in _config.yml. +
; + } + return + +
+ + + +
+
; + } +} + +module.exports = cacheComponent(Paypal, 'donate.paypal', props => { + return { + type: props.type, + business: props.business, + currencyCode: props.currency_code, + __: props.__, + url_for: props.url_for + }; +}); diff --git a/layout/donate/paypal.locals.js b/layout/donate/paypal.locals.js deleted file mode 100644 index bec3126..0000000 --- a/layout/donate/paypal.locals.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = (ctx, locals) => { - return locals; -} \ No newline at end of file diff --git a/layout/donate/wechat.ejs b/layout/donate/wechat.ejs deleted file mode 100644 index a1a6faa..0000000 --- a/layout/donate/wechat.ejs +++ /dev/null @@ -1,14 +0,0 @@ -<% const qrcode = get_config_from_obj(service, 'qrcode'); - if (qrcode) { %> - -<% } else { %> -
- You forgot to set the qrcode for Wechat. Please set it in _config.yml. -
-<% } %> \ No newline at end of file diff --git a/layout/donate/wechat.jsx b/layout/donate/wechat.jsx new file mode 100644 index 0000000..290030e --- /dev/null +++ b/layout/donate/wechat.jsx @@ -0,0 +1,32 @@ +'use strict'; + +const { Component } = require('inferno'); +const { cacheComponent } = require('../util/cache'); + +class Wechat extends Component { + render() { + const { type, qrcode, __, url_for } = this.props; + if (!qrcode) { + return
+ You forgot to set the qrcode for Wechat. + Please set it in _config.yml. +
; + } + return ; + } +} + +module.exports = cacheComponent(Wechat, 'donate.wechat', props => { + return { + type: props.type, + qrcode: props.qrcode, + __: props.__, + url_for: props.url_for + }; +}); diff --git a/layout/donate/wechat.locals.js b/layout/donate/wechat.locals.js deleted file mode 100644 index bec3126..0000000 --- a/layout/donate/wechat.locals.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = (ctx, locals) => { - return locals; -} \ No newline at end of file diff --git a/layout/util/cache.jsx b/layout/util/cache.jsx new file mode 100644 index 0000000..d10a645 --- /dev/null +++ b/layout/util/cache.jsx @@ -0,0 +1,40 @@ +const crypto = require('crypto'); +const { Component } = require('inferno'); +const { createElement } = require('inferno-create-element'); + +const cache = {}; + +function computeHash(props) { + return crypto.createHash('md5').update(JSON.stringify(props)).digest("hex"); +} + +module.exports = { + /** + * Create cached component from a given component class. + * The cache ID is caculated from the input props. + * + * @param {Component} type JSX component class + * @param {string} prefix Cache ID prefix + * @param {Function} transform Transform the input props to target props and + * its result is used to compute cache ID + * @returns Cached JSX element if cache ID is found. + * Otherwise, create a new element and cache it if the transform function is provided. + */ + cacheComponent(type, prefix, transform) { + if (typeof transform !== 'function') { + return props => createElement(type, props); + } else { + return props => { + const targetProps = transform(props); + const cacheId = prefix + '-' + computeHash(targetProps); + if (!cacheId) { + return createElement(type, targetProps); + } + if (!cache[cacheId]) { + cache[cacheId] = createElement(type, targetProps); + } + return cache[cacheId]; + }; + } + } +};