引入代码来源:深入分析markdown-it-quote插件的魔法

markdown-it-quote是一个用于markdown-it的插件,支持多种代码围栏功能。

这是 SourceCodeTrace 项目之一,提供一种 Markdown Fence 的解析方案,包括对代码块的引用、高亮、链接等功能。

SourceCodeTrace Project 帮助您在博客、文章记录的过程中,引入对应项目以及版本,行号等信息,让后续的读者,通过引用来源,能够进行更加深入的学习,在博客或文章中引入代码块时,尽量提供代码的来源信息。

对于新的Markdown格式,如果你觉得写起来很复杂, 可以用 MarkdownQuote 插件,让你在IDE中高效地复制代码块。

更多细节请参阅 SourceCodeTrace 项目

Markdown 写法

以下是一些用法示例,演示代码块包含的不同信息,方便大家在博客的记录中,引入代码块的来源信息。

  • 代码块归属 第3125到3131行,并且将第3126到3130行标记为高亮,并链接到URL:

    ```java {3125-3131} {3129,3131} (https://github.com/10cl/fwkdev/blob/android-13.0.0_r52/dev/src/frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java#L3125-L3131)
    // 冻结时使用当前调整,解冻时设置调整。
    if (state.getCurAdj() >= ProcessList.CACHED_APP_MIN_ADJ && !opt.isFrozen()
    && !opt.shouldNotFreeze()) {
    mCachedAppOptimizer.freezeAppAsyncLSP(app);
    } else if (state.getSetAdj() < ProcessList.CACHED_APP_MIN_ADJ) {
    mCachedAppOptimizer.unfreezeAppLSP(app, oomAdjReason);
    }
    }
  • 代码块归属 第3125到3131行,并链接到URL:

    ```java {3125-3131} (https://github.com/10cl/fwkdev/blob/android-13.0.0_r52/dev/src/frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java#L3125-L3131)
    // 冻结时使用当前调整,解冻时设置调整。
    if (state.getCurAdj() >= ProcessList.CACHED_APP_MIN_ADJ && !opt.isFrozen()
    && !opt.shouldNotFreeze()) {
    mCachedAppOptimizer.freezeAppAsyncLSP(app);
    } else if (state.getSetAdj() < ProcessList.CACHED_APP_MIN_ADJ) {
    mCachedAppOptimizer.unfreezeAppLSP(app, oomAdjReason);
    }
    }
  • 只链接到URL:

    ```java (https://github.com/10cl/fwkdev/blob/android-13.0.0_r52/dev/src/frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java#L3125-L3131)
    // 冻结时使用当前调整,解冻时设置调整。
    if (state.getCurAdj() >= ProcessList.CACHED_APP_MIN_ADJ && !opt.isFrozen()
    && !opt.shouldNotFreeze()) {
    mCachedAppOptimizer.freezeAppAsyncLSP(app);
    } else if (state.getSetAdj() < ProcessList.CACHED_APP_MIN_ADJ) {
    mCachedAppOptimizer.unfreezeAppLSP(app, oomAdjReason);
    }
    }
  • 仅高亮第1至2行:

    ```java {1-2}
    // 冻结时使用当前调整,解冻时设置调整。
    if (state.getCurAdj() >= ProcessList.CACHED_APP_MIN_ADJ && !opt.isFrozen()
    && !opt.shouldNotFreeze()) {
    mCachedAppOptimizer.freezeAppAsyncLSP(app);
    } else if (state.getSetAdj() < ProcessList.CACHED_APP_MIN_ADJ) {
    mCachedAppOptimizer.unfreezeAppLSP(app, oomAdjReason);
    }
    }
  • 高亮第3行:

    ```java{3}
    // 冻结时使用当前调整,解冻时设置调整。
    if (state.getCurAdj() >= ProcessList.CACHED_APP_MIN_ADJ && !opt.isFrozen()
    && !opt.shouldNotFreeze()) {
    mCachedAppOptimizer.freezeAppAsyncLSP(app);
    } else if (state.getSetAdj() < ProcessList.CACHED_APP_MIN_ADJ) {
    mCachedAppOptimizer.unfreezeAppLSP(app, oomAdjReason);
    }
    }
  • 仅指定语言:

    ```java
    // 冻结时使用当前调整,解冻时设置调整。
    if (state.getCurAdj() >= ProcessList.CACHED_APP_MIN_ADJ && !opt.isFrozen()
    && !opt.shouldNotFreeze()) {
    mCachedAppOptimizer.freezeAppAsyncLSP(app);
    } else if (state.getSetAdj() < ProcessList.CACHED_APP_MIN_ADJ) {
    mCachedAppOptimizer.unfreezeAppLSP(app, oomAdjReason);
    }
    }

使用方法

要使用markdown-it-quote,首先通过NPM安装该包:

npm i markdown-it-quote

然后,您可以在JavaScript代码中这样使用它:

const MarkdownIt = require('markdown-it');
const markdownQuote = require('markdown-it-quote'); const md = new MarkdownIt();
md.use(markdownQuote); md.render(markdownString);

请注意,语言名称和左大括号之间的高亮行是可选的。

为了增加自定义样式,您可以使用以下CSS代码为代码引入链接一些自定义样式:

.gist-meta-quote {
font-size: 12px;
padding: 10px;
overflow: hidden;
color: white;
border-radius: 0 0 6px 6px;
} .gist-meta-quote a {
float: right;
color: white;
text-decoration: underline;
}

vurepress 使用详解

  • package.json 中引入依赖
    "markdown-it-quote": "^1.0.3"

/package.json?#L7-L7

  • config.json 里面加入 markdown 拓展
  markdown: {
extendMarkdown: md => {
const markdownQuote = require('markdown-it-quote')
md.use(markdownQuote);
}
},

/source/.vuepress/config.js?#L12-L17

  • md 文件中直接用新的形式来写代码
```java {3125-3131} {3126-3130} (https://github.com/10cl/fwkdev/blob/android-13.0.0_r52/dev/src/frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java#L3125-L3131)
// Use current adjustment when freezing, set adjustment when unfreezing.
if (state.getCurAdj() >= ProcessList.CACHED_APP_MIN_ADJ && !opt.isFrozen()
&& !opt.shouldNotFreeze()) {
mCachedAppOptimizer.freezeAppAsyncLSP(app);
} else if (state.getSetAdj() < ProcessList.CACHED_APP_MIN_ADJ) {
mCachedAppOptimizer.unfreezeAppLSP(app, oomAdjReason);
}
}
```

/source/README.md?#L31-L40

完整的可以参考Vuepress集成的patch

随心定制样式以适合您自己的需要。

原理解析

fence 拓展

export default (md) => {
const fence = md.renderer.rules.fence;
md.renderer.rules.fence = (...args) => {
const [tokens, idx, options, , self] = args;
const token = tokens[idx];

/src/index.js?#L7-L11

markdown-it 的拓展是通过重写 md.renderer.rules.fence 来实现对 fence的重新解析。

关键格式的解析

通过解析得到核心的解析块

java {3125-3131} {3129,3131} (https://github.com/10cl/fwkdev/blob/android-13.0.0_r52/dev/src/frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java#3125-L3131)

从中解析出 代码块所在的起始行、结束行、高亮块、以及链接。

然后通过预定义的模板将其渲染出来。

从用户的角度来说,其中核心的要点就是要支持多种格式,比如原始的格式,以及为了推动代码块来源的可追溯性,还需要支持之前默认的格式。

核心的几块逻辑,就是通过正则表达式来解析出来的。

const regex1 = /(\S+)\s?(\{([\d,-]+)})\s?(\{([\d,-]+)})\s?([\S]+)/i;
const regex2 = /(\S+)\s+(\{\d+-\d+\})?\s+(\S+)/i;
const regex3 = /(\S+)\s?(\{([\d,-]+)})/i;
const regex4 = /(\S+)\s+([^\{]\S+)/i;
const regex5 = /(\S+)/i;

/src/index.js?#L1-L5

https://regex101.com/r/osOtEv/1

高亮支持

对于高亮的支持,需要支持两种形式,一种是

  • 起始行-结束行
  • 通过,分割的单行
      lines.map((split, index) => {
const lineNumber = index + wrapLineNumStart;
lineNumbersCode += `<span class="line-number">${lineNumber}</span><br>`; let inRange = false;
if (highLightLineNumbers !== undefined) {
inRange = highLightLineNumbers.some(([start, end]) => {
if (start && end) {
return lineNumber >= start && lineNumber <= end;
}
return lineNumber === start;
}); if (inRange) {
highlightWrapCode += `<div class="highlighted">&nbsp;</div>`;
} else {
highlightWrapCode += `<br>`;
}
}
});

/src/index.js?#L136-L155

链接的定义

      const gistInfo = `<div class="gist-meta-quote"><a href="${linkUrl}" target="_blank">view raw</a></div>`;

/src/index.js?#L168-L169

这里通过解析到 url 转换成html格式,点击 view raw 即新窗口打开原始的代码源链接。

这里如果不通过这种新的markdown格式,也可以仅采用默认代码块,然后加一条链接的形式,指明你的代码来源。

贡献

如果您想为此项目做出贡献,请按照以下步骤进行:

  1. Fork仓库。
  2. 创建您的特性分支:git checkout -b my-new-feature
  3. 提交您的更改:git commit -am 'Add some feature'
  4. 推送到分支:git push origin my-new-feature
  5. 提交拉取请求

作者

markdown-it-quote10cl编写和维护,并在MIT许可证下发布。

希望得到各位老铁的支持,使这个项目变得更好。

引入代码来源:深入分析markdown-it-quote插件的魔法的更多相关文章

  1. Markdown For EditPlus插件发布(基于EditPlus快速编辑Markdonw文件,写作爱好的福音来啦)

    详细介绍: Markdown For EditPlus插件使用说明 开发缘由 特点好处: 中文版使用说明 相关命令(输入字符敲空格自动输出): EditPlus常用快捷键: 相关教程: English ...

  2. Markdown For EditPlus插件使用说明(基于EditPlus快速编辑Markdonw文件,写作爱好者的福音来啦)

    Markdown For EditPlus插件使用说明 开发缘由 特点好处: 中文版使用说明 相关命令(输入字符敲空格自动输出): EditPlus常用快捷键: 相关教程: English descr ...

  3. Markdown学习和插件介绍

    markdown能干啥 亲们github上的项目首页的 内容+样式,都是项目中README.md文件控制的.将md风格的代码,转化成html. 而且markdown语法非常简单,5-10分钟即可学会! ...

  4. SpringBoot入门篇--整合mybatis+generator自动生成代码+druid连接池+PageHelper分页插件

    原文链接 我们这一篇博客讲的是如何整合Springboot和Mybatis框架,然后使用generator自动生成mapper,pojo等文件.然后再使用阿里巴巴提供的开源连接池druid,这个连接池 ...

  5. MarkDown的vim插件安装

    作用:可以使markdown语法高亮.1.安装.使用pathogen插件管理.    cd ~/.vim/bundle    git clone https://github.com/plasticb ...

  6. uni-app微信小程序开发之引入腾讯视频小程序播放插件

    登录微信小程序管理后台添加腾讯视频播放插件: 正式开始使用腾讯视频小程序插件之前需先在微信公众平台 -> 第三方设置 -> 插件管理处添加插件,如下图所示: 在uni-app中引入插件代码 ...

  7. Sublime Markdown预览插件安装流程

    使用方法 在sublime中已编辑好的markdown使用快捷键 Alt+M 即可在浏览器预览效果. 需要安装的插件 Markdown Editting:主要用来做 Markdown 编辑时的语法高亮 ...

  8. 《Three.js 入门指南》3.1.2 - 一份整齐的代码结构以及使用ORBIT CONTROLS插件(轨道控制)实现模型控制

    3.1.2 正式代码结构 & ORBIT CONTROLS插件(轨道控制) 说明 本节内容属于插入节,<Three.js入门指南>这本书中,只是简单的介绍了一些概念,是一本基础的入 ...

  9. 80行代码教你写一个Webpack插件并发布到npm

    1. 前言 最近在学习 Webpack 相关的原理,以前只知道 Webpack 的配置方法,但并不知道其内部流程,经过一轮的学习,感觉获益良多,为了巩固学习的内容,我决定尝试自己动手写一个插件. 这个 ...

  10. ubuntu自带的gedit编辑器添加Markdown预览插件

    gedit安装Markdown Preview Ubuntu自带的gedit编辑器也是有很强大的功能的,且支持插件的安装.对于喜欢用Markdown的我来说,这当然是很好的了,gedit本身 就支持M ...

随机推荐

  1. Ffmpeg分布式视频转码问题总结

    本文主要聊一聊云原生时代分布式转码系统实施过程中碰到的一些问题. 聊问题之前简单介绍一下我们的分布式转码方案. 云原生分布式转码 在计算资源招之即来的云计算时代,正在重构着软件架构的方方面面. 对软件 ...

  2. 【解决方法】查找比较组时报错:An object (User, Group, or Built-in security principal) with the following nameca..

    目录-快速跳转 问题描述 原因分析: 解决方案: 附言: 问题描述 操作环境与场景: 在 VM 内 Windows 2019 中,在组策略管理中,对GPO进行组查找时报错: An object (Us ...

  3. 完美的背景图全屏css代码 – background-size:cover?

    写主题样式的时候经常会碰到用背景图铺满整个背景的需求,这里分享下使用方法 需要的效果 图片以背景的形式铺满整个屏幕,不留空白区域 保持图像的纵横比(图片不变形) 图片居中 不出现滚动条 多浏览器支持 ...

  4. 爬虫之浏览器指纹ja3_hash的更改

    浏览器指纹 反爬中会遇到浏览器指纹,它是不会随着你更换 IP 或者 User-Agent 而改变的.并且他们的指纹每次请求也是固定的.只要网站发现某个拥有特定指纹的客户端持续高频率请求网站,它就可以把 ...

  5. vue之关闭eslint及vue/require-v-for-key 、vue/no-unsed-vars报错解决方法

    报错:Page1组件已经注册但是没有被使用.  vue/no-unused-components 如果报错以下: 解决方法: 首先打开项目中的package,json 找到eslint-config ...

  6. docker升级gitlab

    昨天在家部署了gitlab,版本居然是15.10,公司版本却是14.6,升级一波. 官方文档: https://docs.gitlab.com/ee/update/#upgrading-without ...

  7. Kubernetes GoRoutineMap工具包代码详解

    1.概述 GoRoutineMap 定义了一种类型,可以运行具有名称的 goroutine 并跟踪它们的状态.它防止创建具有相同名称的多个goroutine,并且在上一个具有该名称的 goroutin ...

  8. OSI7层模型和TCP/IP模型

    前言 在计算机网络领域中,OSI7层模型和TCP/IP模型是两个重要的概念.本文将对这两个模型进行介绍和比较,让大家了解它们的区别和联系. 目录 前言 OSI7层模型 TCP/IP模型 OSI7层模型 ...

  9. spring cloud gateway网关(一)之网关路由

    1.gateway相关介绍 在微服务架构中,系统往往由多个微服务组成,而这些服务可能部署在不同机房.不同地区.不同域名下.这种情况下,客户端(例如浏览器.手机.软件工具等)想要直接请求这些服务,就需要 ...

  10. DIY制作隔离信号注入变压器

    最近在学习模电知识,接触到了测量运放环路增益,需要使用合适的注入变压器,查找资料发现商用信号注入变压器价格昂贵,不适合个人学习使用.看到LOTO使用普通音频变压器做测试,也跟技术群友做了交流,尝试使用 ...