Convert Figma logo to code with AI

88250 logolute

🎼 一款结构化的 Markdown 引擎,支持 Go 和 JavaScript。A structured Markdown engine that supports Go and JavaScript.

1,062
125
1,062
1

Top Related Projects

1,623

CommonMark parsing and rendering library and program in C

:trophy: A markdown parser written in Go. Easy to extend, standard(CommonMark) compliant, well structured.

Blackfriday: a markdown processor for Go

markdown parser and HTML renderer for Go

32,981

A markdown parser and compiler. Built for speed.

Quick Overview

Lute is a structured Markdown engine written in Go. It provides parsing, rendering, and manipulation capabilities for Markdown content, with a focus on extensibility and performance. Lute aims to be a comprehensive solution for working with Markdown in Go applications.

Pros

  • High performance and efficient parsing
  • Extensive support for various Markdown flavors and extensions
  • Customizable and extensible architecture
  • Well-documented API and usage examples

Cons

  • Primarily focused on Go language, limiting its use in other ecosystems
  • May have a steeper learning curve for complex customizations
  • Documentation is primarily in Chinese, which may be a barrier for non-Chinese speakers

Code Examples

  1. Basic Markdown parsing and rendering:
engine := lute.New()
html := engine.MarkdownStr("demo", "# Hello, Lute!")
fmt.Println(html)
// Output: <h1 id="hello-lute">Hello, Lute!</h1>
  1. Customizing Markdown rendering options:
engine := lute.New()
engine.SetHeadingAnchor(true)
engine.SetCodeSyntaxHighlight(true)
html := engine.MarkdownStr("demo", "## Custom Heading\n\n```go\nfmt.Println(\"Hello, World!\")\n```")
fmt.Println(html)
// Output: <h2 id="custom-heading">Custom Heading</h2>
// <pre><code class="language-go">fmt.Println("Hello, World!")
// </code></pre>
  1. Working with Abstract Syntax Tree (AST):
engine := lute.New()
tree := engine.ParseMarkdown([]byte("# Heading\n\nParagraph"))
heading := tree.Root.FirstChild
fmt.Println(heading.Type)  // Output: NodeHeading
fmt.Println(heading.HeadingLevel)  // Output: 1

Getting Started

To use Lute in your Go project, follow these steps:

  1. Install Lute:

    go get -u github.com/88250/lute
    
  2. Import and use Lute in your code:

    import "github.com/88250/lute"
    
    func main() {
        engine := lute.New()
        html := engine.MarkdownStr("demo", "# Hello, Lute!")
        fmt.Println(html)
    }
    
  3. Customize the engine as needed:

    engine.SetHeadingAnchor(true)
    engine.SetCodeSyntaxHighlight(true)
    

For more advanced usage and configuration options, refer to the Lute documentation.

Competitor Comparisons

1,623

CommonMark parsing and rendering library and program in C

Pros of cmark

  • Written in C, offering high performance and potential for easy integration with other languages
  • Strictly adheres to the CommonMark specification, ensuring consistent parsing
  • Extensively tested with a comprehensive test suite

Cons of cmark

  • Limited to CommonMark syntax, lacking support for extended Markdown features
  • Less flexibility for customization compared to Lute
  • Primarily focused on parsing and rendering, with fewer additional utilities

Code Comparison

cmark

cmark_node *document = cmark_parse_document(buffer, len, CMARK_OPT_DEFAULT);
char *html = cmark_render_html(document, CMARK_OPT_DEFAULT);
printf("%s", html);
free(html);
cmark_node_free(document);

Lute

engine := lute.New()
html := engine.MarkdownStr("", markdown)
fmt.Println(html)

Summary

cmark is a high-performance C implementation of CommonMark, offering strict adherence to the specification and extensive testing. It's ideal for projects requiring fast, standard-compliant Markdown parsing. Lute, written in Go, provides more flexibility and extended Markdown features, making it suitable for projects needing customization or additional Markdown syntax support. The choice between them depends on specific project requirements, performance needs, and desired Markdown feature set.

:trophy: A markdown parser written in Go. Easy to extend, standard(CommonMark) compliant, well structured.

Pros of Goldmark

  • Faster parsing and rendering performance
  • More extensive CommonMark compliance
  • Wider adoption and community support

Cons of Goldmark

  • Less feature-rich compared to Lute's advanced functionalities
  • Limited support for custom syntax extensions
  • Fewer built-in options for customizing output

Code Comparison

Goldmark:

md := goldmark.New(
    goldmark.WithExtensions(extension.GFM),
    goldmark.WithParserOptions(
        parser.WithAutoHeadingID(),
    ),
)
var buf bytes.Buffer
if err := md.Convert([]byte(source), &buf); err != nil {
    panic(err)
}

Lute:

engine := lute.New()
engine.SetGFMTable(true)
engine.SetGFMTaskListItem(true)
engine.SetHeadingAnchor(true)
html := engine.MarkdownStr("", source)

Both libraries offer easy-to-use APIs for converting Markdown to HTML, but Lute provides more built-in options for customization, while Goldmark focuses on extensibility through its modular design.

Blackfriday: a markdown processor for Go

Pros of Blackfriday

  • More established and widely used in the Go community
  • Faster parsing and rendering performance
  • Extensive CommonMark compliance

Cons of Blackfriday

  • Less active development and maintenance
  • Fewer customization options for rendering
  • Limited support for extended Markdown features

Code Comparison

Blackfriday:

import "github.com/russross/blackfriday/v2"

markdown := []byte("# Hello, World!")
html := blackfriday.Run(markdown)

Lute:

import "github.com/88250/lute"

engine := lute.New()
markdown := "# Hello, World!"
html := engine.MarkdownStr("", markdown)

Both libraries offer straightforward APIs for converting Markdown to HTML. Blackfriday uses a functional approach with the Run function, while Lute employs an object-oriented style with the engine instance.

Lute provides more configuration options and supports additional Markdown extensions, making it more flexible for customized rendering. However, Blackfriday's simpler API and better performance make it a popular choice for projects prioritizing speed and standard Markdown compliance.

markdown parser and HTML renderer for Go

Pros of markdown

  • More actively maintained with frequent updates and contributions
  • Broader language support, including CommonMark and GitHub Flavored Markdown
  • Extensive documentation and examples for easier integration

Cons of markdown

  • Larger codebase, potentially more complex to understand and modify
  • Less focus on performance optimization compared to Lute
  • May have a steeper learning curve for newcomers to the project

Code Comparison

Lute (parsing example):

ast := parse.Parse("", []byte("Hello, *Lute*!"), luteEngine.ParseOptions)

markdown (parsing example):

parser := parser.NewWithExtensions(parser.CommonExtensions)
node := parser.Parse([]byte("Hello, *markdown*!"))

Both libraries offer similar functionality for parsing Markdown, but Lute's API appears more concise in this example. However, markdown provides more flexibility with parsing extensions.

Summary

While markdown offers broader language support and more active development, Lute focuses on performance and simplicity. The choice between the two depends on specific project requirements, such as the need for extensive Markdown flavors or performance optimization.

32,981

A markdown parser and compiler. Built for speed.

Pros of marked

  • Widely adopted and battle-tested in production environments
  • Extensive documentation and community support
  • Lightweight and fast performance

Cons of marked

  • Limited customization options for parsing and rendering
  • Lacks some advanced features like syntax highlighting and table of contents generation

Code comparison

marked:

import { marked } from 'marked';

const markdown = '# Hello, world!';
const html = marked(markdown);
console.log(html);

lute:

import "github.com/88250/lute"

markdown := "# Hello, world!"
engine := lute.New()
html := engine.MarkdownStr("", markdown)
fmt.Println(html)

Key differences

  • marked is written in JavaScript, while lute is written in Go
  • lute offers more advanced features like syntax highlighting and custom rendering
  • marked has a simpler API and is easier to integrate into web applications
  • lute provides better support for Chinese language processing and formatting

Use cases

  • marked: Ideal for web applications requiring basic Markdown parsing
  • lute: Suitable for projects needing advanced Markdown features and Chinese language support

Community and maintenance

  • marked: Large community, frequent updates, and extensive third-party ecosystem
  • lute: Smaller community, but actively maintained with regular updates

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

Lute

一款结构化的 Markdown 引擎,支持 Go 和 JavaScript

千呼万唤始出来 犹抱琵琶半遮面
转轴拨弦三两声 未成曲调先有情





        

English

💡 简介

Lute 是一款结构化的 Markdown 引擎,完整实现了最新的 GFM/CommonMark 规范,对中文语境支持更好。

欢迎到 Lute 官方讨论区了解更多。同时也欢迎关注 B3log 开源社区微信公众号 B3log开源:

b3logos.jpg

📽️ 背景

之前我一直在使用其他 Markdown 引擎,它们或多或少都有些“瑕疵”:

  • 对标准规范的支持不一致
  • 对“怪异”文本处理非常耗时,甚至挂死
  • 对中文支持不够好

Lute 的目标是构建一个结构化的 Markdown 引擎,实现 GFM/CM 规范并对中文提供更好的支持。所谓的“结构化”指的是从输入的 MD 文本构建抽象语法树,通过操作树来进行 HTML 输出、原文格式化等。 实现规范是为了保证 Markdown 渲染不存在二义性,让同一份 Markdown 文本可以在实现规范的 Markdown 引擎处理后得到一样的结果,这一点非常重要。

实现规范的引擎并不多,我想试试看自己能不能写上一个,这也是 Lute 的动机之一。关于如何实现一个 Markdown 引擎,网上众说纷纭:

  • 有的人说 Markdown 适合用正则解析,因为文法规则太简单
  • 也有的人说 Markdown 可以用编译原理来处理,正则太难维护

我赞同后者,因为正则确实太难维护而且运行效率较低。最重要的原因是符合 GFM/CM 规范的 Markdown 引擎的核心解析算法不可能用正则写出来,因为规范定义的规则实在是太复杂了。

最后,还有一个很重要的动机就是 B3log 开源社区需要一款自己的 Markdown 引擎:

  • Solo、Pipe、Sym 需要效果统一的 Markdown 渲染,并且性能非常重要
  • Vditor 需要一款结构化的引擎作为支撑以实现下一代的 Markdown 编辑器

✨ 特性

  • 实现最新版 GFM/CM 规范
  • 零正则,非常快
  • 内置代码块语法高亮
  • 对中文语境支持更好
  • 术语拼写修正
  • Markdown 格式化
  • Emoji 解析
  • HTML 转换 Markdown
  • 自定义渲染函数
  • 支持 JavaScript 端使用

🗃 案例

🇨🇳 中文语境优化

  • 自动链接识别加强
  • 在中西文间自动插入空格

♍ 格式化

格式化功能可将“不整洁”的 Markdown 文本格式化为统一风格,在需要公共编辑的场景下,统一的排版风格能让大家更容易协作。

点此展开格式化示例。
Markdown 原文:
# ATX 标题也有可能需要格式化的 ##
一个简短的段落。

Setext 说实话我不喜欢 Setext 标题
----
0. 有序列表可以从 0 开始
0. 应该自增序号的
1.   对齐对齐对齐

我们再来看看另一个有序列表。
1. 没空行的情况下序号要从 1 开始才能打断段落开始一个新列表
3. 虽然乱序不影响渲染
2. 但是随意写序号容易引起误解

试下贴段代码:
```go
package main

import "fmt"

func main() {
  fmt.Println("Hello, 世界")
}
```
对了,缩进代码块建议换成围栏代码块:

    缩进代码块太隐晦了
    也没法指定编程语言,容易导致代码高亮失效
    所以建议大家用 ``` 围栏代码块
试下围栏代码块匹配场景:
````markdown
围栏代码块只要开头的 ` 和结束的 ` 数量匹配即可,这样可以实现在围栏代码块中显示围栏代码块:
```
这里只有 3 个 `,所以不会匹配markdown代码块结束
```
下面匹配到就真的结束了。
````
以上块级内容都挤在一坨了,插入合理的空行也很有必要。


但是过多的空行分段也不好啊,用来分段的话一个空行就够了。



接下来让我们试试稍微复杂点的场景,比如列表项包含多个段落的情况:
1. 列表项中的第一段

   这里是第二个段落,贴段代码:
   ```markdown
   要成为Markdown程序员并不容易,同理PPT架构师也是。
   注意代码块中的中西文间并没有插入空格。
   ```
   这里是最后一段了。
1. 整个有序列表是“松散”的:列表项内容要用 `<p>` 标签

最后,我们试下对 GFM 的格式化支持:

|col1|col2  |       col3   |
---           |---------------|--
col1 without left pipe      |   this is col2   | col3 without right pipe
                                 ||need align cell|

**以上就是为什么我们需要Markdown Format,而且是带中西文自动空格的格式化。**

格式化后:

# ATX 标题也有可能需要格式化的

一个简短的段落。

## Setext 说实话我不喜欢 Setext 标题

0. 有序列表可以从 0 开始
1. 应该自增序号的
2. 对齐对齐对齐

我们再来看看另一个有序列表。

1. 没空行的情况下序号要从 1 开始才能打断段落开始一个新列表
2. 虽然乱序不影响渲染
3. 但是随意写序号容易引起误解

试下贴段代码:

```go
package main

import "fmt"

func main() {
  fmt.Println("Hello, 世界")
}
```

对了,缩进代码块建议换成围栏代码块:

```
缩进代码块太隐晦了
也没法指定编程语言,容易导致代码高亮失效
所以建议大家用 ``` 围栏代码块
```

试下围栏代码块匹配场景:

````markdown
围栏代码块只要开头的 ` 和结束的 ` 数量匹配即可,这样可以实现在围栏代码块中显示围栏代码块:
```
这里只有 3 个 `,所以不会匹配markdown代码块结束
```
下面匹配到就真的结束了。
````

以上块级内容都挤在一坨了,插入合理的空行也很有必要。

但是过多的空行分段也不好啊,用来分段的话一个空行就够了。

接下来让我们试试稍微复杂点的场景,比如列表项包含多个段落的情况:

1. 列表项中的第一段

   这里是第二个段落,贴段代码:

   ```markdown
   要成为Markdown程序员并不容易,同理PPT架构师也是。
   注意代码块中的中西文间并没有插入空格。
   ```

   这里是最后一段了。
2. 整个有序列表是“松散”的:列表项内容要用 `<p>` 标签

最后,我们试下对 GFM 的格式化支持:

| col1                   | col2            | col3                    |
| ---------------------- | --------------- | ----------------------- |
| col1 without left pipe | this is col2    | col3 without right pipe |
|                        | need align cell |                         |

**以上就是为什么我们需要 Markdown Format,而且是带中西文自动空格的格式化。**

✍️ 术语修正

Markdown 原文:

在github上做开源项目是一件很开心的事情,请不要把Github拼写成`github`哦!

特别是简历中千万不要出现这样的情况:

> 熟练使用JAVA、Javascript、GIT,对android、ios开发有一定了解,熟练使用Mysql、postgresql数据库。

修正后:

在 GitHub 上做开源项目是一件很开心的事情,请不要把 GitHub 拼写成`github`哦!

特别是简历中千万不要出现这样的情况:

> 熟练使用 Java、JavaScript、Git,对 Android、iOS 开发有一定了解,熟练使用 MySQL、PostgreSQL 数据库。

⚡ 性能

请看 Golang markdown 引擎性能基准测试。

💪 健壮性

Lute 承载了链滴上的所有 Markdown 处理,每天处理数百万解析渲染请求,运行表现稳定。

🔒 安全性

Lute 没有实现实现 GFM 中的 Disallowed Raw HTML (extension),因为该扩展还是存在一定漏洞(比如没有处理 <input> )。 建议通过其他库(比如 bluemonday)来进行 HTML 安全过滤,这样也能更好地适配应用场景。

🛠️ 使用

有三种方式使用 Lute:

  1. 后端:用 Go 语言的话引入 github.com/88250/lute 包
  2. 后端:将 Lute 启动为一个 HTTP 服务进程供其他进程调用,具体请参考这里
  3. 前端:引入 js 目录下的 lute.min.js,支持 Node.js

Go

引入 Lute 库:

go get -u github.com/88250/lute

最小化可工作示例:

package main

import (
	"fmt"

	"github.com/88250/lute"
)

func main() {
	luteEngine := lute.New() // 默认已经启用 GFM 支持以及中文语境优化
	html:= luteEngine.MarkdownStr("demo", "**Lute** - A structured markdown engine.")
	fmt.Println(html)
	// <p><strong>Lute</strong> - A structured Markdown engine.</p>
}

关于代码块语法高亮:

  • 默认使用外部样式表,主题为 github.css,可从 chroma-styles 目录下拷贝该样式文件到项目中引入
  • 可通过 lutenEngine.SetCodeSyntaxHighlightXXX() 来指定高亮相关参数,比如是否启用内联样式、行号以及主题

JavaScript

简单示例可参考 JavaScript 目录下的 demo,结合前端编辑器的完整用法请参考 Vditor 中的示例。

Vditor

一些细节:

  1. lute.js 没有内置语法高亮特性
  2. lute.js 编译后大小为 ~3.5MB,GZip 压缩后大小 ~500KB

📜 文档

🏘️ 社区

📄 授权

Lute 使用 木兰宽松许可证, 第2版 开源协议。

🙏 鸣谢

Lute 的诞生离不开以下开源项目,在此对这些项目的贡献者们致敬!

  • commonmark.js:该项目是 CommonMark 官方参考实现的 JavaScript 版,Lute 参考了其解析器实现部分
  • goldmark:另一款用 golang 写的 Markdown 引擎,Lute 参考了其树遍历实现部分
  • golang-commonmark:另一款用 golang 写的 Markdown 引擎,Lute 参考了其 URL 编码以及 HTML 转义算法
  • Chroma:用 golang 写的语法高亮引擎
  • 中文文案排版指北:统一中文文案、排版的相关用法,降低团队成员之间的沟通成本,增强网站气质
  • GopherJS:将 Go 代码编译成 JavaScript 代码