Markdown区块的架构设计已经变更,文档正在重构当中

区块是在CMS插件模块中提供的。因此,我们延续前面已经创建的插件模块test-cmspluginhello,制作一个区块iframe

如何制作插件,请参见:开发篇 - 制作插件

1. 引用区块及Schema

在模块的meta中引用区块Schema

src/module/test-cmspluginhello/backend/src/meta.js

  1. 1module.exports = app => {
  2. 2 const schemas = require('./config/validation/schemas.js')(app);
  3. 3 const blocks = require('./config/blocks.js')(app);
  4. 4 const meta = {
  5. 5 ...
  6. 6 validation: {
  7. 7 validators: {
  8. 8 blockIFrame: {
  9. 9 schemas: 'blockIFrame',
  10. 10 },
  11. 11 },
  12. 12 keywords: {},
  13. 13 schemas: {
  14. 14 blockIFrame: schemas.blockIFrame,
  15. 15 },
  16. 16 },
  17. 17 cms: {
  18. 18 plugin: {
  19. 19 blocks,
  20. 20 },
  21. 21 },
  22. 22 };
  23. 23 return meta;
  24. 24};
名称 说明
cms.plugin.blocks 本模块所提供的区块清单
validation.validators.blockIFrame 区块所对应的validator
validation.schemas.blockIFrame 区块所对应的schema

2. 定义区块

src/module/test-cmspluginhello/backend/src/config/blocks.js

  1. 1module.exports = app => {
  2. 2 const blockIFrame = require('./block/iframe.js')(app);
  3. 3 return {
  4. 4 blockIFrame,
  5. 5 };
  6. 6};

src/module/test-cmspluginhello/backend/src/config/block/iframe.js

  1. 1module.exports = app => {
  2. 2 const block = {
  3. 3 validator: 'blockIFrame',
  4. 4 bean: 'iframe',
  5. 5 };
  6. 6 return block;
  7. 7};
名称 说明
validator 区块的验证器,用于区块编辑页面的渲染与参数验证
bean 区块Bean组件,用于内容渲染

3. 定义Bean组件

src/module/test-cmspluginhello/backend/src/bean/cms.block.iframe.js

  1. 1module.exports = ctx => {
  2. 2 class CMSBlock {
  3. 3 render({ md, options, block, token, index, content }) {
  4. 4 const url = md.utils.escapeHtml(content.url);
  5. 5 const width = md.utils.escapeHtml(content.width || '100%');
  6. 6 const height = md.utils.escapeHtml(content.height || '300px');
  7. 7 return `<div class="block block-iframe" style="width:${width};height:${height};"><iframe width="100%" height="100%" scrolling="auto" frameborder="0" src="${url}"></iframe></div>\n`;
  8. 8 }
  9. 9 }
  10. 10
  11. 11 return CMSBlock;
  12. 12};
名称 说明
md MarkdownIt实例对象,参见: MarkdownIt
md.utils.escapeHtml 特别的,经常需要通过此方法对用户输入的内容进行安全转译,从而避免注入漏洞的发生
options 扩展参数
options.utils.text 通过此方法返回国际化字符串
options.blocks 所有区块清单
block 区块的对象定义
token MarkdownIt渲染参数
index MarkdownIt渲染参数
content 用户输入的内容

4. 注册Bean组件

src/module/test-cmspluginhello/backend/src/beans.js

  1. 1const cmsBlockIFrame = require('./bean/cms.block.iframe.js');
  2. 2
  3. 3module.exports = app => {
  4. 4 const beans = {
  5. 5 // block
  6. 6 'cms.block.iframe': {
  7. 7 mode: 'ctx',
  8. 8 bean: cmsBlockIFrame,
  9. 9 },
  10. 10 };
  11. 11 return beans;
  12. 12};
注册名称 场景 所属模块 global beanFullName
iframe cms.block test-cmspluginhello false test-cmspluginhello.cms.block.iframe

5. 定义Schema

JSON Schema用来验证用户输入的数据是否符合预期,如果不符合预期,就会有醒目的提示

关于JSON Schema,请参见:表单验证

src/module/test-cmspluginhello/backend/src/config/validation/schemas.js

  1. 1module.exports = app => {
  2. 2 const schemas = { };
  3. 3 // block iframe
  4. 4 schemas.blockIFrame = {
  5. 5 type: 'object',
  6. 6 properties: {
  7. 7 url: {
  8. 8 type: 'string',
  9. 9 ebType: 'text',
  10. 10 ebTitle: 'URL',
  11. 11 format: 'uri',
  12. 12 notEmpty: true,
  13. 13 },
  14. 14 width: {
  15. 15 type: 'string',
  16. 16 ebType: 'text',
  17. 17 ebTitle: 'Width',
  18. 18 },
  19. 19 height: {
  20. 20 type: 'string',
  21. 21 ebType: 'text',
  22. 22 ebTitle: 'Height',
  23. 23 },
  24. 24 },
  25. 25 };
  26. 26
  27. 27 return schemas;
  28. 28};

6. 后端资源定义

在一个复杂的系统中,会涉及到资源授权的问题,我们需要对区块进行权限控制。模块a-cms提供了一个资源类型a-cms:block,只需定义静态资源,并指定角色,即可同时完成资源的注册与初始授权

6.1 定义静态资源

定义一个静态资源数组

src/module/test-cmspluginhello/backend/src/config/static/resources.js

  1. 1module.exports = app => {
  2. 2 const moduleInfo = app.meta.mockUtil.parseInfoFromPackage(__dirname);
  3. 3 const resources = [
  4. 4 // cms block
  5. 5 {
  6. 6 atomName: 'Embed Page',
  7. 7 atomStaticKey: 'blockIFrame',
  8. 8 atomRevision: 0,
  9. 9 atomCategoryId: 'a-cms:block.General',
  10. 10 resourceType: 'a-cms:block',
  11. 11 resourceConfig: JSON.stringify({
  12. 12 default: {
  13. 13 url: '',
  14. 14 width: '',
  15. 15 height: '',
  16. 16 },
  17. 17 validator: {
  18. 18 module: moduleInfo.relativeName,
  19. 19 validator: 'blockIFrame',
  20. 20 },
  21. 21 }),
  22. 22 resourceRoles: 'root',
  23. 23 },
  24. 24 ];
  25. 25 return resources;
  26. 26};
名称 说明
atomStaticKey 系统自动添加模块名称前缀,生成test-cmspluginhello:blockIFrame
atomCategoryId 资源归属目录。资源类型全称a-cms:block:button作为一级目录
resourceType 资源类型全称
resourceConfig 资源配置信息
resourceConfig.default 区块的缺省值
resourceConfig.validator 区块的验证器
resourceRoles 资源授权对象,这里是角色root

角色root是整个角色树的根,也就意味着所有用户(包括匿名用户)均可访问此资源

更多配置说明,参见静态资源

6.2 注册静态资源

前面定义好一组静态资源,接下来就需要在模块的meta文件中进行注册

src/module/test-cmspluginhello/backend/src/meta.js

  1. 1const staticResources = require('./config/static/resources.js')(app);
  2. 2
  3. 3base: {
  4. 4 statics: {
  5. 5 'a-base.resource': {
  6. 6 items: staticResources,
  7. 7 },
  8. 8 },
  9. 9},
名称 说明
a-base.resource 原子类型的全称。在这里,原子类型resource是由模块a-base提供的
items 静态资源数组