浏览代码

feat: 完善文档功能

zhenyulei 5 年之前
父节点
当前提交
bc8b79b671

+ 1 - 0
.eslintignore

@@ -0,0 +1 @@
+/src/packages/**/*.md

+ 0 - 19
loader/md-vue/card-wrapper.js

@@ -1,19 +0,0 @@
-/*
-把<h>标题,替换为:::分割的标题,然后可以定制化的处理h标题
-*/
-module.exports = function cardWrapper(html) {
-  const group = html
-    .replace(/<h3/g, ':::<h3')
-    .replace(/<h2/g, ':::<h2')
-    .split(':::');
-
-  return group
-    .map(fragment => {
-      if (fragment.indexOf('<h3') !== -1) {
-        return `<div>${fragment}</div>`;
-      }
-
-      return fragment;
-    })
-    .join('');
-};

+ 0 - 15
loader/md-vue/code-wrapper.js

@@ -1,15 +0,0 @@
-/*
-处理code
-*/
-module.exports = function codeWrapper(html) {
-  const group = html.replace(/<\/pre>/g, '</pre>:::').split(':::');
-  const codeOnline = `<div class="handle-part"><a href="https://gitpod.io/#https://github.com/jdf2e/nutui.git" target="_blank" class="online-btn">在线运行</a></div>`;
-  return group
-    .map(fragment => {
-      if (fragment.indexOf('</div>demo') !== -1) {
-        return fragment.replace('<p></div>demo</p>', '') + codeOnline;
-      }
-      return fragment;
-    })
-    .join('');
-};

+ 40 - 0
loader/md-vue/config.js

@@ -0,0 +1,40 @@
+/* eslint-disable @typescript-eslint/no-var-requires */
+const Config = require('markdown-it-chain');
+const anchorPlugin = require('markdown-it-anchor');
+const slugify = require('transliteration').slugify;
+const hljs = require('highlight.js');
+const containers = require('./containers');
+const overWriteFenceRule = require('./fence');
+
+const config = new Config();
+
+const highlight = (str, lang) => {
+  if (!lang || !hljs.getLanguage(lang)) {
+    return '<pre><code class="hljs">' + str + '</code></pre>';
+  }
+  const html = hljs.highlight(lang, str, true, undefined).value;
+  return `<pre><code class="hljs language-${lang}">${html}</code></pre>`;
+};
+
+config.options
+  .html(true)
+  .highlight(highlight)
+  .end()
+
+  // .plugin('anchor').use(anchorPlugin, [
+  //   {
+  //     level: 2,
+  //     slugify: slugify,
+  //     permalink: false,
+  //     permalinkBefore: false,
+  //   },
+  // ]).end()
+
+  .plugin('containers')
+  .use(containers)
+  .end();
+
+const md = config.toMd();
+overWriteFenceRule(md);
+
+module.exports = md;

+ 25 - 0
loader/md-vue/containers.js

@@ -0,0 +1,25 @@
+/* eslint-disable @typescript-eslint/no-var-requires */
+const mdContainer = require('markdown-it-container');
+
+module.exports = md => {
+  md.use(mdContainer, 'demo', {
+    validate(params) {
+      return params.trim().match(/^demo\s*(.*)$/);
+    },
+    render(tokens, idx) {
+      const m = tokens[idx].info.trim().match(/^demo\s*(.*)$/);
+      if (tokens[idx].nesting === 1) {
+        const description = m && m.length > 1 ? m[1] : '';
+        const content = tokens[idx + 1].type === 'fence' ? tokens[idx + 1].content : '';
+        return `<demo-block>
+        ${description ? `<div>${md.render(description)}</div>` : ''}
+        <!--nutui-demo: ${content}:nutui-demo-->
+        `;
+      }
+      return '</demo-block>';
+    }
+  });
+
+  md.use(mdContainer, 'tip');
+  md.use(mdContainer, 'warning');
+};

+ 14 - 0
loader/md-vue/fence.js

@@ -0,0 +1,14 @@
+// 覆盖默认的 fence 渲染策略
+module.exports = md => {
+  const defaultRender = md.renderer.rules.fence;
+  md.renderer.rules.fence = (tokens, idx, options, env, self) => {
+    const token = tokens[idx];
+    // 判断该 fence 是否在 :::demo 内
+    const prevToken = tokens[idx - 1];
+    const isInDemoContainer = prevToken && prevToken.nesting === 1 && prevToken.info.trim().match(/^demo\s*(.*)$/);
+    if (token.info === 'html' && isInDemoContainer) {
+      return `<template #highlight><pre v-pre><code class="html">${md.utils.escapeHtml(token.content)}</code></pre></template>`;
+    }
+    return defaultRender(tokens, idx, options, env, self);
+  };
+};

+ 0 - 9
loader/md-vue/highlight.js

@@ -1,9 +0,0 @@
-const hljs = require('highlight.js');
-
-module.exports = function highlight(str, lang) {
-  if (lang && hljs.getLanguage(lang)) {
-    return hljs.highlight(lang, str, true).value;
-  }
-
-  return '';
-};

+ 56 - 68
loader/md-vue/index.js

@@ -1,80 +1,68 @@
-const loaderUtils = require('loader-utils'); //:loader-utils 是一个npm i loader-utils -D 安装的插件,便于获取webpack.config.js 中配置loader的options;
-const MarkdownIt = require('markdown-it'); //渲染 markdown 基本语法
-const markdownItAnchor = require('markdown-it-anchor'); //为各级标题添加锚点
-const frontMatter = require('front-matter'); //就是md文档最上面的内容 类似于docz中的路由/标题的设置部分
-const highlight = require('./highlight');
-const linkOpen = require('./link-open');
-const cardWrapper = require('./card-wrapper');
-const codeWrapper = require('./code-wrapper');
+/* eslint-disable @typescript-eslint/no-var-requires */
+const { stripScript, stripTemplate, genInlineComponentText } = require('./util');
+const md = require('./config');
 
-const { slugify } = require('transliteration');
-
-function wrapper(content) {
-  content = cardWrapper(content);
-  content = codeWrapper(content);
-  content = escape(content);
-
-  return `
-import { h } from 'vue';
+module.exports = function(source) {
+  const content = md.render(source);
 
-const content = unescape(\`${content}\`);
+  const startTag = '<!--nutui-demo:';
+  const startTagLen = startTag.length;
+  const endTag = ':nutui-demo-->';
+  const endTagLen = endTag.length;
 
-export default {
-  mounted() {
-    const anchors = [].slice.call(this.$el.querySelectorAll('h2, h3, h4, h5'));
+  let componenetsString = '';
+  let id = 0; // demo 的 id
+  let output = []; // 输出的内容
+  let start = 0; // 字符串开始位置
 
-    anchors.forEach(anchor => {
-      anchor.addEventListener('click', this.scrollToAnchor);
-    });
-  },
+  let commentStart = content.indexOf(startTag);
+  let commentEnd = content.indexOf(endTag, commentStart + startTagLen);
+  while (commentStart !== -1 && commentEnd !== -1) {
+    output.push(content.slice(start, commentStart));
 
-  methods: {
-    scrollToAnchor(event) {
-      if (event.target.id) {
-        this.$router.push({
-          path: this.$route.path,
-          hash: '#'+event.target.id
-        })
-      }
-    }
-  },
+    const commentContent = content.slice(commentStart + startTagLen, commentEnd);
+    const html = stripTemplate(commentContent);
+    const script = stripScript(commentContent);
+    let demoComponentContent = genInlineComponentText(html, script);
+    const demoComponentName = `nutui-demo${id}`;
+    output.push(`<template #source><${demoComponentName} /></template>`);
+    componenetsString += `${JSON.stringify(demoComponentName)}: ${demoComponentContent},`;
 
-  render() {
-    return h('section', { innerHTML: content });
+    // 重新计算下一次的位置
+    id++;
+    start = commentEnd + endTagLen;
+    commentStart = content.indexOf(startTag, start);
+    commentEnd = content.indexOf(endTag, commentStart + startTagLen);
   }
-};
-`;
-}
-
-const parser = new MarkdownIt({
-  html: true,
-  linkify: true,
-  highlight
-}).use(markdownItAnchor, {
-  level: 2, // 添加超链接锚点的最小标题级别, 如: #标题 不会添加锚点
-  slugify // 自定义slugify, 我们使用的是将中文转为汉语拼音,最终生成为标题id属性
-});
 
-module.exports = function(source) {
-  let options = loaderUtils.getOptions(this) || {}; // 获取loader的参数
-  this.cacheable && this.cacheable();
-
-  options = {
-    wrapper,
-    linkOpen: true,
-    ...options
-  };
-
-  let fm;
+  // 仅允许在 demo 不存在时,才可以在 Markdown 中写 script 标签
+  // todo: 优化这段逻辑
 
-  if (options.enableMetaData) {
-    fm = frontMatter(source);
-    source = fm.body;
-  }
-
-  if (options.linkOpen) {
-    linkOpen(parser);
+  let pageScript = '';
+  if (componenetsString) {
+    pageScript = `<script lang="ts">
+      import * as Vue from 'vue';
+      export default {
+        name: 'component-doc',
+        components: {
+          ${componenetsString}
+        }
+      }
+    </script>`;
+  } else if (content.indexOf('<script>') === 0) {
+    // 硬编码,有待改善
+    start = content.indexOf('</script>') + '</script>'.length;
+    pageScript = content.slice(0, start);
   }
 
-  return options.wrapper(parser.render(source), fm);
+  output.push(content.slice(start));
+  const result = `
+  <template>
+    <section class="content nutui-doc">
+      ${output.join('')}
+    </section>
+  </template>
+  ${pageScript}
+  `;
+  return result;
 };

+ 0 - 18
loader/md-vue/link-open.js

@@ -1,18 +0,0 @@
-// add target="_blank" to all links
-module.exports = function linkOpen(md) {
-  const defaultRender =
-    md.renderer.rules.link_open ||
-    function(tokens, idx, options, env, self) {
-      return self.renderToken(tokens, idx, options);
-    };
-
-  md.renderer.rules.link_open = function(tokens, idx, options, env, self) {
-    const aIndex = tokens[idx].attrIndex('target');
-
-    if (aIndex < 0) {
-      tokens[idx].attrPush(['target', '_blank']); // add new attribute
-    }
-
-    return defaultRender(tokens, idx, options, env, self);
-  };
-};

+ 82 - 0
loader/md-vue/util.js

@@ -0,0 +1,82 @@
+/* eslint-disable @typescript-eslint/no-var-requires */
+const { compileTemplate, TemplateCompiler } = require('@vue/compiler-sfc');
+
+function stripScript(content) {
+  const result = content.match(/<(script)>([\s\S]+)<\/\1>/);
+  return result && result[2] ? result[2].trim() : '';
+}
+
+function stripStyle(content) {
+  const result = content.match(/<(style)\s*>([\s\S]+)<\/\1>/);
+  return result && result[2] ? result[2].trim() : '';
+}
+
+// 编写例子时不一定有 template。所以采取的方案是剔除其他的内容
+function stripTemplate(content) {
+  content = content.trim();
+  if (!content) {
+    return content;
+  }
+  return content.replace(/<(script|style)[\s\S]+<\/\1>/g, '').trim();
+}
+
+function pad(source) {
+  return source
+    .split(/\r?\n/)
+    .map(line => `  ${line}`)
+    .join('\n');
+}
+
+const templateReplaceRegex = /<template>([\s\S]+)<\/template>/g;
+function genInlineComponentText(template, script) {
+  // https://github.com/vuejs/vue-loader/blob/423b8341ab368c2117931e909e2da9af74503635/lib/loaders/templateLoader.js#L46
+  let source = template;
+  if (templateReplaceRegex.test(source)) {
+    source = source.replace(templateReplaceRegex, '$1');
+  }
+  const finalOptions = {
+    source: `<div>${source}</div>`,
+    filename: 'inline-component', // TODO:这里有待调整
+    compiler: TemplateCompiler,
+    compilerOptions: {
+      mode: 'function'
+    }
+  };
+  const compiled = compileTemplate(finalOptions);
+  // tips
+  if (compiled.tips && compiled.tips.length) {
+    compiled.tips.forEach(tip => {
+      console.warn(tip);
+    });
+  }
+  // errors
+  if (compiled.errors && compiled.errors.length) {
+    console.error(`\n  Error compiling template:\n${pad(compiled.source)}\n` + compiled.errors.map(e => `  - ${e}`).join('\n') + '\n');
+  }
+  let demoComponentContent = `
+    ${compiled.code.replace('return function render', 'function render')}
+  `;
+  // todo: 这里采用了硬编码有待改进
+  script = script.trim();
+  if (script) {
+    script = script.replace(/export\s+default/, 'const democomponentExport =').replace(/import ({.*}) from 'vue'/g, (s, s1) => `const ${s1} = Vue`);
+  } else {
+    script = 'const democomponentExport = {}';
+  }
+  demoComponentContent = `(function() {
+    ${demoComponentContent}
+    ${script}
+    return {
+      render,
+      ...democomponentExport
+    }
+  })()`;
+  return demoComponentContent;
+}
+
+module.exports = {
+  stripScript,
+  stripStyle,
+  stripTemplate,
+  genInlineComponentText
+};

+ 338 - 117
package-lock.json

@@ -1136,9 +1136,9 @@
       }
     },
     "@babel/types": {
-      "version": "7.12.5",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.5.tgz",
-      "integrity": "sha512-gyTcvz7JFa4V45C0Zklv//GmFOAal5fL23OWpBLqc4nZ4Yrz67s4kCNwSK1Gu0MXGTU8mRY3zJYtacLdKXlzig==",
+      "version": "7.12.6",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.6.tgz",
+      "integrity": "sha512-hwyjw6GvjBLiyy3W0YQf0Z5Zf4NpYejUnKFcfcUhZCSffoBBp30w6wP2Wn6pk31jMYZvcOrB/1b7cGXvEoKogA==",
       "requires": {
         "@babel/helper-validator-identifier": "^7.10.4",
         "lodash": "^4.17.19",
@@ -1611,6 +1611,15 @@
       "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==",
       "dev": true
     },
+    "@types/mini-css-extract-plugin": {
+      "version": "0.9.1",
+      "resolved": "https://registry.npmjs.org/@types/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.1.tgz",
+      "integrity": "sha512-+mN04Oszdz9tGjUP/c1ReVwJXxSniLd7lF++sv+8dkABxVNthg6uccei+4ssKxRHGoMmPxdn7uBdJWONSJGTGQ==",
+      "dev": true,
+      "requires": {
+        "@types/webpack": "*"
+      }
+    },
     "@types/minimatch": {
       "version": "3.0.3",
       "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
@@ -2155,6 +2164,15 @@
             "universalify": "^0.1.0"
           }
         },
+        "json5": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
+          "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
+          "dev": true,
+          "requires": {
+            "minimist": "^1.2.0"
+          }
+        },
         "jsonfile": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
@@ -2164,6 +2182,26 @@
             "graceful-fs": "^4.1.6"
           }
         },
+        "loader-utils": {
+          "version": "1.4.0",
+          "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz",
+          "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==",
+          "dev": true,
+          "requires": {
+            "big.js": "^5.2.2",
+            "emojis-list": "^3.0.0",
+            "json5": "^1.0.1"
+          }
+        },
+        "lru-cache": {
+          "version": "5.1.1",
+          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+          "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+          "dev": true,
+          "requires": {
+            "yallist": "^3.0.2"
+          }
+        },
         "make-dir": {
           "version": "3.1.0",
           "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
@@ -2231,6 +2269,69 @@
           "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
           "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
           "dev": true
+        },
+        "vue-loader": {
+          "version": "15.9.5",
+          "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.5.tgz",
+          "integrity": "sha512-oeMOs2b5o5gRqkxfds10bCx6JeXYTwivRgbb8hzOrcThD2z1+GqEKE3EX9A2SGbsYDf4rXwRg6D5n1w0jO5SwA==",
+          "dev": true,
+          "requires": {
+            "@vue/component-compiler-utils": "^3.1.0",
+            "hash-sum": "^1.0.2",
+            "loader-utils": "^1.1.0",
+            "vue-hot-reload-api": "^2.3.0",
+            "vue-style-loader": "^4.1.0"
+          },
+          "dependencies": {
+            "hash-sum": {
+              "version": "1.0.2",
+              "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz",
+              "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=",
+              "dev": true
+            }
+          }
+        },
+        "vue-loader-v16": {
+          "version": "npm:vue-loader@16.0.0-beta.10",
+          "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.0.0-beta.10.tgz",
+          "integrity": "sha512-PflGsj4RHW3tuYFmSPhcozAkds8ELXf8d19twWorQTjcuWxl/Xqb9W1NgfsY7AAkCkkRRYy2FwIX4tSnskfKig==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "chalk": "^4.1.0",
+            "hash-sum": "^2.0.0",
+            "loader-utils": "^2.0.0"
+          },
+          "dependencies": {
+            "json5": {
+              "version": "2.1.3",
+              "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
+              "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==",
+              "dev": true,
+              "optional": true,
+              "requires": {
+                "minimist": "^1.2.5"
+              }
+            },
+            "loader-utils": {
+              "version": "2.0.0",
+              "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
+              "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
+              "dev": true,
+              "optional": true,
+              "requires": {
+                "big.js": "^5.2.2",
+                "emojis-list": "^3.0.0",
+                "json5": "^2.1.2"
+              }
+            }
+          }
+        },
+        "yallist": {
+          "version": "3.1.1",
+          "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+          "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+          "dev": true
         }
       }
     },
@@ -2295,6 +2396,15 @@
           "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
           "dev": true
         },
+        "lru-cache": {
+          "version": "5.1.1",
+          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+          "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+          "dev": true,
+          "requires": {
+            "yallist": "^3.0.2"
+          }
+        },
         "semver": {
           "version": "6.3.0",
           "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@@ -2309,6 +2419,12 @@
           "requires": {
             "has-flag": "^3.0.0"
           }
+        },
+        "yallist": {
+          "version": "3.1.1",
+          "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+          "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+          "dev": true
         }
       }
     },
@@ -2365,6 +2481,21 @@
           "requires": {
             "bluebird": "^3.7.2"
           }
+        },
+        "lru-cache": {
+          "version": "5.1.1",
+          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+          "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+          "dev": true,
+          "requires": {
+            "yallist": "^3.0.2"
+          }
+        },
+        "yallist": {
+          "version": "3.1.1",
+          "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+          "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+          "dev": true
         }
       }
     },
@@ -3546,6 +3677,23 @@
         "ssri": "^6.0.1",
         "unique-filename": "^1.1.1",
         "y18n": "^4.0.0"
+      },
+      "dependencies": {
+        "lru-cache": {
+          "version": "5.1.1",
+          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+          "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+          "dev": true,
+          "requires": {
+            "yallist": "^3.0.2"
+          }
+        },
+        "yallist": {
+          "version": "3.1.1",
+          "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+          "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+          "dev": true
+        }
       }
     },
     "cache-base": {
@@ -3735,9 +3883,9 @@
       }
     },
     "caniuse-lite": {
-      "version": "1.0.30001154",
-      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001154.tgz",
-      "integrity": "sha512-y9DvdSti8NnYB9Be92ddMZQrcOe04kcQtcxtBx4NkB04+qZ+JUWotnXBJTmxlKudhxNTQ3RRknMwNU2YQl/Org==",
+      "version": "1.0.30001156",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001156.tgz",
+      "integrity": "sha512-z7qztybA2eFZTB6Z3yvaQBIoJpQtsewRD74adw2UbRWwsRq3jIPvgrQGawBMbfafekQaD21FWuXNcywtTDGGCw==",
       "dev": true
     },
     "case-sensitive-paths-webpack-plugin": {
@@ -4261,9 +4409,9 @@
       "dev": true
     },
     "conventional-changelog-angular": {
-      "version": "5.0.11",
-      "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.11.tgz",
-      "integrity": "sha512-nSLypht/1yEflhuTogC03i7DX7sOrXGsRn14g131Potqi6cbGbGEE9PSDEHKldabB6N76HiSyw9Ph+kLmC04Qw==",
+      "version": "5.0.12",
+      "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.12.tgz",
+      "integrity": "sha512-5GLsbnkR/7A89RyHLvvoExbiGbd9xKdKqDTrArnPbOqBqG/2wIosu0fHwpeIRI8Tl94MhVNBXcLJZl92ZQ5USw==",
       "dev": true,
       "requires": {
         "compare-func": "^2.0.0",
@@ -4271,9 +4419,9 @@
       }
     },
     "conventional-changelog-conventionalcommits": {
-      "version": "4.4.0",
-      "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.4.0.tgz",
-      "integrity": "sha512-ybvx76jTh08tpaYrYn/yd0uJNLt5yMrb1BphDe4WBredMlvPisvMghfpnJb6RmRNcqXeuhR6LfGZGewbkRm9yA==",
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.5.0.tgz",
+      "integrity": "sha512-buge9xDvjjOxJlyxUnar/+6i/aVEVGA7EEh4OafBCXPlLUQPGbRUBhBUveWRxzvR8TEjhKEP4BdepnpG2FSZXw==",
       "dev": true,
       "requires": {
         "compare-func": "^2.0.0",
@@ -4282,17 +4430,17 @@
       }
     },
     "conventional-commits-parser": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.1.0.tgz",
-      "integrity": "sha512-RSo5S0WIwXZiRxUGTPuYFbqvrR4vpJ1BDdTlthFgvHt5kEdnd1+pdvwWphWn57/oIl4V72NMmOocFqqJ8mFFhA==",
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.0.tgz",
+      "integrity": "sha512-XmJiXPxsF0JhAKyfA2Nn+rZwYKJ60nanlbSWwwkGwLQFbugsc0gv1rzc7VbbUWAzJfR1qR87/pNgv9NgmxtBMQ==",
       "dev": true,
       "requires": {
         "JSONStream": "^1.0.4",
         "is-text-path": "^1.0.1",
         "lodash": "^4.17.15",
-        "meow": "^7.0.0",
+        "meow": "^8.0.0",
         "split2": "^2.0.0",
-        "through2": "^3.0.0",
+        "through2": "^4.0.0",
         "trim-off-newlines": "^1.0.0"
       }
     },
@@ -4856,6 +5004,12 @@
         "assert-plus": "^1.0.0"
       }
     },
+    "de-indent": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz",
+      "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=",
+      "dev": true
+    },
     "debug": {
       "version": "4.2.0",
       "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
@@ -5391,9 +5545,9 @@
       "dev": true
     },
     "electron-to-chromium": {
-      "version": "1.3.586",
-      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.586.tgz",
-      "integrity": "sha512-or8FCbQCRlPZHkOoqBULOI9hzTiStVIQqDLgAPt8pzY+swTrW+89vsqd24Zn+Iv4guAJLxRBD6OR5AmbpabGDA==",
+      "version": "1.3.588",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.588.tgz",
+      "integrity": "sha512-0zr+ZfytnLeJZxGgmEpPTcItu5Mm4A5zHPZXLfHcGp0mdsk95rmD7ePNewYtK1yIdLbk8Z1U2oTRRfOtR4gbYg==",
       "dev": true
     },
     "elliptic": {
@@ -6768,16 +6922,16 @@
       }
     },
     "git-raw-commits": {
-      "version": "2.0.7",
-      "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.7.tgz",
-      "integrity": "sha512-SkwrTqrDxw8y0G1uGJ9Zw13F7qu3LF8V4BifyDeiJCxSnjRGZD9SaoMiMqUvvXMXh6S3sOQ1DsBN7L2fMUZW/g==",
+      "version": "2.0.8",
+      "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.8.tgz",
+      "integrity": "sha512-6Gk7tQHGMLEL1bSnrMJTCVt2AQl4EmCcJDtzs/JJacCb2+TNEyHM67Gp7Ri9faF7OcGpjGGRjHLvs/AG7QKZ2Q==",
       "dev": true,
       "requires": {
         "dargs": "^7.0.0",
         "lodash.template": "^4.0.2",
-        "meow": "^7.0.0",
+        "meow": "^8.0.0",
         "split2": "^2.0.0",
-        "through2": "^3.0.0"
+        "through2": "^4.0.0"
       }
     },
     "glob": {
@@ -7055,10 +7209,13 @@
       "dev": true
     },
     "hosted-git-info": {
-      "version": "2.8.8",
-      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
-      "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
-      "dev": true
+      "version": "3.0.7",
+      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.7.tgz",
+      "integrity": "sha512-fWqc0IcuXs+BmE9orLDyVykAG9GJtGLGuZAAqgcckPgv5xad4AcXGIv8galtQvlwutxSlaMcdw7BUtq2EIvqCQ==",
+      "dev": true,
+      "requires": {
+        "lru-cache": "^6.0.0"
+      }
     },
     "hpack.js": {
       "version": "2.1.6",
@@ -7650,9 +7807,9 @@
       }
     },
     "is-core-module": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.0.0.tgz",
-      "integrity": "sha512-jq1AH6C8MuteOoBPwkxHafmByhL9j5q4OaPGdbuD+ZtQJVzH+i6E3BJDQcBA09k57i2Hh2yQbEG8yObZ0jdlWw==",
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.1.0.tgz",
+      "integrity": "sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA==",
       "dev": true,
       "requires": {
         "has": "^1.0.3"
@@ -8610,12 +8767,12 @@
       "dev": true
     },
     "lru-cache": {
-      "version": "5.1.1",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
-      "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+      "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
       "dev": true,
       "requires": {
-        "yallist": "^3.0.2"
+        "yallist": "^4.0.0"
       }
     },
     "magic-string": {
@@ -8699,6 +8856,45 @@
       "integrity": "sha512-WOcIGhG1M1W94VV5cmSZAMSKi2vqCxpLAqQZ0wSO9RzQ9Rbls7ecjRVXp5DIPoXrNy9bjv9K7M0nYqNk60ctxQ==",
       "dev": true
     },
+    "markdown-it-chain": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/markdown-it-chain/-/markdown-it-chain-1.3.0.tgz",
+      "integrity": "sha512-XClV8I1TKy8L2qsT9iX3qiV+50ZtcInGXI80CA+DP62sMs7hXlyV/RM3hfwy5O3Ad0sJm9xIwQELgANfESo8mQ==",
+      "dev": true,
+      "requires": {
+        "webpack-chain": "^4.9.0"
+      },
+      "dependencies": {
+        "deepmerge": {
+          "version": "1.5.2",
+          "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz",
+          "integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==",
+          "dev": true
+        },
+        "javascript-stringify": {
+          "version": "1.6.0",
+          "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-1.6.0.tgz",
+          "integrity": "sha1-FC0RHzpuPa6PSpr9d9RYVbWpzOM=",
+          "dev": true
+        },
+        "webpack-chain": {
+          "version": "4.12.1",
+          "resolved": "https://registry.npmjs.org/webpack-chain/-/webpack-chain-4.12.1.tgz",
+          "integrity": "sha512-BCfKo2YkDe2ByqkEWe1Rw+zko4LsyS75LVr29C6xIrxAg9JHJ4pl8kaIZ396SUSNp6b4815dRZPSTAS8LlURRQ==",
+          "dev": true,
+          "requires": {
+            "deepmerge": "^1.5.2",
+            "javascript-stringify": "^1.6.0"
+          }
+        }
+      }
+    },
+    "markdown-it-container": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/markdown-it-container/-/markdown-it-container-3.0.0.tgz",
+      "integrity": "sha512-y6oKTq4BB9OQuY/KLfk/O3ysFhB3IMYoIWhGJEidXt1NQFocFK2sA2t0NYZAMyMShAGL6x5OPIbrmXPIqaN9rw==",
+      "dev": true
+    },
     "md5.js": {
       "version": "1.3.5",
       "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
@@ -8749,9 +8945,9 @@
       }
     },
     "meow": {
-      "version": "7.1.1",
-      "resolved": "https://registry.npmjs.org/meow/-/meow-7.1.1.tgz",
-      "integrity": "sha512-GWHvA5QOcS412WCo8vwKDlTelGLsCGBVevQB5Kva961rmNfun0PCbv5+xta2kUMFJyR8/oWnn7ddeKdosbAPbA==",
+      "version": "8.0.0",
+      "resolved": "https://registry.npmjs.org/meow/-/meow-8.0.0.tgz",
+      "integrity": "sha512-nbsTRz2fwniJBFgUkcdISq8y/q9n9VbiHYbfwklFh5V4V2uAcxtKQkDc0yCLPM/kP0d+inZBewn3zJqewHE7kg==",
       "dev": true,
       "requires": {
         "@types/minimist": "^1.2.0",
@@ -8759,12 +8955,12 @@
         "decamelize-keys": "^1.1.0",
         "hard-rejection": "^2.1.0",
         "minimist-options": "4.1.0",
-        "normalize-package-data": "^2.5.0",
+        "normalize-package-data": "^3.0.0",
         "read-pkg-up": "^7.0.1",
         "redent": "^3.0.0",
         "trim-newlines": "^3.0.0",
-        "type-fest": "^0.13.1",
-        "yargs-parser": "^18.1.3"
+        "type-fest": "^0.18.0",
+        "yargs-parser": "^20.2.3"
       }
     },
     "merge-descriptors": {
@@ -9063,14 +9259,6 @@
       "dev": true,
       "requires": {
         "yallist": "^4.0.0"
-      },
-      "dependencies": {
-        "yallist": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-          "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
-          "dev": true
-        }
       }
     },
     "minipass-collect": {
@@ -9334,23 +9522,15 @@
       "dev": true
     },
     "normalize-package-data": {
-      "version": "2.5.0",
-      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
-      "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.0.tgz",
+      "integrity": "sha512-6lUjEI0d3v6kFrtgA/lOx4zHCWULXsFNIjHolnZCKCTLA6m/G625cdn3O7eNmT0iD3jfo6HZ9cdImGZwf21prw==",
       "dev": true,
       "requires": {
-        "hosted-git-info": "^2.1.4",
-        "resolve": "^1.10.0",
-        "semver": "2 || 3 || 4 || 5",
+        "hosted-git-info": "^3.0.6",
+        "resolve": "^1.17.0",
+        "semver": "^7.3.2",
         "validate-npm-package-license": "^3.0.1"
-      },
-      "dependencies": {
-        "semver": {
-          "version": "5.7.1",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
-          "dev": true
-        }
       }
     },
     "normalize-path": {
@@ -11001,6 +11181,30 @@
         "type-fest": "^0.6.0"
       },
       "dependencies": {
+        "hosted-git-info": {
+          "version": "2.8.8",
+          "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
+          "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
+          "dev": true
+        },
+        "normalize-package-data": {
+          "version": "2.5.0",
+          "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+          "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+          "dev": true,
+          "requires": {
+            "hosted-git-info": "^2.1.4",
+            "resolve": "^1.10.0",
+            "semver": "2 || 3 || 4 || 5",
+            "validate-npm-package-license": "^3.0.1"
+          }
+        },
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        },
         "type-fest": {
           "version": "0.6.0",
           "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
@@ -11429,9 +11633,9 @@
       "dev": true
     },
     "sass": {
-      "version": "1.28.0",
-      "resolved": "https://registry.npmjs.org/sass/-/sass-1.28.0.tgz",
-      "integrity": "sha512-9FWX/0wuE1KxwfiP02chZhHaPzu6adpx9+wGch7WMOuHy5npOo0UapRI3FNSHva2CczaYJu2yNUBN8cCSqHz/A==",
+      "version": "1.29.0",
+      "resolved": "https://registry.npmjs.org/sass/-/sass-1.29.0.tgz",
+      "integrity": "sha512-ZpwAUFgnvAUCdkjwPREny+17BpUj8nh5Yr6zKPGtLNTLrmtoRYIjm7njP24COhjJldjwW1dcv52Lpf4tNZVVRA==",
       "requires": {
         "chokidar": ">=2.0.0 <4.0.0"
       }
@@ -12647,13 +12851,25 @@
       "dev": true
     },
     "through2": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz",
-      "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==",
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz",
+      "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==",
       "dev": true,
       "requires": {
-        "inherits": "^2.0.4",
-        "readable-stream": "2 || 3"
+        "readable-stream": "3"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "3.6.0",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+          "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+          "dev": true,
+          "requires": {
+            "inherits": "^2.0.3",
+            "string_decoder": "^1.1.1",
+            "util-deprecate": "^1.0.1"
+          }
+        }
       }
     },
     "thunky": {
@@ -12810,12 +13026,6 @@
             "y18n": "^5.0.2",
             "yargs-parser": "^20.2.2"
           }
-        },
-        "yargs-parser": {
-          "version": "20.2.3",
-          "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.3.tgz",
-          "integrity": "sha512-emOFRT9WVHw03QSvN5qor9QQT9+sw5vwxfYweivSMHTcAXPefwVae2FjO7JJjj8hCE4CzPOPeFM83VwT29HCww==",
-          "dev": true
         }
       }
     },
@@ -13078,9 +13288,9 @@
       }
     },
     "type-fest": {
-      "version": "0.13.1",
-      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz",
-      "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==",
+      "version": "0.18.0",
+      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.0.tgz",
+      "integrity": "sha512-fbDukFPnJBdn2eZ3RR+5mK2slHLFd6gYHY7jna1KWWy4Yr4XysHuCdXRzy+RiG/HwG4WJat00vdC2UHky5eKiQ==",
       "dev": true
     },
     "type-is": {
@@ -13490,23 +13700,28 @@
       "dev": true
     },
     "vue-loader": {
-      "version": "15.9.5",
-      "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.5.tgz",
-      "integrity": "sha512-oeMOs2b5o5gRqkxfds10bCx6JeXYTwivRgbb8hzOrcThD2z1+GqEKE3EX9A2SGbsYDf4rXwRg6D5n1w0jO5SwA==",
+      "version": "16.0.0-beta.7",
+      "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.0.0-beta.7.tgz",
+      "integrity": "sha512-xQ8/GZmRPdQ3EinnE0IXwdVoDzh7Dowo0MowoyBuScEBXrRabw6At5/IdtD3waKklKW5PGokPsm8KRN6rvQ1cw==",
       "dev": true,
       "requires": {
-        "@vue/component-compiler-utils": "^3.1.0",
-        "hash-sum": "^1.0.2",
-        "loader-utils": "^1.1.0",
-        "vue-hot-reload-api": "^2.3.0",
-        "vue-style-loader": "^4.1.0"
+        "@types/mini-css-extract-plugin": "^0.9.1",
+        "chalk": "^3.0.0",
+        "hash-sum": "^2.0.0",
+        "loader-utils": "^1.2.3",
+        "merge-source-map": "^1.1.0",
+        "source-map": "^0.6.1"
       },
       "dependencies": {
-        "hash-sum": {
-          "version": "1.0.2",
-          "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz",
-          "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=",
-          "dev": true
+        "chalk": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+          "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
         },
         "json5": {
           "version": "1.0.1",
@@ -13530,18 +13745,6 @@
         }
       }
     },
-    "vue-loader-v16": {
-      "version": "npm:vue-loader@16.0.0-beta.10",
-      "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.0.0-beta.10.tgz",
-      "integrity": "sha512-PflGsj4RHW3tuYFmSPhcozAkds8ELXf8d19twWorQTjcuWxl/Xqb9W1NgfsY7AAkCkkRRYy2FwIX4tSnskfKig==",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "chalk": "^4.1.0",
-        "hash-sum": "^2.0.0",
-        "loader-utils": "^2.0.0"
-      }
-    },
     "vue-router": {
       "version": "4.0.0-rc.1",
       "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.0.0-rc.1.tgz",
@@ -13585,6 +13788,16 @@
         }
       }
     },
+    "vue-template-compiler": {
+      "version": "2.6.12",
+      "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.12.tgz",
+      "integrity": "sha512-OzzZ52zS41YUbkCBfdXShQTe69j1gQDZ9HIX8miuC9C3rBCk9wIRjLiZZLrmX9V+Ftq/YEyv1JaVr5Y/hNtByg==",
+      "dev": true,
+      "requires": {
+        "de-indent": "^1.0.2",
+        "he": "^1.1.0"
+      }
+    },
     "vue-template-es2015-compiler": {
       "version": "1.9.1",
       "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz",
@@ -14578,9 +14791,9 @@
       "dev": true
     },
     "yallist": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
-      "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
       "dev": true
     },
     "yaml": {
@@ -14606,17 +14819,25 @@
         "which-module": "^2.0.0",
         "y18n": "^4.0.0",
         "yargs-parser": "^18.1.2"
+      },
+      "dependencies": {
+        "yargs-parser": {
+          "version": "18.1.3",
+          "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
+          "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+          "dev": true,
+          "requires": {
+            "camelcase": "^5.0.0",
+            "decamelize": "^1.2.0"
+          }
+        }
       }
     },
     "yargs-parser": {
-      "version": "18.1.3",
-      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
-      "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
-      "dev": true,
-      "requires": {
-        "camelcase": "^5.0.0",
-        "decamelize": "^1.2.0"
-      }
+      "version": "20.2.3",
+      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.3.tgz",
+      "integrity": "sha512-emOFRT9WVHw03QSvN5qor9QQT9+sw5vwxfYweivSMHTcAXPefwVae2FjO7JJjj8hCE4CzPOPeFM83VwT29HCww==",
+      "dev": true
     },
     "yorkie": {
       "version": "2.0.0",

+ 5 - 1
package.json

@@ -69,7 +69,11 @@
     "markdown-it-anchor": "^6.0.0",
     "prettier": "^1.19.1",
     "transliteration": "^2.2.0",
-    "typescript": "~3.9.3"
+    "typescript": "~3.9.3",
+    "vue-loader": "16.0.0-beta.7",
+    "vue-template-compiler": "^2.6.12",
+    "markdown-it-chain": "^1.3.0",
+    "markdown-it-container": "^3.0.0"
   },
   "eslintConfig": {
     "root": true,

+ 2 - 2
src/sites/assets/styles/highlight.scss

@@ -25,9 +25,9 @@ pre {
 
 .hljs {
   display: block;
-  padding: 0.5em;
+  padding: 30px;
   overflow-x: auto;
-  background: #fff;
+  background: #f7f8fa;
 }
 
 .hljs-subst {

+ 32 - 0
src/sites/doc/components/demo-block/demoBlock.vue

@@ -0,0 +1,32 @@
+<template>
+  <div>
+    <slot></slot>
+    <p class="online-part">
+      <a href="//gitpod.io/#https://github.com/jdf2e/nutui.git" target="_blank" class="online-btn">在线运行</a>
+    </p>
+  </div>
+</template>
+<script>
+export default {
+  setup(props, ctx) {
+    function onlineFun() {
+      alert('hello');
+    }
+    return {
+      onlineFun
+    };
+  }
+};
+</script>
+<style lang="scss" scoped>
+.online-part {
+  display: flex;
+  justify-content: flex-end;
+  .online-btn {
+    display: block;
+    padding: 10px;
+    background: #eee;
+    cursor: pointer;
+  }
+}
+</style>

+ 2 - 0
src/sites/doc/components/demo-block/index.ts

@@ -0,0 +1,2 @@
+import DemoBlock from './demoBlock.vue';
+export default DemoBlock;

+ 2 - 0
src/sites/doc/main.ts

@@ -3,6 +3,7 @@ import App from './App.vue';
 import router from './router';
 import '@/sites/assets/styles/reset.scss';
 import '@/sites/assets/styles/md-style.scss';
+import DemoBlock from './components/demo-block';
 
 import { isMobile } from '@/sites/assets/util';
 
@@ -10,5 +11,6 @@ if (isMobile) {
   location.replace('demo.html' + location.hash);
 }
 createApp(App)
+  .component('demo-block', DemoBlock)
   .use(router)
   .mount('#doc');

+ 1 - 1
src/sites/doc/router.ts

@@ -1,4 +1,4 @@
-// @ts-nocheck
+/* eslint-disable @typescript-eslint/no-var-requires */
 import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router';
 import Index from './views/Index.vue';
 

+ 3 - 0
vue.config.js

@@ -62,6 +62,9 @@ module.exports = {
     config.module
       .rule('md-vue')
       .test(/\.md$/)
+      .use('vue-loader')
+      .loader('vue-loader')
+      .end()
       .use(path.resolve(__dirname, './loader/md-vue/index.js'))
       .loader(path.resolve(__dirname, './loader/md-vue/index.js'))
       .end();