使用 marked + highlight + tocify.tsx 完成 Markdown(码克党)笔记的渲染

本文介绍了如何在React-Nuxt环境中使用marked、highlight和tocify.tsx来渲染Markdown笔记,包括Markdown的语法渲染、高亮显示以及使用tocify.tsx创建文章大纲。详细讲述了下载模块、配置样式以及在antd框架下应用tocify.tsx的条件和步骤。
摘要由CSDN通过智能技术生成

前几天看技术胖的视频,做了一个笔记的渲染功能,记录一下做法,以后忘记了可以查看 ,可能不是很理解,先记录 。
一般,我们的文章页面 或是 后台的管理 页面,平常可能要 渲染文章 和 编写文章时的浏览;我们可以使用 以下几个插件来完成这个任务!

marked:      码克党语法的渲染;
highlight:   代码高亮;
tocify.tsx:  提取标题成大纲;


1. 语法的渲染 和 高亮显示

1.1 下载模块

npm install marked highlight.js

1.2 进行配置

我的环境是在 react-nuxt 中的,可能会有一些不同,下面的 文章的详情页面,进行笔记语法的渲染 。

details.js

import React from 'react'
import marked from 'marked'
import hljs from 'highlight.js'
import 'highlight.js/styles/monokai-sublime.css'

function Details () {
  // 配置 marked
  const renderer = new marked.Renderer()
  marked.setOptions({
    renderer: renderer,  // 这个是必须填写的
    gfm: true,  // 启动类似Github样式的Markdown,
    pedantic: false,  // 只解析符合Markdown定义的,不修正Markdown的错误
    sanitize: false,  // 原始输出,忽略HTML标签
    tables: true,  // 支持Github形式的表格,必须打开gfm选项
    breaks: false,  // 支持Github换行符,必须打开gfm选项
    smartLists: true,  // 优化列表输出
    smartypants: false,
    // 高亮显示规则 ,这里使用highlight.js来完成
    highlight: function (code) {
      return hljs.highlightAuto(code).value;
    }
  })

  // 文章详情数据
  const data = 'xxxxxxx,模拟文章内容数据, markdown 语法格式'
  
  // 里面是数据源
  let html = marked(data)
  
  return (
  	<>
      {/* 使用div的属性渲染,才可以有效果 */}
   	  <div dangerouslySetInnerHTML={{__html: html}}></div>
    </>
  )
}

里面的 data 是数据,文章内容可以在 Typora 笔记中写好格式,然后复制黏贴到里面,作为 文章的内容,这样就会有 markdown 的格式;
这样在页面中,就可以渲染 Markdown 语法了;就是样式有点不好看,我们可以使用 css 修饰一下 。



1.3 样式修饰

页面中,使用 F12 检测你的页面结构,将以下的标签进行美化:

/* 代码块 */
code {
  margin: 0 5px;
  padding: 2px 5px;
  background-color: #ffe0e0;
  color: #ff502c;
  border-radius: 5px;
}

/* 代码块 */
pre > code {
    display: block;
    padding: 10px;
    margin: 10px 0;
    background-color: #333;
    border-radius: 5px;
    overflow-y: auto;
    color: #FFF;
    font-family: Menlo, monospace;
}

/* p标签的颜色 */
p { 
	color: #666;
}

ul {
  margin-bottom: 16px;
  font-size: 1rem;
  letter-spacing: 0.1rem;
}

/* li 的项目符号在内侧,显示项目符号 */
ul > li {
   list-style: disc inside;
}

ol {
  font-size: 1rem;
}

ol > li {
   list-style: none;
}

样式你觉得 ok 就可以了 。



2. tocify.tsx 提取大纲

一般的文章详情页面,都有大纲,方便浏览者观看文章,所以呢,我们可以使用他来弄 大纲 。
一般会使用 固钉 把大纲给固定到一个地方,不让他随着页面滚动 (项目中 react 的一个框架, antd 这个 ui 框架)。
这个是使用 技术胖 介绍的插件,大家可以去看看 哔哩哔哩传送门


2.1 条件

要使用这个插件有几个条件;

1,你的项目要使用到 antd 这个ui 框架;才能使用他,因为他依赖到里面的 锚点 Anchor

2,还有下载 lodash 这个插件;

npm install --save @types/lodash

注意,不是 lodash` ,因为要使用到 ts 来写这个文件(是别人的代码);


2.2 创建插件

tocify.tsx 文件(是一个 ts 文件),编写逻辑:

import React from 'react'
import { Anchor } from 'antd'
import { last } from 'lodash'

const { Link } : any = Anchor;


export interface TocItem {
  anchor: string;
  level: number;
  text: string;
  children?: TocItem[];
}

export type TocItems = TocItem[]; // TOC目录树结构

export default class Tocify {
  tocItems: TocItems = [];

  index: number = 0;

  constructor() {
    this.tocItems = [];
    this.index = 0;
  }

  add(text: string, level: number) {
    const anchor = `toc${level}${++this.index}`;
    const item = { anchor, level, text };
    const items = this.tocItems;

    if (items.length === 0) { // 第一个 item 直接 push
      items.push(item);
    } else {
      let lastItem = last(items) as TocItem; // 最后一个 item

      if (item.level > lastItem.level) { // item 是 lastItem 的 children
        for (let i = lastItem.level + 1; i <= 2; i++) {
          const { children } = lastItem;
          if (!children) { // 如果 children 不存在
            lastItem.children = [item];
            break;
          }

          lastItem = last(children) as TocItem; // 重置 lastItem 为 children 的最后一个 item

          if (item.level <= lastItem.level) { // item level 小于或等于 lastItem level 都视为与 children 同级
            children.push(item);
            break;
          }
        }
      } else { // 置于最顶级
        items.push(item);
      }
    }

    return anchor;
  }

  reset = () => {
    this.tocItems = [];
    this.index = 0;
  };

  renderToc(items: TocItem[]) { // 递归 render
    return items.map(item => (
      <Link key={item.anchor} href={`#${item.anchor}`} title={item.text}>
        {item.children && this.renderToc(item.children)}
      </Link>
    ));
  }

  render() {
    return (
      <Anchor affix showInkInFixed targetOffset={100}>
         {this.renderToc(this.tocItems)}
      </Anchor>
    );
  }
}

上面的代码是我复制黏贴的,因为是 ts 文件,会有几个方面要注意的:

1:引入的组件要先说明,再使用:

import { Anchor } from 'antd'
import { last } from 'lodash'

const { Link } : any = Anchor;

我也不会,所以给 Link 添加了 any 这个类型;在 vscode 中会警告说 组件没有注册,差不多这个意思,不管他好像没有错误(嘻嘻嘻,别骂我);
求求大佬解答?



2.3 创建插件

在文章详情页面导入文件,然后进行配置

web > pages > details.js

// 后来的 马克党
import marked from 'marked'
import hljs from 'highlight.js'
import 'highlight.js/styles/monokai-sublime.css'

// 生成目录,注意不要写错 Tocify / tocify
import Tocify from './api/tocify.tsx'

function Details () {
  // 之前配置 marked  笔记渲染的代码
  const renderer = new marked.Renderer()
  marked.setOptions({
    renderer: renderer,
    gfm: true,
    pedantic: false,
    sanitize: false,
    tables: true,
    breaks: false,
    smartLists: true,
    smartypants: false,
    highlight: function (code) {
      return hljs.highlightAuto(code).value;
    }
  })
    
  // 配置 Tocify 大纲
  const tocify = new Tocify()
  // 前面有 marked + highlight 配置,是一起作用的
  renderer.heading = function(text, level, raw) {
    const anchor = tocify.add(text, level)
    return `<a id="${anchor}" href="#${anchor}" class="anchor-fix"><h${level}> ${text} </h${level}></a> \n`
  }
    
   return (
   	  <>
       	{/* 固钉-大纲 */}
        <Affix>
          <div>
            <h3>大纲:</h3>
            {/* 就是这个 */}
            {tocify && tocify.render()}
          </div>
        </Affix>
      </>
   )
}

export default Details

一般放在固钉里,固定位置,
如需,控制 内容 的位置,可以在 tsx 文件中调整 Anchor,就是点击大纲,文章进行定位,如果要调整文章定位的位置,可以使用 targetOffset (距离顶部位置)进行调整;

    return (
      <Anchor affix showInkInFixed targetOffset={100}>
         {this.renderToc(this.tocItems)}
      </Anchor>
    );
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
使用Vue3脚手架,可以使用marked库将Markdown文件渲染成HTML页面,并通过highlight.js库实现代码块的高亮和行号显示。下面是具体的步骤: 1. 安装所需的库 使用npm或yarn安装markedhighlight.js库: ```shell npm install marked highlight.js --save ``` 2. 创建一个Markdown文件 在src目录下创建一个Markdown文件,例如example.md,用于测试渲染Markdown的功能。 ```markdown # Hello, world! 这是一个示例Markdown文件。 ## 代码块 ```js function hello() { console.log("Hello, world!"); } ``` 以上是一个JavaScript代码块。 ## 列表 - 列表项1 - 列表项2 - 列表项3 ``` 3. 创建一个Markdown组件 在src/components目录下创建一个Markdown组件,例如Markdown.vue,用于渲染Markdown文件。 ```vue <template> <div v-html="markdown"></div> </template> <script> import marked from "marked"; import hljs from "highlight.js"; export default { name: "Markdown", props: { source: String, }, computed: { markdown() { return marked(this.source, { highlight: function (code, lang) { if (lang && hljs.getLanguage(lang)) { return hljs.highlight(lang, code).value; } return hljs.highlightAuto(code).value; }, langPrefix: "hljs language-", breaks: true, gfm: true, }); }, }, }; </script> <style> .hljs-line-numbers { text-align: right; border-right: 1px solid #ccc; color: #999; padding-right: 5px; } </style> ``` 在组件中,我们使用marked库将Markdown文件渲染成HTML页面,通过props属性接受Markdown文件的路径或字符串。同时,我们传递一个highlight函数给marked库,使用highlight.js对代码块进行高亮。另外,我们使用hljs-line-numbers类为代码块添加行号显示。 4. 在页面中使用Markdown组件 在需要显示Markdown文件的页面中,引入Markdown组件,传递Markdown文件的路径或字符串作为source属性的值。 ```vue <template> <div> <Markdown :source="markdown" /> </div> </template> <script> import Markdown from "@/components/Markdown.vue"; import exampleMarkdown from "@/example.md"; export default { name: "App", components: { Markdown, }, data() { return { markdown: exampleMarkdown, }; }, }; </script> ``` 在页面中引入Markdown组件,并将example.md文件作为markdown属性的值传递给Markdown组件。 这样,当页面加载时,Markdown组件将会把example.md文件渲染成HTML页面,并且代码块会被高亮并且显示行号。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值