npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

md-react-best

v1.1.5

Published

react版本的markdown-editor

Downloads

4

Readme

Hi md-markdown-react

一款react的markdown在线编辑器,可拆离出来单独在react项目中使用

npm i md-react-best / yarn add md-react-best

在线Demo

核心原理讲解

md是什么

额。。。就是一款程序员很喜欢使用的文件格式,简单来说就是使用标记的语法,来解析成加粗,图片,斜体,列表等等的效果

文本标记识别

最基础的一部分就是当我编写了md文件格式时,我们需要去解析,#,****等等这种标记,我观察了很多插件,最终选择了markdown-it这款插件

基本布局

最基本的左右两栏的布局,左侧编辑区,右侧转换显示区

解析的核心代码

import MarkdownIt from "markdown-it"
import hljs from "highlight.js"
const md:any = new MarkdownIt({
    breaks: true, // 自动换行
    /**
     * 
     * @param code 代码
     * @param lang 语言模式
     */
    highlight: function(code, lang):string{
        // 判断是否传入语言和能否从高亮插件中获取语言
        if(lang && hljs.getLanguage(lang)){
            try {
                return `<pre><code class='hljs' language=${lang}>${hljs.highlight(code, {language: lang}).value}</code></pre>`
            } catch (error) {
                
            }
        }
        return `<pre class='hljs'><code>${md.utils.escapeHtml(code)}</code></pre>`
    }
}).use(require("markdown-it-task-checkbox"), {
    disabled: true,
    divWrap: false,
    divClass: "checkbox",
    idPrefix: "cbx_",
    ulClass: "task-list",
    liClass: "task=list-item"
}) // 任务插件配置

export default md

主要的核心就是使用markdown-it进行标记解析,然后通过传入的语言模式,使用highlight.js转换为对应的语言模式的代码

上面这一步已经将标记语言转换

快捷按钮

布局就不说了,列出基本的已存在的功能

  • 加粗
  • 斜体
  • 删除线
  • 有序列表
  • 无需列表
  • 任务列表
  • 代码语言块
  • 超链接
  • 表格
  • 图片
  • markdown主题
  • 代码高亮主题
  • 导入导出
  • 清除
  • 暂存 这里我列表加粗, 斜体,删除线如何实现的。其实实现原理很简单,居然是标记语言,那么就和html没什么区别,无疑通过一些符号占位符来标记

1.加粗 通过****包裹

**hi md-react-best**

当点击加粗按钮是时候,只需要将之前的内容加入标记字符串即可

// 首先获取当前编辑区的光标的位置
let [start, end] = getCursorPosition(props.editElement.current)
let newValue = start === end ? value.slice(0, start) + `${symbol}${txt}${symbol}` + value.slice(end) : value.slice(0, start) + symbol + value.slice(start, end) + symbol + value.slice(end)
// 拿到最新的value重新设置
props.setValue(newValue)

光标的位置很关键,分为两种情况 1.开始光标和结束光标相等的情况下 2.开始光标和结束光标不等情况下,其实就是选择了一些文字的情况

导入导出如何做到的?

如何大家对js的基础很熟悉,其实实现起来很简单,或者至少能看懂那块的代码吧

  • 导出mdwe文件
// 首先判断是否支持流对象
if (!Blob || !URL) {
    return message.error({
        content: "浏览器不支持导出md文件,请更换浏览器再试"
    })
}
// 是否存在转换只会走的value值
if (!props.value) {
    // 不存在
    return message.warn({
        content: "当前内容为空,无需导出"
    })
}
let blob = new Blob([props.value])
// 创建a标签
let aEl = document.createElement("a")
let downloadUrl = URL.createObjectURL(blob)
aEl.href = downloadUrl
aEl.download = `${hash()}.md`
aEl.click()
// 移除创建的流对象
URL.revokeObjectURL(downloadUrl)

原理实际上就是,创建a标签,a标签模拟下载链接,下载链接通过objectUrl对象创建,前提是先将编辑器内的内容变为ibjectUrl,然后出发a标签的download操作即可完成下载

  • 导出md文件
 // 判断是否有写入对象
if (!FileReader) {
    return message.error({
        content: "浏览器不支持导入md文件, 请更换浏览器再试"
    })
}
// 手动创建input文件上传框,来支持文件上传的操作
let inputEl = document.createElement("input")
inputEl.type = "file"
inputEl.accept = ".md"
inputEl.click()
inputEl.addEventListener("change", () => {
    let files = inputEl.files as FileList
    // 没有文件
    if (!files.length) {
        return
    }
    let reader = new FileReader()
    reader.readAsText(files[0])
    reader.onload = () => {
        props.setValue(reader.result as string)
        message.success({
            content: "dao"
        })
    }
})

需要使用到FileReader对象,和模拟input文件上传的操作,再将文件对象转为text文本流即可导入成功