Cabloy-CMS uses ejs template engine for page rendering, a context object is created before rendering, and collects related data and methods for use in template files

Context Object Structure

{
  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]
}
Name Type Description
ctx property perform backend APIs via ctx
site property site configuration
require method require module
url method create an absolute link
css method declare css files for final merging and minimization
js method declare js files for final merging and minimization
env method inject environment variables for frontend usage
text method text i18n
util property util functions
util.safeHtml method create safe HTML
util.escapeHtml method create safe escaped HTML content
util.escapeURL method create safe URL
article property current article object
_path property indicates the relative path of the current template file (relative to the directory intermediate)

Perform Backend APIs

Backend APIs can be performed via object ctx

For example, in order to render the menu, you can retrieve the category tree as follows:

const res = await ctx.performAction({
  method:'post',
  url: '/a/cms/category/tree',
  body: { language:site.language.current, hidden:0 },
});
const tree=res.list;

Require Module

In the .ejs file, you can also require the module as in NodeJS

// require module in node_modules
const moment=require('moment');
// require module in the project
const test=require('./test.js');

Absolute URL Link

It is recommended that URL links of all resources in the page are rendered as absolute link

// relative to the website root path
<%=url('assets/images/background.png')%>
// relative to the current file
<%=url('./fonts/github/700i.woff')%>

Merge and Minimize CSS & JS

During the rendering process, the CSS and JS files are declared at first and then merged and minimized at the end. A placeholder is provided in the rendering template, which will be replaced with the actual generated URL link

Declare 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');

If the referenced CSS, JS file suffix is .ejs, it will also be rendered as an ejs template

Placeholder

cms-themeblog/backend/cms/theme/layout/header/head.ejs

<link rel="stylesheet" href="_ _CSS_ _">

cms-themeblog/backend/cms/theme/layout/footer.ejs

<script src="_ _JS_ _"></script>

Effects

<link rel="stylesheet" href="https://zhennann.me/assets/css/8d38154d198309325c0759a22213dbd6ff0b7edecd2f4868dc72311335ccbe25.css">
<script src="https://zhennann.me/assets/js/b17e06ccb536dee939d4b1deaa595436363a52769c210d74d6a77f011e0f6461.js"></script>

Inject Environment Variables

In order to facilitate the flexible and rich functional logic of the frontend, some environmental variables need to be injected into the frontend

The backend declares environment variables via env, which are finally merged into the frontend

Similarly, a placeholder also need to be provided in the rendering template, which will be replaced with the actual generated environment variables

Declare

env('index',{
  [_path]:data.index,
});

Placeholder

cms-themeblog/backend/cms/theme/layout/header/head.ejs

_ _ENV_ _

Effects

<script type="text/javascript">
var env={
  "base": ...,
  "language": ...,
  "format": ...,
  "comment": ...,
  "site": ...,
  "index": {
    "main/index/index": 20
  }
};
</script>

I18N

If you want to support multi-language for themes and plugins, you need to i18n the text resources used in them

Because the theme and plugin are essentially EggBornJS modules, you can use the i18n mechanism provided by EggBornJS directly

For example, the plugin cms-pluginbase provides the feature of infinite scrolling, Which will display the prompt of Load error, try again when failed, you can do the following

Define Language Resources

cms-pluginbase/backend/src/config/locale/zh-cn.js

module.exports = {
  'Load error, try again': '加载失败,请重试',
};

Use Language Resources

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 Indication: _path

A common ejs template file may be referenced by different master ejs template files. With _path, you can know which master ejs template file reference this common ejs template file in order to perform different logical processing

路径标示:_path

一个通用的ejs模版文件可能被多个主ejs模版文件包含引用。通过_path,可以在通用ejs模版文件中知晓当前被哪个主ejs模版文件引用,以便做不同的逻辑处理

Safe Handling: safeHtml/escapeHtml/escapeURL

When outputting any resources in the ejs template, you should keep in mind the safe handling

1. safeHtml

Note that you need to use safeHtml to handle the rich text (which contains the text of the HTML code) as a variable directly in the template. Use safeHtml to output HTML tags, while executing XSS filtering, then it can filter out illegal scripts

The processing process is more complicated, the performance loss is larger, please use only if you need to output html content

2. escapeHtml

The HTML string is processed safely and replaced with the following characters:

Original Character Replaced with
& &amp;
< &gt;
> &gt;
" &quot;
&#039;

3. escapeURL

The URL string is processed safely and replaced with the following characters:

Original Character Replaced with
< %3C
> %3E
" %22
%27