基于VitePress创建组件文档

news2025/8/7 6:04:41

我们准备用vitepress做我们的组件文档,方便我们浏览组件,提供使用指南给用户。

安装VitePress

安装:

yarn add -D vitepress

创建第一个文档:

mkdir docs && echo '# Hello VitePress' > docs/index.md

增加脚本命令:

{
  "scripts": {
    "docs:dev": "vitepress dev docs",
    "docs:build": "vitepress build docs",
    "docs:serve": "vitepress serve docs"
  }
}

本地启动:

yarn docs:dev

浏览器访问看效果:http://localhost:3000/,这是VitePress默认的效果。

在这里插入图片描述

参考:https://vitepress.vuejs.org/guide/getting-started.html

配置VitePress

我们需要实现以下功能:

  • 需要一个左侧菜单,用来展示我们有哪些组件
  • 点击左侧菜单中的组件,可以展示这个组件的基本信息、Demo、API文档

配置sidebar

VitePress有一个配置文件,里面有一个themeConfig/sidebar配置,可以配置左侧菜单。

docs/.vitepress/config.ts

const sidebar = [
  {
    text: '快速开始',
    items: [
      { text: '安装', link: '/guide/install' } // /guide/install.md
    ]
  },
  {
    text: '通用',
    items: [
      { text: 'Button 按钮', link: '/components/button/' } // /components/button/index.md
    ]
  },
  { text: '导航', items: [] },
  { text: '反馈', items: [] },
  { text: '数据录入', items: [] },
  { text: '数据展示', items: [] },
  { text: '布局', items: [] }
]

export default {
  themeConfig: {
    sidebar
  }
}

点击左侧菜单的Button,看下效果,页面404了:

在这里插入图片描述

创建Button组件的文档

404的原因是我们没有创建相应的文档,创建docs/component/button/index.md

先随便写一些内容:

# Button 按钮

再看下效果:

在这里插入图片描述

在md中增加vue组件

VitePress的一大好处是可以直接在md中写vue组件,VitePress会将其渲染出来,docs/components/button/index.md

# Button 按钮
<s-button></s-button>

我们还没有实现这个s-button,所以没有效果。

编写一个Button组件

下面我们编写这个Button组件,sheep-ui/src/button/src/Button.tsx:

const Button = () => <div>Button 按钮</div>
export default Button

引入Button组件

docs/.vitepress/theme/index.ts

import DefaultTheme from 'vitepress/theme'
import Button from '../../../src/button/src/Button'

export default {
  ...DefaultTheme,
  enhanceApp({ app }) {
    // register global components
    app.component('s-button', Button)
  }
}

报错:React is not defined

Uncaught (in promise) ReferenceError: React is not defined
    at Button (button.tsx:1)

引入jsx插件

docs/vite.config.ts中引入jsx插件:

import { defineConfig } from 'vite'
import vueJsx from '@vitejs/plugin-vue-jsx'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vueJsx()]
})

组件显示出来了!

在这里插入图片描述

组件Demo代码展示

使用 Vitepress 编写组件示例有以下不足之处:

  • 1.组件示例和示例代码本质上一样,却需要写两遍。
  • 2.Vitepress 无法渲染 Markdown 中的 script 和 style 代码块。

比如下面这样:

<!-- index.md -->

<!-- 以下是显示组件部分 -->
<s-icon name="emoji"><s-icon>

<!-- 以下是暴露到文档的代码块 -->
<!-- 需要再次重复写同样的代码 -->
```html
<s-icon name="emoji"><s-icon>

vitepress有款支持demo展示的插件vitepress-theme-demoblock可以解决以上问题,写一遍同时显示结果和代码块,先安装:

yarn add -D vitepress-theme-demoblock

注入插件

首先我们得知道vitepress关于markdown的拓展规则,vitepress 使用markdown-it作为 markdown 渲染器,具体可以查看,我们得将插件在vitepressconfig.js中注册,如下面这样:

import { demoBlockPlugin } from 'vitepress-theme-demoblock'

module.exports = {
  markdown: {
    config: (md) => {
      // 这里可以使用 markdown-it 插件,vitepress-theme-demoblock就是基于此开发的
      md.use(demoBlockPlugin)
    }
  }
}

我们还得在docs/.vitepress/theme/index.ts中注册vitepress-theme-demoblock插件所需的demodemo-block组件,以及所需样式。如下面这样

// 主题样式
import 'vitepress-theme-demoblock/theme/styles/index.css'
// 插件的组件,主要是demo组件
import Demo from 'vitepress-theme-demoblock/components/Demo.vue'
import DemoBlock from 'vitepress-theme-demoblock/components/DemoBlock.vue'

export default {
  enhanceApp({ app }) {
    app.component('Demo', Demo)
    app.component('DemoBlock', DemoBlock)
  }
}

至此,vitepress-theme-demoblock的就在vitepress中注册成功了!

接下来按要求编写文档,比如下面这样写:

:::demo 使用`s-button`创建一个按钮。
  ```vue
  <template>
    <s-button></s-button>
  </template>

:::
最终生成的效果如图所示,效果非常棒~
在这里插入图片描述

样式不太协调,而且不支持暗黑模式,这里给个样式仅供参考

```Sass (Sass) 
$dividing-line: #dfe1e6;
$dividing-line-dark: #3b3b3b;
$base-bg: #ffffff;
$base-bg-dark: #2c2c2c;
$brand: #42b883;
$area: #f8f8f8;
$area-dark: #242424;
$text:#252b3a;
$text-dark:#f8f8f8;
$font-size: 12px;
$disabled-line: #dfe1e6;
$border-radius: 3px;
$disabled-bg:#f5f5f6;
$disabled-text:#adb0b8;

// 点击复制代码 message样式修复
.demoblock-message-wrap{
  .demoblock-message-content{
    background-color: #3dcca6 !important;
  }
}

.dark {
  .demo-block {
    border: solid 1px $dividing-line-dark !important;
  }
  .demo-block-control {
    background-color: $base-bg-dark !important;
    border-top: solid 1px $dividing-line-dark !important;
  
    &:hover {
      color: $brand !important;
    }
  
    .control-button {
      color: $brand !important;
    }

    .control-icon {
      color: #565656
    }
  }
  .meta {
    border-top: solid 1px $dividing-line-dark !important;
    background-color: $area-dark !important;
  
    .description {
      border:transparent !important;
      color: $text-dark !important;
      background-color: transparent !important;
    }

    .highlight div[class*='language-'] {
      margin: 0 !important;
      border-radius: 0;
      border: solid 1px $dividing-line-dark !important;
      background-color: $base-bg-dark !important;
    }
  }

  .vp-doc [class*='language-'] {
    pre {
      background-color: $base-bg-dark !important;
      
      code{
        background-color: $base-bg-dark !important;
        border-radius: 10;
        color: $text-dark !important
      }
    }
  }
}

.demo-block {
  border: solid 1px $dividing-line !important;

  &.hover {
    box-shadow: none !important;
  }

  .source {
    .demo-spacing {
      & > * {
        margin: 0 8px 8px 0;

        &:last-child {
          margin-right: 0;
        }
      }

      &:last-child {
        & > * {
          margin-bottom: 0;
        }
      }
    }
  }
}

.demo-block-control {
  background-color: $base-bg !important;
  border-top: solid 1px $dividing-line !important;

  &:hover {
    color: $brand !important;
  }

  .control-button {
    color: $brand !important;
  }
}

.meta {
  border-top: solid 1px $dividing-line !important;
  background-color: $area !important;

  .description {
    border: solid 1px $dividing-line !important;
    color: $text !important;
    background-color: $base-bg !important;
  }
}

[class^=version-tag] {
  display: inline-block;
  padding: 0 4px;
  line-height: 20px;
  color: #ffffff;
  border-radius: 4px;
}

.version-tag-1 {
  background-color: #3dcca6;
}

.version-tag-2 {
  background-color: #f66f6a;
}



// 代码样式
code {
  margin: 0;
  border-radius: 3px;
  padding: 0.25rem 0.5rem;
  font-family: var(--code-font-family);
  font-size: 0.85em;
  color: var(--text,#252b3a) !important;
  background-color: $area !important;
}

code .token.deleted {
  color: #ec5975;
}

code .token.inserted {
  color: var(--c-brand);
}

div[class*='language-'] {
  position: relative;
  margin: 1rem -1.5rem;
  background-color: $area !important;
  overflow-x: auto;
}

li > div[class*='language-'] {
  border-radius: 6px 0 0 6px;
  margin: 1rem -1.5rem 1rem -1.25rem;
}

@media (min-width: 420px) {
  div[class*='language-'] {
    margin: 1rem 0;
    border-radius: 6px;
  }

  li > div[class*='language-'] {
    margin: 1rem 0 1rem 0rem;
    border-radius: 6px;
  }
}

[class*='language-'] pre,
[class*='language-'] code {
  text-align: left;
  white-space: pre;
  word-spacing: normal;
  word-break: normal;
  word-wrap: normal;
  -moz-tab-size: 4;
  -o-tab-size: 4;
  tab-size: 4;
  -webkit-hyphens: none;
  -moz-hyphens: none;
  -ms-hyphens: none;
  hyphens: none;
}

[class*='language-'] pre {
  position: relative;
  z-index: 1;
  margin: 0;
  padding: 1.25rem 1.5rem;
  background: transparent;
  overflow-x: auto;
}

[class*='language-'] code {
  padding: 0;
  line-height: var(--code-line-height);
  font-size: var(--code-font-size);
  color: #eee;
}

/* Line highlighting */

.highlight-lines {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  padding: 1.25rem 0;
  width: 100%;
  line-height: var(--code-line-height);
  font-family: var(--code-font-family);
  font-size: var(--code-font-size);
  user-select: none;
  overflow: hidden;
}

.highlight-lines .highlighted {
  background-color: rgba(0, 0, 0, 0.66);
}

/* Line numbers mode */

div[class*='language-'].line-numbers-mode {
  padding-left: 3.5rem;
}

.line-numbers-wrapper {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  z-index: 3;
  border-right: 1px solid rgba(0, 0, 0, 0.5);
  padding: 1.25rem 0;
  width: 3.5rem;
  text-align: center;
  line-height: var(--code-line-height);
  font-family: var(--code-font-family);
  font-size: var(--code-font-size);
  color: #888;
}

/* Language marker */

div[class*='language-']:before {
  position: absolute;
  top: 0.6em;
  right: 1em;
  z-index: 2;
  font-size: 0.8rem;
  color: #888;
}

div[class~='language-html']:before,
div[class~='language-markup']:before {
  content: 'html';
}

div[class~='language-md']:before,
div[class~='language-markdown']:before {
  content: 'md';
}

div[class~='language-css']:before {
  content: 'css';
}

div[class~='language-sass']:before {
  content: 'sass';
}

div[class~='language-scss']:before {
  content: 'scss';
}

div[class~='language-less']:before {
  content: 'less';
}

div[class~='language-stylus']:before {
  content: 'styl';
}

div[class~='language-js']:before,
div[class~='language-javascript']:before {
  content: 'js';
}

div[class~='language-ts']:before,
div[class~='language-typescript']:before {
  content: 'ts';
}

div[class~='language-json']:before {
  content: 'json';
}

div[class~='language-rb']:before,
div[class~='language-ruby']:before {
  content: 'rb';
}

div[class~='language-py']:before,
div[class~='language-python']:before {
  content: 'py';
}

div[class~='language-sh']:before,
div[class~='language-bash']:before {
  content: 'sh';
}

div[class~='language-php']:before {
  content: 'php';
}

div[class~='language-go']:before {
  content: 'go';
}

div[class~='language-rust']:before {
  content: 'rust';
}

div[class~='language-java']:before {
  content: 'java';
}

div[class~='language-c']:before {
  content: 'c';
}

div[class~='language-yaml']:before {
  content: 'yaml';
}

div[class~='language-dockerfile']:before {
  content: 'dockerfile';
}

div[class~='language-vue']:before {
  content: 'vue';
}

/**
 * prism.js tomorrow night eighties for JavaScript, CoffeeScript, CSS and HTML.
 * Based on https://github.com/chriskempson/tomorrow-theme
 *
 * @author Rose Pritchard
 */
.token.comment,
.token.block-comment,
.token.prolog,
.token.doctype,
.token.cdata {
  color: #999;
}

.token.punctuation {
  color: #ccc;
}

.token.tag,
.token.attr-name,
.token.namespace,
.token.deleted {
  color: #e2777a;
}

.token.function-name {
  color: #6196cc;
}

.token.boolean,
.token.number,
.token.function {
  color: #f08d49;
}

.token.property,
.token.class-name,
.token.constant,
.token.symbol {
  color: #f8c555;
}

.token.selector,
.token.important,
.token.atrule,
.token.keyword,
.token.builtin {
  color: #cc99cd;
}

.token.string,
.token.char,
.token.attr-value,
.token.regex,
.token.variable {
  color: #7ec699;
}

.token.operator,
.token.entity,
.token.url {
  color: #67cdcc;
}

.token.important,
.token.bold {
  font-weight: bold;
}

.token.italic {
  font-style: italic;
}

.token.entity {
  cursor: help;
}

.token.inserted {
  color: green;
}


还需要在.vitepress/theme/index.ts中引入样式文件

import './demo-block.scss'

由于用到sass,还需要安装一下它:

yarn add -D sass

最后,需要大家注意的是,当我们需要在demo代码块中编写js或ts代码时,引入库一定要使用单引号,否则会爆下图的错误,这是vitepress-theme-demoblock的特殊邀请,详情查阅其文档。

  :::demo 导入vue的时候使用单引号,使用单引号,使用单引号
  <script setup>
    import { ref } from 'vue';
    // import { ref } from "vue"; // 这样引入会报错
    const title = ref('card')
  </script>
  :::

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/34562.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

十大跑步运动耳机品牌排行榜,值得推荐的六款运动耳机

除了工作时间&#xff0c;大多数人群都喜欢去运动健身&#xff0c;戴着耳机放着喜爱的音乐&#xff0c;慢跑在城市的每个角落里&#xff0c;看着各种事物&#xff0c;悠然自得释放压力的同时还能更加有动力去运动&#xff0c;不得不说&#xff0c;运动确实能够让我们暂时忘却烦…

算法训练Day28 | LeetCode93.复原IP地址(回溯算法中的切割问题2);78 子集(每个节点都收集结果);90.子集II(子集问题+去重)

前言&#xff1a;算法训练系列是做《代码随想录》一刷&#xff0c;个人的学习笔记和详细的解题思路&#xff0c;总共会有60篇博客来记录&#xff0c;记录结构上分为 思路&#xff0c;代码实现&#xff0c;复杂度分析&#xff0c;思考和收获&#xff0c;四个方面。如果这个系列的…

通过DIN算法进行深度特征组合商品推荐 数据+代码(可作为毕设)

案例知识点 推荐系统任务描述:通过用户的历史行为(比如浏览记录、购买记录等等)准确的预测出用户未来的行为;好的推荐系统不仅如此,而且能够拓展用户的视野,帮助他们发现可能感兴趣的却不容易发现的item;同时将埋没在长尾中的好商品推荐给可能感兴趣的用户。 方法概述:…

美团SemEval 2022结构化情感分析跨语言赛道冠军方法总结

总第547篇2022年 第064篇美团语音交互部针对跨语言结构化情感分析任务中缺少小语种的标注数据、传统方法优化成本高昂的问题&#xff0c;通过利用跨语言预训练语言模型、多任务和数据增强方法在不同语言间实现低成本的迁移&#xff0c;相关方法获得了SemEval 2022结构化情感分析…

使用dispatchEvent解决重叠元素响应事件问题

.npm 下的缓存文件太多怎么办&#xff1f;.npm 下缓存的包长时间未清理&#xff0c;占用空间太大怎么办&#xff1f; 查看磁盘占用情况 linux 系统里&#xff0c;查看磁盘占用情况&#xff1a;df -h 1.查看单个目录磁盘占用情况du -sh /指定目录 2.查看所有目录的磁盘占用情况…

基于VGG与LSTM实现针对图片的问答任务 数据+代码 可以作为毕设

任务描述:本教程将通过深度学习的方式实现一个简单的视觉问答模型,视觉问答的任务内容是将一张图片和一个自然语言问题作为输入,结合这两种信息,机器生成一条自然语言答案。本教程通过数据准备,视觉问答模型构建,视觉问答模型训练,视觉问答模型评估,视觉问答模型预测等…

2022年亚太C题资料汇总更新目录

1.17版本更新内容&#xff1a; 为大家收集了一套网上的成品论文&#xff0c;切记只能借鉴&#xff0c;不可全抄 1.16版本更新内容&#xff1a; 根据半成品论文中提及的加分点&#xff0c;为大家收集了本次比赛中作图较为好看的方式。 1.15版本更新内容&#xff1a; 对上传…

Hbuilder出现 CR LF

今天打开Hbuilder编辑器发现&#xff0c;咦&#xff0c;怎么变成这个样子了&#xff0c;我设置了啥&#xff1f; 最终尝试寻找了半天&#xff0c;原来这是显示了换行符号 &#xff0c;取消这个勾选就OK

西门子S7-200 SMART(6ES7 288-1ST40-0AA0)相关与晨控智能CK-FR08-E00关于modbus tcp 通信配置指南

西门子S7-200 SMART(6ES7 288-1ST40-0AA0)相关与晨控智能CK-FR08-E00关于modbus tcp 通信配置指南 准备阶段 软件&#xff1a;STEP 7-MicroWIN SMART PLC:S7-200 SMATR (6ES7 288-1ST40-OAAO) 读卡器&#xff1a;CK-FR08-E00 交换机&#xff1a;标准POE交换机 电源&#x…

华为云开发者官网首页焕新升级,赋能开发者云上成长

摘要&#xff1a;近日&#xff0c;华为云开发者官网首页迎来全新改版升级。本文分享自华为云社区《华为云开发者官网首页焕新升级&#xff0c;赋能开发者云上成长》&#xff0c;作者&#xff1a; 华为云社区精选 。 近日&#xff0c;华为云开发者官网首页迎来全新改版升级&…

3.81 OrCAD软件绘制原理图时如何使用任意角度的走线?OrCAD软件怎么统一查看哪些元器件是没有PCB封装的?

笔者电子信息专业硕士毕业&#xff0c;获得过多次电子设计大赛、大学生智能车、数学建模国奖&#xff0c;现就职于南京某半导体芯片公司&#xff0c;从事硬件研发&#xff0c;电路设计研究。对于学电子的小伙伴&#xff0c;深知入门的不易&#xff0c;特开次博客交流分享经验&a…

UNI-APP_开发支付宝小程序注意事项与解决方法,支付宝小程序图片显示问题

一、编译后&#xff0c;微信小程序上图片图标显示正常&#xff0c;但是一到支付宝小程序图片图标显示就不正常如下图&#xff1a; 微信显示 支付宝显示 官方文档&#xff1a;https://opendocs.alipay.com/mini/component/image //修改前---会出问题 <image src"&qu…

WSL2编译ijkplayer

Windows 11 专业版 22H2 22621.819 应用商店安装 Ubuntu 22.04.1 LTS 控制面板——程序和功能——启用或关闭Windows功能——适用于 Linux的Windows子系统 Error: 0x800701bc WSL 2 ??? 升级WSL https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.ms…

香港阿里云服务器被攻击了怎么办

香港阿里云被流量攻击了&#xff0c;一说到防御攻击&#xff0c;很多用户可能会想到CDN、高防IP等防御产品&#xff0c;这个思路是不错的。但是香港阿里云相对于国内的阿里云而言&#xff0c;更多情况下是无法直接使用国内的CDN和高防IP来防御的。大部分用户在使用香港阿里云时…

Go运行时的内存分配器以及消耗指定大小的内存(C语言)

对于go语言在运行时的一些内存分配&#xff0c;想要详细的了解&#xff0c;我们会用到自带的runtime.MemStats&#xff0c;有很多具体的细节实现&#xff0c;而不是简单的只看任务管理器中的内存分配。 我们先来看下这个记录内存分配器的结构体 type MemStats struct {Alloc …

【新知实验室】腾讯云TRTC初体验

一、前言 今年腾讯云音视频发布了“三合一”的RT-ONE™网络。该网络整合了腾讯云实时通信网络&#xff08;TRTC&#xff09;、即时通信网络&#xff08;IM&#xff09;以及流媒体分发网络&#xff08;CDN&#xff09;三张网络&#xff0c;为业界最完整的音视频通信PaaS平台构建…

【App自动化测试】(八)三种等待方式——强制等待、隐式等待、显示等待

目录1. 为什么要添加等待&#xff1f;2. 三种等待方式3. 强制&#xff08;直接&#xff09;等待4. 隐式等待4.1 隐式等待说明4.2 隐式等待无法解决的问题5. 显式等待5.1 为什么要使用显示等待机制&#xff1f;5.1.1 Html文件加载顺序5.1.2 为什么要使用显示等待机制&#xff1f…

简化工作和生活的 7 个在线地图制作平台分享

地图制作是数据和艺术的结合&#xff0c;数据可以传达人们想要的信息&#xff0c;而艺术是传达信息的一种方式&#xff0c;两者的正确组合创造了完美的地图。 每个平台在功能和价格方面都是独一无二的&#xff0c;有人可能认为创建自定义地图需要高级制图知识或复杂的地理信息…

从react源码看hooks的原理

React暴露出来的部分Hooks //packages/react/src/React.js export {...useCallback,useContext,useEffect,useLayoutEffect,useMemo,useReducer,useRef,useState,... }功能描述 useState、useReducer: 状态值相关useEffect、useLayoutEffect: 生命周期相关useContext: 状态共…

Java多线程(一)——多线程的创建

多线程 在计算机中为了提高内存和资源的利用率&#xff0c;引入了并发编程的思想&#xff1b;多进程和多线程都能实现并发编程&#xff0c;但是多线程相对于多进程更“轻量”&#xff0c;&#xff08;多线程和多线程的关系和区别&#xff09;&#xff0c;所以这篇博客将着重讲…