Cabloy-CMS采用ejs
模版引擎进行页面渲染,在渲染之前创建一个上下文对象,归集相关的数据和方法,以便在模版文件中使用
上下文对象结构
{
ctx: [Object],
site: [Object],
require: [Function],
url: [Function],
css: [Function],
js: [Function],
env: [Function],
text: [Function],
util: {
time: {
now: [Function],
today: [Function],
formatDateTime: [Function],
formatDate: [Function],
formatTime: [Function]
},
formatDateTime: [Function],
safeHtml: [Function],
escapeHtml: [Function],
escapeURL: [Function]
},
article: [Object],
_path: [String]
}
名称 | 类型 | 说明 |
---|---|---|
ctx | 属性 | 通过ctx对象可以调用后端API接口,及挂载在ctx对象上的各类功能 |
site | 属性 | 站点配置信息 |
require | 方法 | 引用模块 |
url | 方法 | 构造绝对链接 |
css | 方法 | 声明css文件,以便最后合并和最小化 |
js | 方法 | 声明js文件,以便最后合并和最小化 |
env | 方法 | 注入环境变量,以便输出到前端使用 |
text | 方法 | 文本国际化 |
util | 属性 | 工具函数 |
util.safeHtml | 方法 | 对Html字符串进行安全过滤处理 |
util.escapeHtml | 方法 | 对Html字符串进行安全转义处理 |
util.escapeURL | 方法 | 对URL字符串进行安全转义处理 |
article | 属性 | 当前渲染的文章信息 |
_path | 属性 | 标示当前模版文件的相对路径(相对于目录intermediate) |
访问后端资源
通过ctx
对象可以调用后端API接口
,及挂载在ctx对象上的各类功能
比如,为了渲染菜单,需要获取目录树,可以如下操作
src/module-system/cms-pluginarticle
// categories
const categories = await ctx.performAction({
method: 'post',
url: '/a/base/category/tree',
body: {
atomClass: site.atomClass,
language: site.language.current,
categoryId: 0,
categoryHidden: 0,
},
});
引用模块
在.ejs
文件中,也可以像在NodeJS中一样引用模块
// 引用node_modules中的模块
const moment=require('moment');
// 引用项目内的文件模块
const test=require('./test.js');
绝对地址
建议页面中所有资源的URL链接都渲染成绝对地址
// 相对于网站根目录
<%=url('assets/images/background.png')%>
// 相对于当前文件
<%=url('./fonts/github/700i.woff')%>
合并和最小化CSS、JS
在渲染过程中,先声明CSS和JS文件,然后在最后进行合并和最小化。在渲染模版中提供占位符
,替换为实际生成的URL链接
- 声明CSS、JS
// css
css('../assets/css/markdown/github.css.ejs');
css('../assets/css/article.css');
css('../assets/css/sidebar.css');
// js
js('../assets/js/lib/json2.min.js');
js('../assets/js/lib/bootbox.min.js');
js('../assets/js/util.js.ejs');
js('../assets/js/article.js.ejs');
js('../assets/js/sidebar.js.ejs');
如果引用的CSS、JS文件后缀名为
.ejs
,也会作为ejs模版进行渲染
- 占位符
// CSS文件链接占位符
<link rel="stylesheet" href="_ _CSS_ _">
// JS文件链接占位符
<script src="_ _JS_ _"></script>
- 效果
<link rel="stylesheet" href="https://zhennann.me/assets/css/8d38154d198309325c0759a22213dbd6ff0b7edecd2f4868dc72311335ccbe25.css">
<script src="https://zhennann.me/assets/js/b17e06ccb536dee939d4b1deaa595436363a52769c210d74d6a77f011e0f6461.js"></script>
注入环境参数
为了便于前端实现灵活且丰富的功能逻辑,需要把一些环境参数注入到前端。后端通过env
声明环境参数,这些参数最后会进行合并注入到前端
同样,也需要在前端提供占位符
,替换为实际生成的环境参数
- 声明env
env('index',{
[_path]:data.index,
});
- 占位符
// ENV占位符
_ _ENV_ _
- 效果
<script type="text/javascript">
var env={
"base": ...,
"language": ...,
"format": ...,
"comment": ...,
"site": ...,
"index": {
"main/index/index": 20
}
};
</script>
国际化
如果需要让主题
和插件
可以应用于不同的语言,需要对其中用到的文本资源进行国际化处理
因为主题
和插件
本质上都是EggBornJS模块
,所以可以直接使用EggBornJS模块
提供的国际化机制
比如,插件cms-pluginbase
提供了无限滚动
的功能,如果加载失败需要在页面中提示Load error, try again
,可以如下操作
- 定义语言资源
cms-pluginbase/backend/src/config/locale/zh-cn.js
module.exports = {
'Load error, try again': '加载失败,请重试',
};
- 使用语言资源
cms-pluginbase/backend/cms/plugin/assets/js/util.js.ejs
const $buttonTry = $('<button type="button" class="btn btn-warning btn-xs"><%=text("Load error, try again")%></button>');
路径标示:_path
一个通用的ejs模版文件可能被多个主ejs模版文件
包含引用。通过_path
,可以在通用ejs模版文件中知晓当前被哪个主ejs模版文件
引用,以便做不同的逻辑处理
安全处理:escapeHtml/escapeURL
在ejs模版中输出任何资源时,都要牢记安全处理
1. safeHtml
注意,将富文本(包含 HTML 代码的文本)当成变量直接在模版里面输出时,需要用到 safeHtml 来处理。 使用 safeHtml 可以输出 HTML 的 tag,同时执行 XSS 的过滤动作,过滤掉非法的脚本
由于是一个非常复杂的安全处理过程,对服务器处理性能一定影响,如果不是输出 HTML,请勿使用
2. escapeHtml
对Html字符串进行安全转义处理,进行如下字符替换:
原字符 | 替换字符 |
---|---|
& | & |
< | > |
> | > |
" | " |
’ | ' |
3. escapeURL
对URL字符串进行安全转义处理,进行如下字符替换:
原字符 | 替换字符 |
---|---|
< | %3C |
> | %3E |
" | %22 |
’ | %27 |
评论: