Golang中是否有支持“论坛风格”帖子格式化的库?

Golang中是否有支持“论坛风格”帖子格式化的库? 大家好,

我需要构建一个功能,允许我网站的用户输入“论坛风格”格式的帖子或评论。他们需要能够将文本加粗、插入标题(类似于H1、H2等)、插入图片、划分段落等。

一些示例: [B]加粗文本[B] [IMG]图片链接[IMG] [H]标题[H] 等等

我的网站在显示页面时,将根据上述标签将此帖子/评论渲染为HTML。

我正准备开始编写自己的实现,但转念一想,应该先在这里问问是否已经存在类似的东西。从安全角度来看,我有点担心JavaScript/HTML注入到这个格式化引擎中。

是否有任何现成的此类工具?

谢谢!

2 回复

看起来像是“bbcode”,在谷歌上的第一个结果是 https://github.com/frustra/bbcode

不过,如果你更喜欢 Markdown,谷歌上的另一个首选结果似乎是 https://github.com/yuin/goldmark

更多关于Golang中是否有支持“论坛风格”帖子格式化的库?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Golang中,确实有处理类似BBCode(论坛风格标记)的库。推荐使用 github.com/microcosm-cc/bluemonday 结合自定义解析器来实现安全渲染。

以下是一个简单的实现示例:

package main

import (
    "fmt"
    "regexp"
    "strings"
    
    "github.com/microcosm-cc/bluemonday"
)

type BBCodeParser struct {
    sanitizer *bluemonday.Policy
}

func NewBBCodeParser() *BBCodeParser {
    // 创建安全策略,允许基本HTML标签
    p := bluemonday.UGCPolicy()
    p.AllowAttrs("src").OnElements("img")
    p.AllowAttrs("alt").OnElements("img")
    
    return &BBCodeParser{
        sanitizer: p,
    }
}

func (p *BBCodeParser) Parse(input string) string {
    // 定义BBCode到HTML的转换规则
    replacements := []struct {
        pattern *regexp.Regexp
        replace string
    }{
        {regexp.MustCompile(`\[B\](.*?)\[/B\]`), `<strong>$1</strong>`},
        {regexp.MustCompile(`\[I\](.*?)\[/I\]`), `<em>$1</em>`},
        {regexp.MustCompile(`\[U\](.*?)\[/U\]`), `<u>$1</u>`},
        {regexp.MustCompile(`\[H1\](.*?)\[/H1\]`), `<h1>$1</h1>`},
        {regexp.MustCompile(`\[H2\](.*?)\[/H2\]`), `<h2>$1</h2>`},
        {regexp.MustCompile(`\[IMG\](.*?)\[/IMG\]`), `<img src="$1" alt="user image">`},
        {regexp.MustCompile(`\[URL\](.*?)\[/URL\]`), `<a href="$1">$1</a>`},
        {regexp.MustCompile(`\[URL=(.*?)\](.*?)\[/URL\]`), `<a href="$1">$2</a>`},
        {regexp.MustCompile(`\r?\n`), `<br>`},
    }
    
    // 应用所有替换规则
    output := input
    for _, r := range replacements {
        output = r.pattern.ReplaceAllString(output, r.replace)
    }
    
    // 使用bluemonday进行HTML净化
    return p.sanitizer.Sanitize(output)
}

func main() {
    parser := NewBBCodeParser()
    
    // 测试用例
    testInput := `[H1]欢迎来到论坛[/H1]
这是一个[B]加粗[/B]的文本示例。
查看我的图片:[IMG]https://example.com/image.jpg[/IMG]
访问我的网站:[URL=https://example.com]示例网站[/URL]`
    
    result := parser.Parse(testInput)
    fmt.Println(result)
}

对于更完整的BBCode支持,可以考虑使用专门的BBCode库:

// 使用 github.com/phpbb/phpbb-formatter 的Golang移植版本思路
package main

import (
    "fmt"
    "github.com/flosch/pongo2"
)

type AdvancedBBCodeParser struct {
    template *pongo2.Template
}

func NewAdvancedBBCodeParser() *AdvancedBBCodeParser {
    // 使用模板定义更复杂的转换规则
    return &AdvancedBBCodeParser{}
}

func (p *AdvancedBBCodeParser) ParseWithTemplate(input string) string {
    // 这里可以使用模板引擎处理复杂BBCode
    // 例如嵌套标签、列表等
    return input
}

安全方面,bluemonday 会过滤掉所有未明确允许的HTML标签和属性,防止XSS攻击:

func TestSanitization() {
    p := bluemonday.UGCPolicy()
    
    // 恶意输入示例
    malicious := `<script>alert('xss')</script>[B]正常文本[/B]`
    parser := NewBBCodeParser()
    
    safeOutput := parser.Parse(malicious)
    // 输出: <strong>正常文本</strong>
    // <script>标签已被移除
    fmt.Println(safeOutput)
}

对于性能要求高的场景,可以预编译正则表达式并缓存解析结果:

type CachedParser struct {
    parser   *BBCodeParser
    cache    map[string]string
    patterns map[string]*regexp.Regexp
}

func NewCachedParser() *CachedParser {
    cp := &CachedParser{
        parser: NewBBCodeParser(),
        cache:  make(map[string]string),
        patterns: map[string]*regexp.Regexp{
            "bold":   regexp.MustCompile(`\[B\](.*?)\[/B\]`),
            "italic": regexp.MustCompile(`\[I\](.*?)\[/I\]`),
            // ... 其他模式
        },
    }
    return cp
}

这些实现提供了安全的BBCode解析,同时防止了HTML/JavaScript注入攻击。

回到顶部