Skip to content

tonitrnel/markdown

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

45 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Painted Markdown

一个使用 Rust 编写的 Markdown AST 解析器

Motivation

我需要一个能解析 Markdown AST 的解析器,用于解析 CommonMark、GFM(GitHub Flavored Markdown)和 OFM(Obsidian Flavored Markdown)。除了解析 Markdown 格式外,还能解析 HTML 顶层标签(Tag)的 nameattributes

需要注意的是,渲染 HTML 并不是该库的实现目标,这一功能主要用于测试目的。该库其核心需求是将库编译为 WebAssembly(WASM),然后在 NodeJS 的 Astro 项目中使用,根据 AST(抽象语法树)渲染相应的组件。之所以使用 Rust 语言而不是 TypeScript 编写是为了方便学习和实践 Rust 语言。

如果你在寻找一个高性能的 Markdown Rust 库,我推荐使用 pulldown-cmark ,其性能是本库的 20 倍以上。

注意:该库尚未通过所有测试,使用 \t 制表符会导致某些例如列表出现解析错误,建议使用 4 个空格替代 \t

Installation

npm i @painted/markdown-binding

Usage

import { parse, type DocumentNode, type AstNode } from "@painted/markdown-binding";

const markdown = parse("## hello world");
const node = markdown.tree as DocumentNode; // Document Node,入口

export type DetermineElement =
  | readonly []
  | readonly [tag: string]
  | readonly [tag: string, props: Record<string, unknown>];

export const determineElement = (
  node: AstNode | undefined,
): DetermineElement => {
    if (!node) return [];
    switch (node.kind) {
        case "document": {
            return []
        }
        case 'paragraph': {
          return ['p', {id: node.id ? `block-${node.id}` : undefined}];
        }
        case "text": {
            const text = node.content;
        }
        // ...
    }
}

const render = (nodes: ReadonlyArray<AstNode>) => {
  for (const node of nodes){
    const [tag, props] = determineElement(node);
    if (!tag) continue
    // do something...
  }
}
render(node.children) // render document children

默认启用 autocorrect 用于优化排版

Todos

Blocks

  • Thematic-Breaks
  • ATX Headings
  • Setext headings
  • Indented code blocks
  • Fenced code blocks
  • HTML blocks
  • Link reference definitions
  • Paragraphs
  • Blank lines
  • Tables(GFM)
  • Block quotes
  • List items
  • Task list items(GFM)
  • Callouts(OFM)
  • Footnotes

Inlines

  • Backslash escapes
  • Entity and numeric character references
  • Code spans
  • Emphasis and strong emphasis
  • Strikethrough(GFM)
  • Links
  • Internal links(OFM)
  • Block reference(OFM)
  • Block defining id(OFM)
  • Images
  • Embedding Files(OFM)
  • Math(OFM)
  • Autolinks
  • Autolinks(GFM)
  • RawHTML
  • Comments(OFM)
  • DisallowedRawHTML(GFM)
  • Hard line breaks
  • Soft line breaks
  • Emoji
  • Tag
  • Textual content

Other

  • Smart Punctuation
  • 中文语境优化 chinese-copywriting-guidelines
  • 在 delimiter 针对 CJK 符号的特殊处理
  • 颜色文字 #fff{这是白色的文本}:red[这是红色的文本]:red{这是红色的背景?}

Processing flow

Input(&str)
   |
   V
Tokenizer(TokenIterator)
   |
   V
-----------------
| Parse Blocks
|  extract line
|   process line
|   add line with block_id to inlines
------------------
   |
   V
------------------
| Parse Inlines
|  process block's line
|   process delimiter
|   process text(merge, cjk autocorrect)
------------------
   |
   V
Output(AST Tree)

License

MIT

About

a markdown parser

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published