vue:无法将“vue”识别为脚本_使用WebPack将MD文件解析为Vue组件

https://github.com/Linkontoask/md2vue-loader​github.com

本文适合对webpack有一丁点了解的同学,因为会涉及到loader的编写。不过不用害怕,因为webpack的loader并不复杂,我们只需要了解一点基础即可。传送门 [编写一个loader](https://webpack.docschina.org/contribute/writing-a-loader/)

阅读官方文档后可以发现,其实我们只需要改变内容的输出即可,在这里要注意一下,loader的加载顺序是从后往前,也就是说,我们要想把md文件编译为vue组件,需要先使用markdown的解析器将md文件编译为html文件,再由vue-loader渲染成vue组件(其中需要注意一下,仓库中是将script标签放在前面,如果有时间可以写正则判断哪些script是属于vue组件的script内容)。大概的流程如图所示

8fe613c27d9870bb3cbda904493baad9.png

流程图中 md2vue-loader 就是我们写逻辑代码的地方,比如可以自定义md语法,改变输出交给vue-loader,这样我们就完成了md转换成vue组件。接下来,我们详细的介绍 md2vue-loader。

首先我们要明确需求,如何将md文件转换为vue组件。如果还不知道md文件,请移步https://zh.wikipedia.org/wiki/Markdown。

还要明确一点就是,vue组件需要什么内容。请移步https://vue-loader.vuejs.org/zh/spec.html。

那么,我们负责将md文件转换为templatescriptstyle(自定义块不考虑),其中 style可以从外部导入,md2vue-loader不负责这部分内容 。那我们如何提取其中html内容和javascript内容。

我们可以使用社区提供的markdown-it,仓库地址 https://github.com/markdown-it/markdown-it,markdown-it提供了render方法 ,代码如下

// md2vue-loader
module.exports = function (source) {
  var MarkdownIt = require('markdown-it'),
    md = new MarkdownIt();
  var result = md.render(source);
  return `<template><div>${result}</div></template>`;
}

到这里,我们已经可以将md文件转换为html文件并输出了。什么,不信?赶快开一个仓库去试一试,或者clone我的仓库试一试https://github.com/Linkontoask/md2vue-loader。

既然得到html内容了是不是大功告成了?不,当然不,之前我们说过vue组件不仅仅只有template ,还有更重要的javascript部分。我们这里使用一个很简单的方法提取html文件中 ,就是将script标签放在文件开头,然后再用indexOf方法判断,再使用 slice方法切割字符串、拼接后输出。具体代码如下:

module.exports = function (source) {
  var MarkdownIt = require('markdown-it'),
    md = new MarkdownIt();

  const content = md.render(source);

  let start = 0, pageScript = '', output = '';

  if (content.indexOf('<script>') === 0) {
    start = content.indexOf('</script>') + '</script>'.length;
    pageScript = content.slice(0, start);
  }

  output = content.slice(start);

  return `
    <template>
      <section class="markdown-body">
        ${output}
      </section>
    </template>
    ${pageScript}
  `;
};

在这里,md2vue-loader基本已经完成,还有一些功能,比如标题的ID、永久链接、锚点的类名等等。

所有代码请移步到 https://github.com/Linkontoask/md2vue-loader

这里贴一个截止到2019-12-17代码

// index.js
const { getOptions } =  require('loader-utils');
const validateOptions = require('schema-utils');
const MarkdownIt = require('markdown-it');
const Hljs = require('highlight.js');
const slugify = require('transliteration').slugify;

const schema = {
  type: 'object',
  properties: {
    html: {
      type: "boolean"
    },
    permalink: {
      type: "boolean"
    }
  }
};

function mdOption (options = {}) {
  return new MarkdownIt({
    html: options.html,
    highlight: function (str, lang) {
      if (lang && Hljs.getLanguage(lang)) {
        try {
          return Hljs.highlight(lang, str, true).value;
        } catch (e) {}
      }
      return str;
    }
  }).use(require('markdown-it-anchor'), {
    slugify: slugify,
    permalink: options.permalink
  });
}

/**
 * @param source
 * @returns {string}
 */
module.exports = function (source) {
  const options = getOptions(this);

  validateOptions(schema, options);

  const md = mdOption(options);

  const content = md.render(source);

  let start = 0, pageScript = '', output = '';

  if (content.indexOf('<script>') === 0) {
    start = content.indexOf('</script>') + '</script>'.length;
    pageScript = content.slice(0, start);
  }

  output = content.slice(start);

  return `
    <template>
      <section class="markdown-body">
        ${output}
      </section>
    </template>
    ${pageScript}
  `;
};

配置参数参考源码,可自行更改。

// webpack.config.js
module: {
    rules: [
      {
        test: /.md$/,
        use: [
          'vue-loader',
          {
            loader: path.resolve(__dirname, '../index.js'),
            options: {
              html: true // 是否渲染原生标签,如果要使用script标签务必设置为true
            }
          }
        ],
      }
    ]
  }

md2vue-loader参考[Element](https://github.com/ElemeFE/element)实现思路,还有值得优化的部分。比如:

https://github.com/ElemeFE/element/blob/6ec5f8e900ff698cf30e9479d692784af836a108/build/md-loader/index.js#L53​github.com

转载请注明出处,谢谢。

参考链接

markdown-it | markdown-it 中文文档​markdown-it.docschina.org https://github.com/valeriangalliat/markdown-it-anchor​github.com API — v-easy-components​linkorg.club
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值