百家饭团队开发的百家饭OpenAPI平台是用vuepress2.0搭建的,搭建的时候不知道2.0还处在beta状态,所以导致后来踩了一些坑,使用过程中vuepress2.0也从2.0.0-beta.18升到了2.0.0-beta.48,有很多的变化,所以想写一个教程介绍一下vuepress2.0的情况以及使用经验。

大致计划写这些内容吧:

  1. vuepress介绍、选型原因及使用感受(先介绍一下自己用的情况吧)
  2. vuepress2.0使用(搭建一个vuepress支撑的网站)-第一部分
  3. vuepress2.0使用(搭建一个vuepress支撑的网站)-修改默认模板配置
  4. vuepress2.0使用(搭建一个vuepress支撑的网站)-详细配置默认模板
  5. vuepress2.0使用(搭建一个vuepress支撑的网站)-md文件的玩法
  6. vuepress2.0使用(扩展默认主题)- 准备及扩展页面组件
  7. vuepress2.0使用(扩展默认主题)- 提供更多页面模板并引入ElementUI
  8. vuepress2.0使用(扩展默认主题)- 扩展MD页面功能(Section扩展及自定义语法)
  9. vuepress2.0使用(扩展默认主题)- 引入百度搜索支持及其他库的引用
  10. 编写vuepress主题(自定义自己的框架,开发复杂程序)
  11. vuepress2.0使用——编译及站点部署
  12. vuepress2.0当前的状态(版本变化,方便大家升级,占位中,未书写)
  13. 更多读者发起话题点击这里进专题查看,就不更新标题了

这里先给搜索进来的同学提个醒:凡是网上搜索到需要修改clientAppEnhance.js 文件的教程都已经过时,最新版本已不再使用。另外说个题外话,我查了下,我为数不多的搜索关键词里面,vuepress的占了大部分,这里感谢大家的关注,这个教程肯定有不合理的地方,如果有任何需要帮助的,大家都可以留言,我尽力解答。

本周,百家饭OpenAPI平台已经初步完成了以API工作台为核心功能的0.6.0版本的初步开发测试,下周基本可以发布了,希望到时候给大家能够提供更好的API开发服务。

本周继续来讲我们的Vuepress教程。

vuepress 2.0中的md扩展

md扩展对于希望文章能够更精彩的博主来讲,是非常重要的功能,比如百家饭就用了Element-Plus的时间线来显示编辑器的更新日志。

那如何将这样的功能放到MD文件中,使得编辑人员可以自由使用呢。通过学习,我们觉得大概有这么两种方案:

扩展MD中的容器

vuepress中使用到了容器(container)的概念,来在md文件中提供复杂功能。

什么是容器?

vuepress的容器是以:::括起来的内容,默认主题提供三种容器(tip/warning/danger),调用的方式就是在开头的:::后面跟名称

比如

::: tip
# 微服务版下载隐私计算企业服务请拉取和使用微服务版。**微服务版本暂未提供给公共使用,请联系百家饭团队获得相关帮助**> 百家饭OpenAPI微服务版为用户提供基于开发脚本的内部Web服务能力,将脚本的计算能力开放为Web Service接口,供其他业务系统调用。微服务版采用Docker安装模式,请安装Docker服务之后,采用以下方式安装微服务版::::

显示为

因此,如果要扩展不同的容器,以我们用的timeline为例,那我们就可以增加一种名为timeline的容器

为主题增加自定义容器

自定义容器的增加,我们需要在主题的index.js里增加如下的内容:

const { containerPlugin } = require('@vuepress/plugin-container')module.exports = ({ themePlugins = {}, ...localeOptions }) => {// ctx.siteData.docs = option.sidebarreturn {……plugins: [……containerPlugin({type: 'timeline',before: (info) =>`<ClientOnly><el-timeline>\n`,after: () => '</el-timeline></ClientOnly>\n'}),

也就是在exports返回配置对象的plugins属性中增加一个containerPlugin,注意,该方法在旧版本中形式如下:

 ['@vuepress/container', {type: 'timeline',before: (info) =>`<ClientOnly><el-timeline>\n`,after: () => '</el-timeline></ClientOnly>\n'}],

如果搜索到按上述方法进行容器扩展的,应该已经过期了。

我们可以看出,容器其实就是给md中的内容增加一个前(通过before)后(提供after)的内容,共同形成html的方式。

掌握了这个方式,我们就可以使用容器把我们想要的各种内容在md中组织起来。

添加自定义MD语法

上面的方法里,我们扩展了容器的用法,最后可以通过不同的容器实现各种自定义组件,类似:

:::: timeline::: timeline-item 2022-06-13
### v0.2.0* 更新了对于复杂属性的定义界面
* 提升了复杂接口的渲染速度
* 提升了Json编辑器的打开速度
* 支持array类型参数的详细字段定义:::::::

上面的代码里,我们定义了两级的容器(为了区分级别,md中的容器要求外层比里层至少多一个":"),但是这种结构用多了显得很麻烦,md里到处都是:。

那还有没有更高级的方式呢,有,就是自定义md语法。比如容器的语法就是通过三个以上的:来触发。那我们也可以自定义自己的语法。

比如我们定义了一个语法结构!{}}来表示中间的内容是纯html变量。

引用自定义组件

上述的方式是通过扩展md的方式完成的,同样,我们需要扩展index.js,引入以下内容

const plugin1 = require("./md_html_plugin")module.exports = ({ themePlugins = {}, ...localeOptions }) => {// ctx.siteData.docs = option.sidebarreturn {……extendsMarkdown: (md) => {md.use(plugin1)},

在配置的extendsMarkdown属性中,告诉md组件去使用一个新的plugin,而这个plugin由我们自己进行定义即可。

定义组件

那如何定义这个组件呢,vuepress的md解析使用的是markdown-it,这里定义组件的方式就是定义markdown-it扩展的方式。

markdown-it扩展的定义有些复杂,这个部分可能不能覆盖所有的逻辑,有复杂需求的需要另行搜索。

定义组件的exports

组件定义的exports部分逻辑如下:

module.exports = function vue_html_plugin(md) {md.block.ruler.before('heading', 'vue_html', container);md.renderer.rules['vue_html_open'] = (tokens, index, opts, env) => {var token = tokens[index];return `<div v-html='${token.info}'>`;};md.renderer.rules['vue_html_close'] = () => "</div>";
}

这个部分的包含多个部分(我们的html渲染例子中为三个部分,复杂的插件可能更多),第一个部分,定义了我们这个插件所处的层级,这和md的解析有关系,我们定义的插件定义在解析heading之前,名称定为了vue_html,具体的解析函数是名为container的函数。

那第二个和第三个部分则对应处理我们插件增加的新的语法结构,在我们的例子中,我们定义的插件逻辑较为简单,把插件内部的内容作为v-html传给一个div即可,因此,层级简单,只需要把!{ content }}解析为<div v-html="content"></div>即可,因此我们只需要定义两个新的规则,一个是vue_html_open,一个是vue_html_close,分别用于渲染div定义的开始部分和结束部分即可。

定义组件的解析函数。

接下来就要具体写container函数了,具体如下:

var marker_str = '!{',marker_char = marker_str.charCodeAt(0),marker_len = 2,marker_end_str = '}}',marker_end_char = marker_end_str.charCodeAt(0)function container(state, startLine, endLine, silent) {var pos, nextLine, marker_count, markup, params, token,old_parent, old_line_max,auto_closed = false,start = state.bMarks[startLine] + state.tShift[startLine],max = state.eMarks[startLine];// 如果传进来的内容的第一个字符不是我们需要的"!",直接返回if (marker_char !== state.src.charCodeAt(start)) { return false; }// 再继续匹配"!{"的其他部分,我们的例子里,开头是!{,可以不用循环,如果你定义的符号更为复杂,可以参考该循环的写法for (pos = start + 1; pos <= max; pos++) {if (marker_str[(pos - start) % marker_len] !== state.src[pos]) {break;}}marker_count = pos - start;if (marker_count < marker_len) { return false; } //如果匹配长度不够,直接返回markup = state.src.slice(start, pos - marker_len);//内容初始位置指向开始匹配符后面start = pos//循环匹配内容,直到遇到结束符为止for (; ;) {pos++if (marker_end_char !== state.src.charCodeAt(pos)) { continue; }for (pos1 = pos + 1; pos1 <= max; pos1++) {if (marker_end_str[pos1 - pos] !== state.src[pos1]) {break;}}break;}//将内容存储params = state.src.slice(start, pos);//缓存旧的状态情况old_parent = state.parentType;old_line_max = state.lineMax;state.parentType = 'vue_html';//将vue_html_open推送到解析栈中,传入内容作为info参数token = state.push('vue_html_open', 'div', 1);token.markup = markup;token.block = true;token.info = params;token.map = [startLine, startLine];//将vue_html_close推送到解析栈中token = state.push('vue_html_close', 'div', -1);token.markup = state.src.slice(start, pos);token.block = true;//将原有堆栈情况复原state.parentType = old_parent;state.lineMax = old_line_max;state.line = startLine + (auto_closed ? 1 : 0);return true;
}

注意,本例子只用于单行内容插件,多行内容插件可以参考vscode-markdown-extended/markdownItAdmonition.ts at master · qjebbs/vscode-markdown-extended · GitHub

插件的书写要求较高,需要有语法树解析的基础认知,要不理解比较困难。 总之,如果有复杂的需求,可以参考来写,这章写的也没啥底气,呵呵,有错误或者有问题的,欢迎提问,共同探讨。

vuepress2.0使用教程(8)-扩展MD功能(Section扩展及自定义语法)相关推荐

  1. Zabbix6.0使用教程 (一)—zabbix新增功能介绍1

    使用zabbix的小伙伴应该都有关注到目前zabbix的大版本已经更新到了6.0,后面乐乐将会对如何使用zabbix6.0做一个使用教程的系列,大家可以持续关注,这篇我们主要聊聊zabbix6.0新增 ...

  2. Zabbix6.0使用教程 (一)—zabbix新增功能介绍2

    上一篇我们已经介绍了部分zabbix6.0的新增功能,这期我们将继续为家详细介绍下余下的zabbix6.0新增功能,大家可以往下看. 六.监控项 6.1 自动类型选择 监控项配置表单会自动建议匹配的信 ...

  3. 全志T507开发板去掉IO扩展芯片,保留扩展引脚功能

    飞凌嵌入式推出的OKT507-C作为一款广受欢迎的开发板拥有丰富的接口资源,而实际上OKT507-C的CPU引脚资源是比较紧缺的,那么它是如何实现这么丰富的接口资源呢? 答案就是飞凌使用了一个IO扩展 ...

  4. 全志T507去掉IO扩展芯片,保留扩展引脚功能

    飞凌嵌入式推出的OKT507-C作为一款广受欢迎的开发板拥有丰富的接口资源,而实际上OKT507-C的CPU引脚资源是比较紧缺的,那么它是如何实现这么丰富的接口资源呢? 答案就是飞凌使用了一个IO扩展 ...

  5. 【Vue3.0实战逐步深入系列】扩展投票功能基于elementui进行组件封装实现一个简单的问卷调查功能

    [千字长文,熬夜更新,原创不易,多多支持,感谢大家] 前言 小伙伴们大家好.在前面一偏文章中我们把投票功能进行了简单的改造:引入了axios第三方库并进行了二次封装用于模拟请求服务器数据.同时添加了一 ...

  6. Swift3.0语言教程使用路径字符串

    Swift3.0语言教程使用路径字符串 Swift3.0语言教程使用路径字符串,路径其实是字符串的一种,我们称为路径字符串.本小节将讲解如何使用路径字符串. 1.组合路径 开发者可以将数组快速的组合成 ...

  7. drupal 6.0 入门教程

    为什么80%的码农都做不了架构师?>>>    由于工作项目的原因,需要采用drupal来部署,所以最近学习了drupal cms,天天到 drupal.org,drupalchin ...

  8. c盘扩展卷功能只能向右扩展_信用风险管理:功能扩展和选择

    c盘扩展卷功能只能向右扩展 Following feature engineering, this part moves to the next step in the data preparatio ...

  9. Unity Cinemachine智能相机教程(五):VirtualCamera的Extension扩展

    摘要:[长文预警,先收藏后品尝]如何让相机更智能呢?Extension扩展可以给虚拟相机带来无限的可能. 洪流学堂,让你快人几步.你好,我是跟着大智(VX: zhz11235)学Unity的萌新,我叫 ...

最新文章

  1. 我在兰亭这三年完结篇之离开
  2. vbs结束进程代码_物联网学习教程—Linux系统编程之进程控制
  3. 工程设计+算法规模化真的是AI突破吗?DeepMind唇读系统ICLR遭拒
  4. 本机镜像仓库base64解密
  5. 跨境出海,Tik Tok商业化营销推广分享
  6. mysql 数据库还原后没有_MySQL数据库的备份还原至最新状态
  7. php双分支语句【三个数排序】
  8. cf1561D Up the Strip(D1D2)
  9. df添加一行 python_Python为输出的数据绘制表格
  10. 如何在一个日期值上加上分钟值得到新的日期
  11. android 文件下载
  12. GS运维常用工具及文档
  13. AE从初级到高级全套视频教程
  14. R语言—90分钟从入门到精通
  15. 花花的森林(倍增,LCA
  16. HCIP(四)---BMA,NBMA网络类型
  17. word行首空格下划线_行首空格和下划线问题的解决
  18. js replace 与replaceall实例用法
  19. html中相对位置与绝对位置介绍
  20. PHPExcel的自定义导出及合并单元格

热门文章

  1. 干货丨excel单元格如何添加下拉选项?
  2. php中字符串去除空格,php怎么去除字符串中的空格
  3. 将MySQL数据导出为sql文件
  4. 【DG】[三思笔记]一步一步学DataGuard
  5. 谷歌验证码,国内各种验证码识别
  6. 下载keil和proteus遇到的问题——学习笔记
  7. 安装netstat命令和使用明细
  8. 典型相关分析原理(例题+代码)
  9. 数据库sql语句删除指定日期或之前之后的数据
  10. E-Prime心理学实验设计软件丨产品简介