Element 的文档站是讲Markdown解析成vue组件在页面中渲染出来,转换过程如下图所示:

红框部分势必要对 Markdown 进行特殊的订制,订制过的 Markdown 像下面这样。


:::demo 要使用 Radio 组件,只需要设置`v-model`绑定变量,选中意味着变量的值为相应 Radio `label`属性的值,`label`可以是`String`、`Number`或`Boolean`。
```html
<template>
  <el-radio v-model="radio" label="1">备选项</el-radio>
  <el-radio v-model="radio" label="2">备选项</el-radio>
</template>
<script>
  export default {
    data () {
      return {
        radio: '1'
      };
    }
  }
</script>
\`\`\`
:::

需要解析成对应的页面如下图:

通过 :::demo 作为页面中组件实例的标识,这个转换过程在md-loader中处理。具体element文档站如何实现解析功能的,看看源码build文件下的webpack.demo.js配置md的解析器。

webpack配置

把Markdown解析成vue组件就在webpack配置md的解析loader:

    {
        test: /\.md$/,
        use: [
          {
            loader: 'vue-loader',
            options: {
              compilerOptions: {
                preserveWhitespace: false
              }
            }
          },
          {
            loader: path.resolve(__dirname, './md-loader/index.js')
          }
        ]
      },

从配置文件中可以看出,Markdown 先经由 md-loader 处理,然后再交由 vue-loader 处理。经过这两个 loader 的处理后输出JavaScript在页面中渲染出来。

md-loader

源码中md-loader目录如下:

├─md-loader
| ├─config.js
| ├─containers.js
| ├─fence.js
| ├─index.js
| ├─util.js

index.js:

const {
  stripScript,
  stripTemplate,
  genInlineComponentText
} = require('./util');
const md = require('./config');
module.exports = function(source) {
  const content = md.render(source);
  const startTag = '<!--element-demo:';
  const startTagLen = startTag.length;
  const endTag = ':element-demo-->';
  const endTagLen = endTag.length;
...

md.render(source)这句代码是在markdown-it插件(将markdown转换为html插件)用法很相似,根据const md = require('./config');可以猜测markdown转换为html的代码在config中。

config.js:

const Config = require('markdown-it-chain');
const anchorPlugin = require('markdown-it-anchor');
const slugify = require('transliteration').slugify;
const containers = require('./containers');
const overWriteFenceRule = require('./fence');
const config = new Config();
config
  .options.html(true).end()
  .plugin('anchor').use(anchorPlugin, [
    {
      level: 2,
      slugify: slugify,
      permalink: true,
      permalinkBefore: true
    }
  ]).end()
  .plugin('containers').use(containers).end();
const md = config.toMd();
overWriteFenceRule(md);
module.exports = md;

代码中用到很多插件,我们先百度下这几个插件的作用。

markdown-it-chain:npm上markdown-it-chain包的描述是这样的:

In order to ensure the consistency of the chained API world, webpack-it-chain is developed directly on the basis of webpack-chain and ensures that the usage is completely consistent.Here are some things worth reading that come from webpack-chain:ChainedMapConfig plugins

因为英语不好,我用谷歌翻译:

为了确保链式API世界的一致性,直接在webpack-chain的基础上开发了webpack-it-chain,并确保用法是完全一致的。

确保链式API世界的一致性这句基本没看懂,可能作者老哥也和我一样英语不好,但我们可以知道这个插件是在webpack-it-chain的基础做的功能完善优化。通过给的markdown-it-chain的例子我们知道 config.js代码主要就是在声明使用markdown-it-chain的。markdown-it-chain的例子代码如下:

// Require the markdown-it-chain module. This module exports a single
// constructor function for creating a configuration API.
const Config = require('markdown-it-chain')
 
// Instantiate the configuration with a new API
const config = new Config()
 
// Make configuration changes using the chain API.
// Every API call tracks a change to the stored configuration.
config
  // Interact with 'options' in new MarkdownIt
  // Ref: https://markdown-it.github.io/markdown-it/#MarkdownIt.new
  .options
    .html(true) // equal to .set('html', true)
    .linkify(true)
    .end()
 
  // Interact with 'plugins'
  .plugin('toc')
    // The first parameter is the plugin module, which may be a function
    // while the second parameter is an array of parameters accepted by the plugin.
    .use(require('markdown-it-table-of-contents'), [{
      includeLevel: [2, 3]
    }])
    // Move up one level, like .end() in jQuery.
    .end()
 
  .plugin('anchor')
    .use(require('markdown-it-anchor'), [{
      permalink: true,
      permalinkBefore: true,
      permalinkSymbol: '$'
    }])
    // Apply this plugin before toc.
    .before('toc')
 
// Create a markdown-it instance using the above configuration
const md = config.toMd()
md.render('[[TOC]] \n # h1 \n ## h2 \n ## h3 ')

要知道markdown-it-chain的到底是做什么的,我去查了下webpack-chain插件

Use a chaining API to generate and simplify the modification of webpack version 2-4 configurations.

链式API用于创建和修改webpack配置

就是提供一些链式函数的调用方法来修改和创建webpack配置,例子如下:

const Config = require('webpack-chain');

const config = new Config();

config
.amd(amd)
.bail(bail)
.cache(cache)
.devtool(devtool)
.context(context)
.externals(externals)
.loader(loader)
.name(name)
.mode(mode)
.parallelism(parallelism)
.profile(profile)
.recordsPath(recordsPath)
.recordsInputPath(recordsInputPath)
.recordsOutputPath(recordsOutputPath)
.stats(stats)
.target(target)
.watch(watch)
.watchOptions(watchOptions)

至此第一个插件markdown-it-chain我们知道了他的用处:用链式调用的方法来创建和修改markdown-it配置,而其中plugin是给markdown-it配置一些插件。config.js代码中

 .plugin('anchor').use(anchorPlugin, [
    {
      level: 2,
      slugify: slugify,
      permalink: true,
      permalinkBefore: true
    }
  ]).end()
  .plugin('containers').use(containers).end();

就是给markdown-it添加markdown-it-anchorcontainers.js插件。

那么这里抛出一个问题,为什么使用markdown-it-chain,它带来的好处是什么呢?

npm上 webpack-chain的文档是这么说的:

webpack's core configuration is based on creating and modifying a potentially unwieldy JavaScript object. While this is OK for configurations on individual projects, trying to share these objects across projects and make subsequent modifications gets messy, as you need to have a deep understanding of the underlying object structure to make those changes.

webpack的核心配置基于创建和修改可能难以使用的JavaScript对象。 尽管这对于单个项目上的配置是可以的,但是尝试在项目之间共享这些对象并进行后续修改会很麻烦,因为您需要对基础对象结构有深刻的了解才能进行这些更改。

大概意思理解了,但因为没有经常操作webpack的配置所以对尝试在项目之间共享这些对象并进行后续修改会很麻烦这个点get不到。后续去找资料麻烦的点具体是指的什么,大家也可以一起讨论下。觉得写的可以点个赞。下篇继续!

参考资料

Element 文档中的 Markdown 解析的更多相关文章

  1. php解析word,获得文档中的图片

    背景 前段时间在写一个功能:用原生php将获得word中的内容并导入到网站系统中.因为文档中存在公式,图片,表格等,因此写的比较麻烦. 思路 大体思路是先将word中格式为doc的文档转化为docx, ...

  2. Java解析word,获取文档中图片位置

    前言(背景介绍): Apache POI是Apache基金会下一个开源的项目,用来处理office系列的文档,能够创建和解析word.excel.ppt格式的文档. 其中对word文档的处理有两个技术 ...

  3. 使用Python中的HTMLParser、cookielib抓取和解析网页、从HTML文档中提取链接、图像、文本、Cookies(二)(转)

    对搜索引擎.文件索引.文档转换.数据检索.站点备份或迁移等应用程序来说,经常用到对网页(即HTML文件)的解析处理.事实上,通过 Python语言提供的各种模块,我们无需借助Web服务器或者Web浏览 ...

  4. 如何在Markdown文档中插入空格?

    简单说 在 Markdown 文档中,可以直接采用 HTML 标记插入空格(blank space),而且无需任何其他前缀或分隔符.具体如下所示: 插入一个空格 (non-breaking space ...

  5. 【python】使用HTMLParser、cookielib抓取和解析网页、从HTML文档中提取链接、图像、文本、Cookies

    一.从HTML文档中提取链接 模块HTMLParser,该模块使我们能够根据HTML文档中的标签来简洁.高效地解析HTML文档. 处理HTML文档的时候,我们常常需要从其中提取出所有的链接.使用HTM ...

  6. 01将图片嵌入到Markdown文档中

    将图片内嵌入Markdown文档中 将图片嵌入Markdown文档中一直是一个比较麻烦的事情.通常的做法是将图片存入本地某个路径或者网络存储空间,使用URL链接的形式插入图片: ![image][ur ...

  7. Python中的HTMLParser、cookielib抓取和解析网页、从HTML文档中提取链接、图像、文本、Cookies(二)

    对搜索引擎.文件索引.文档转换.数据检索.站点备份或迁移等应用程序来说,经常用到对网页(即HTML文件)的解析处理.事实上,通过 Python语言提供的各种模块,我们无需借助Web服务器或者Web浏览 ...

  8. dom4j解析xml报"文档中根元素后面的标记格式必须正确"

    今天,在写个批量启动报盘机的自动化应用,为了简化起见,将配置信息存储在xml中,格式如下: <?xml version="1.0" encoding="UTF-8& ...

  9. 详解xml文件描述,读取方法以及将对象存放到xml文档中,并按照指定的特征寻找的方案

    主要的几个功能: 1.完成多条Emp信息的XML描述2.读取XML文档解析Emp信息3.将Emp(存放在List中)对象转换为XML文档4.在XML文档中查找指定特征的Emp信息 dom4j,jaxe ...

随机推荐

  1. B 等差素数列

    B 等差素数列:2,3,5,7,11,13,....是素数序列.类似:7,37,67,97,127,157 这样完全由素数组成的等差数列,叫等差素数数列.上边的数列公差为30,长度为6.2004年,格 ...

  2. Codeforces Beta Round #19 D. Points

    Description Pete and Bob invented a new interesting game. Bob takes a sheet of paper and locates a C ...

  3. CF1462-F. The Treasure of The Segments

    题意: 给出n个线段组成的集合,第i个线段用 \(\{l_i, r_i\}\) 表示线段从坐标轴的点\(l_i\)横跨到点\(r_i\).现在你可以删除其中的一些线段,使得剩下的线段组成的集合中至少存 ...

  4. oslab oranges 一个操作系统的实现 实验三 认识保护模式(二):分页

    实验目的: 掌握内存分页机制 对应章节:3.3 实验内容: 1.认真阅读章节资料,掌握什么是分页机制 2. 调试代码,掌握分页机制基本方法与思路 – 代码3.22中,212行---237行,设置断点调 ...

  5. 【非原创】codeforces 1029F Multicolored Markers 【贪心+构造】

    题目:戳这里 题意:给a个红色小方块和b个蓝色小方块,求其能组成的周长最小的矩形,要求红色或蓝色方块至少有一个也是矩形. 思路来源:戳这里 解题思路:遍历大矩形可能满足的所有周长,维护最小值即可.需要 ...

  6. leetcode 2 两数相加 考虑溢出

    先用int存了结果然后出错,int溢出了. 真是憨批嗷. 不用考虑保存结果,直接一位一位计算就行. 感觉被描述误导了. /** * Definition for singly-linked list. ...

  7. Leetcode(19)-删除链表的倒数第N个节点

    给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点. 示例: 给定一个链表: 1->2->3->4->5, 和 n = 2. 当删除了倒数第二个节点后,链表变为 ...

  8. Keras 报错: Error when checking target: expected dense_4...

    笔者此处是一个回归任务, 最后一层是: ... pred = Dense(1)(x) 在最后一个Dense层前加上x = Flatten()(x)即可.

  9. Redux Middleware All in One

    Redux Middleware All in One https://redux.js.org/advanced/middleware https://redux.js.org/api/applym ...

  10. svg insert shape string bug

    svg insert shape string bug not support custom areaProps attributes ??? const svg = document.querySe ...