golang实现HTML转Markdown格式转换插件库html-to-markdown的使用

Golang实现HTML转Markdown格式转换插件库html-to-markdown的使用

html-to-markdown是一个强大的HTML转Markdown转换器,可以将HTML(甚至是整个网站)转换为干净、可读的Markdown格式。它支持复杂的格式化、可定制的选项和插件,可以完全控制转换过程。

主要特性

  • 粗体和斜体:支持粗体和斜体,甚至可以在单个单词内使用
  • 列表:处理有序和无序列表,支持完整嵌套
  • 引用块:引用块可以包含其他元素,完美支持嵌套引用
  • 内联代码和代码块:正确处理反引号和多行代码块,保留代码结构
  • 链接和图片:正确格式化多行链接,在需要时添加空白行转义
  • 智能转义:仅在必要时转义特殊字符,避免意外的Markdown渲染
  • 移除/保留HTML:选择删除或保留特定的HTML标签,完全控制输出
  • 插件:轻松扩展插件,或创建自定义插件以增强功能
  • 表格插件:转换表格,支持对齐、行跨度和列跨度

Golang库使用

安装

go get -u github.com/JohannesKaufmann/html-to-markdown/v2

基本用法

package main

import (
	"fmt"
	"log"

	htmltomarkdown "github.com/JohannesKaufmann/html-to-markdown/v2"
)

func main() {
	input := `<strong>Bold Text</strong>`

	markdown, err := htmltomarkdown.ConvertString(input)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(markdown)
	// Output: **Bold Text**
}

使用WithDomain转换相对链接为绝对链接

package main

import (
	"fmt"
	"log"

	htmltomarkdown "github.com/JohannesKaufmann/html-to-markdown/v2"
	"github.com/JohannesKaufmann/html-to-markdown/v2/converter"
)

func main() {
	input := `<img src="/assets/image.png" />`

	markdown, err := htmltomarkdown.ConvertString(
		input,
		converter.WithDomain("https://example.com"),
	)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(markdown)
	// Output: ![](https://example.com/assets/image.png)
}

高级用法(更多控制)

package main

import (
	"fmt"
	"log"

	"github.com/JohannesKaufmann/html-to-markdown/v2/converter"
	"github.com/JohannesKaufmann/html-to-markdown/v2/plugin/base"
	"github.com/JohannesKaufmann/html-to-markdown/v2/plugin/commonmark"
)

func main() {
	input := `<strong>Bold Text</strong>`

	conv := converter.NewConverter(
		converter.WithPlugins(
			base.NewBasePlugin(),
			commonmark.NewCommonmarkPlugin(
				commonmark.WithStrongDelimiter("__"),
				// ...additional configurations for the plugin
			),

			// ...additional plugins (e.g. table)
		),
	)

	markdown, err := conv.ConvertString(input)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(markdown)
	// Output: __Bold Text__
}

标签类型和折叠

你可以指定在转换过程中如何处理不同的HTML标签:

conv.Register.TagType("nav", converter.TagTypeRemove, converter.PriorityStandard)

conv.Register.RendererFor("b", converter.TagTypeInline, base.RenderAsHTML, converter.PriorityEarly)

conv.Register.RendererFor("article", converter.TagTypeBlock, base.RenderAsHTMLWrapper, converter.PriorityStandard)

插件系统

已发布的插件

名称 描述
Base 实现基本共享功能(例如删除节点)
Commonmark 根据Commonmark规范实现Markdown
Strikethrough <strike>, <s><del>转换为~~语法
Table 根据GitHub Flavored Markdown规范实现表格

编写插件

  1. 编写你的逻辑并注册它
  2. (可选)将你的逻辑打包成一个插件并发布

CLI命令行使用

安装

# Homebrew安装
brew install JohannesKaufmann/tap/html2markdown

# 通过Go安装
go install github.com/JohannesKaufmann/html-to-markdown/v2/cli/html2markdown@latest

基本用法

$ echo "<strong>important</strong>" | html2markdown

**important**

$ curl --no-progress-meter http://example.com | html2markdown

# Example Domain

This domain is for use in illustrative examples in documents. You may use this domain in literature without prior coordination or asking for permission.

[More information...](https://www.iana.org/domains/example)

$ html2markdown --input file.html --output file.md

$ html2markdown --input "src/*.html" --output "dist/"

常见问题

扩展插件

  • 需要自定义逻辑?编写你自己的代码然后注册它
  • 如果你认为你的逻辑对其他人也有用,可以将其打包成一个插件

安全问题

这个库生成的Markdown是可读的,可以由人类修改。一旦你将这个Markdown转换回HTML(例如使用goldmark或blackfriday),你需要小心恶意内容。这个库不会清理不受信任的内容。在浏览器中显示HTML之前,请使用HTML清理器(如bluemonday)。

并发使用

你可以从(多个)goroutine中使用Converter。内部使用互斥锁,并且有一个测试来验证这种行为。

测试

你不必担心破坏转换器,因为有许多"Golden File"测试:将你的有问题的HTML片段添加到testdata文件夹中的一个.in.html文件中。然后运行go test -update,并查看GIT中哪些.out.md文件发生了变化。


更多关于golang实现HTML转Markdown格式转换插件库html-to-markdown的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang实现HTML转Markdown格式转换插件库html-to-markdown的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用html-to-markdown实现HTML转Markdown

在Go语言中,可以使用github.com/JohannesKaufmann/html-to-markdown库来实现HTML到Markdown的转换。这个库提供了简单易用的API,能够将HTML内容转换为Markdown格式。

安装

首先需要安装该库:

go get github.com/JohannesKaufmann/html-to-markdown

基本使用

下面是一个基本的使用示例:

package main

import (
	"fmt"
	"log"

	md "github.com/JohannesKaufmann/html-to-markdown"
)

func main() {
	html := `
		<h1>标题1</h1>
		<h2>标题2</h2>
		<p>这是一个段落,包含<strong>加粗</strong>和<em>斜体</em>文本。</p>
		<ul>
			<li>列表项1</li>
			<li>列表项2</li>
		</ul>
		<a href="https://example.com">链接</a>
	`

	converter := md.NewConverter("", true, nil)
	markdown, err := converter.ConvertString(html)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(markdown)
}

输出结果:

# 标题1

## 标题2

这是一个段落,包含**加粗**和*斜体*文本。

- 列表项1
- 列表项2

[链接](https://example.com)

高级配置

自定义转换规则

你可以自定义HTML元素的转换规则:

converter := md.NewConverter("", true, nil)

// 添加自定义规则
converter.AddRules(
	// 转换<blockquote>标签
	md.Rule{
		Filter: []string{"blockquote"},
		Replacement: func(content string, selec *goquery.Selection, opt *md.Options) *string {
			// 在每个blockquote行前添加>
			lines := strings.Split(content, "\n")
			for i := range lines {
				if lines[i] != "" {
					lines[i] = "> " + lines[i]
				}
			}
			content = strings.Join(lines, "\n")
			return &content
		},
	},
)

处理特定属性

converter := md.NewConverter("", true, nil)

// 处理img标签的title属性
converter.AddRules(
	md.Rule{
		Filter: []string{"img"},
		Replacement: func(content string, selec *goquery.Selection, opt *md.Options) *string {
			src := selec.AttrOr("src", "")
			alt := selec.AttrOr("alt", "")
			title := selec.AttrOr("title", "")
			
			var result string
			if title != "" {
				result = fmt.Sprintf("![%s](%s \"%s\")", alt, src, title)
			} else {
				result = fmt.Sprintf("![%s](%s)", alt, src)
			}
			
			return &result
		},
	},
)

忽略特定元素

converter := md.NewConverter("", true, nil)

// 忽略script和style标签
converter.AddRules(
	md.Rule{
		Filter: []string{"script", "style"},
		Replacement: func(content string, selec *goquery.Selection, opt *md.Options) *string {
			return nil // 返回nil表示忽略该元素
		},
	},
)

完整示例

下面是一个完整的示例,展示如何处理更复杂的HTML:

package main

import (
	"fmt"
	"log"
	"strings"

	md "github.com/JohannesKaufmann/html-to-markdown"
	"github.com/PuerkitoBio/goquery"
)

func main() {
	html := `
		<div class="article">
			<h1>文章标题</h1>
			<div class="author">作者: 张三</div>
			<p>这是第一段内容。</p>
			<p>这是第二段内容,包含<a href="https://example.com">链接</a>和<code>代码</code>。</p>
			<pre><code class="language-go">package main
import "fmt"
func main() {
	fmt.Println("Hello, World!")
}</code></pre>
			<table>
				<tr><th>姓名</th><th>年龄</th></tr>
				<tr><td>张三</td><td>25</td></tr>
			</table>
		</div>
	`

	converter := md.NewConverter("", true, nil)
	
	// 添加自定义规则
	converter.AddRules(
		// 处理表格
		md.Rule{
			Filter: []string{"table"},
			Replacement: func(content string, selec *goquery.Selection, opt *md.Options) *string {
				var header []string
				var rows [][]string
				
				// 处理表头
				selec.Find("tr").Each(func(i int, tr *goquery.Selection) {
					if i == 0 { // 第一行是表头
						tr.Find("th").Each(func(j int, th *goquery.Selection) {
							header = append(header, strings.TrimSpace(th.Text()))
						})
						return
					}
					
					// 处理数据行
					var row []string
					tr.Find("td").Each(func(j int, td *goquery.Selection) {
						row = append(row, strings.TrimSpace(td.Text()))
					})
					if len(row) > 0 {
						rows = append(rows, row)
					}
				})
				
				if len(header) == 0 || len(rows) == 0 {
					return nil
				}
				
				// 构建Markdown表格
				var builder strings.Builder
				
				// 表头
				builder.WriteString("| " + strings.Join(header, " | ") + " |\n")
				
				// 分隔线
				builder.WriteString("|")
				for range header {
					builder.WriteString(" --- |")
				}
				builder.WriteString("\n")
				
				// 数据行
				for _, row := range rows {
					builder.WriteString("| " + strings.Join(row, " | ") + " |\n")
				}
				
				result := builder.String()
				return &result
			},
		},
	)
	
	markdown, err := converter.ConvertString(html)
	if err != nil {
		log.Fatal(err)
	}
	
	fmt.Println(markdown)
}

注意事项

  1. 该库依赖github.com/PuerkitoBio/goquery来解析HTML
  2. 对于复杂的HTML结构,可能需要添加自定义规则
  3. 转换结果可能不完全符合你的预期,需要根据需求调整规则
  4. 某些HTML5元素可能没有默认的转换规则

这个库提供了灵活的API,你可以根据需要扩展或修改转换规则,以获得最佳的Markdown输出效果。

回到顶部