开源软件名称(OpenSource Name):yuin/goldmark开源软件地址(OpenSource Url):https://github.com/yuin/goldmark开源编程语言(OpenSource Language):Go 99.4%开源软件介绍(OpenSource Introduction):goldmark
goldmark is compliant with CommonMark 0.30. MotivationI needed a Markdown parser for Go that satisfies the following requirements:
golang-commonmark may be a good choice, but it seems to be a copy of markdown-it. blackfriday.v2 is a fast and widely-used implementation, but is not CommonMark-compliant and cannot be extended from outside of the package, since its AST uses structs instead of interfaces. Furthermore, its behavior differs from other implementations in some cases, especially regarding lists: Deep nested lists don't output correctly #329, List block cannot have a second line #244, etc. This behavior sometimes causes problems. If you migrate your Markdown text from GitHub to blackfriday-based wikis, many lists will immediately be broken. As mentioned above, CommonMark is complicated and hard to implement, so Markdown parsers based on CommonMark are few and far between. Features
Installation$ go get github.com/yuin/goldmark UsageImport packages: import (
"bytes"
"github.com/yuin/goldmark"
) Convert Markdown documents with the CommonMark-compliant mode: var buf bytes.Buffer
if err := goldmark.Convert(source, &buf); err != nil {
panic(err)
} With optionsvar buf bytes.Buffer
if err := goldmark.Convert(source, &buf, parser.WithContext(ctx)); err != nil {
panic(err)
}
Context options
Custom parser and rendererimport (
"bytes"
"github.com/yuin/goldmark"
"github.com/yuin/goldmark/extension"
"github.com/yuin/goldmark/parser"
"github.com/yuin/goldmark/renderer/html"
)
md := goldmark.New(
goldmark.WithExtensions(extension.GFM),
goldmark.WithParserOptions(
parser.WithAutoHeadingID(),
),
goldmark.WithRendererOptions(
html.WithHardWraps(),
html.WithXHTML(),
),
)
var buf bytes.Buffer
if err := md.Convert(source, &buf); err != nil {
panic(err)
}
Parser and Renderer optionsParser options
HTML Renderer options
Built-in extensions
AttributesThe Currently only headings support attributes. Attributes are being discussed in the CommonMark forum. This syntax may possibly change in the future. Headings
Table extensionThe Table extension implements Table(extension), as defined in GitHub Flavored Markdown Spec. Specs are defined for XHTML, so specs use some deprecated attributes for HTML5. You can override alignment rendering method via options.
Typographer extensionThe Typographer extension translates plain ASCII punctuation characters into typographic-punctuation HTML entities. Default substitutions are:
You can override the default substitutions via markdown := goldmark.New(
goldmark.WithExtensions(
extension.NewTypographer(
extension.WithTypographicSubstitutions(extension.TypographicSubstitutions{
extension.LeftSingleQuote: []byte("‚"),
extension.RightSingleQuote: nil, // nil disables a substitution
}),
),
),
) Linkify extensionThe Linkify extension implements Autolinks(extension), as defined in GitHub Flavored Markdown Spec. Since the spec does not define details about URLs, there are numerous ambiguous cases. You can override autolinking patterns via options.
Example, using xurls: import "mvdan.cc/xurls/v2"
markdown := goldmark.New(
goldmark.WithRendererOptions(
html.WithXHTML(),
html.WithUnsafe(),
),
goldmark.WithExtensions(
extension.NewLinkify(
extension.WithLinkifyAllowedProtocols([][]byte{
[]byte("http:"),
[]byte("https:"),
}),
extension.WithLinkifyURLRegexp(
xurls.Strict,
),
),
),
) Footnotes extensionThe Footnote extension implements PHP Markdown Extra: Footnotes. This extension has some options:
Some options can have special substitutions. Occurrences of “^^” in the string will be replaced by the corresponding footnote number in the HTML output. Occurrences of “%%” will be replaced by a number for the reference (footnotes can have multiple references).
for _, path := range files {
source := readAll(path)
prefix := getPrefix(path)
markdown := goldmark.New(
goldmark.WithExtensions(
NewFootnote(
WithFootnoteIDPrefix([]byte(path)),
),
),
)
var b bytes.Buffer
err := markdown.Convert(source, &b)
if err != nil {
t.Error(err.Error())
}
}
markdown := goldmark.New(
goldmark.WithExtensions(
NewFootnote(
WithFootnoteIDPrefixFunction(func(n gast.Node) []byte {
v, ok := n.OwnerDocument().Meta()["footnote-prefix"]
if ok {
return util.StringToReadOnlyBytes(v.(string))
}
return nil
}),
),
),
)
for _, path := range files {
source := readAll(path)
var b bytes.Buffer
doc := markdown.Parser().Parse(text.NewReader(source))
doc.Meta()["footnote-prefix"] = getPrefix(path)
err := markdown.Renderer().Render(&b, source, doc)
} You can use goldmark-meta to define a id prefix in the markdown document: ---
title: document title
slug: article1
footnote-prefix: article1
---
# My article
SecurityBy default, goldmark does not render raw HTML or potentially-dangerous URLs. If you need to gain more control over untrusted contents, it is recommended that you use an HTML sanitizer such as bluemonday. BenchmarkYou can run this benchmark in the against other golang librariesblackfriday v2 seems to be the fastest, but as it is not CommonMark compliant, its performance cannot be directly compared to that of the CommonMark-compliant libraries. goldmark, meanwhile, builds a clean, extensible AST structure, achieves full compliance with CommonMark, and consumes less memory, all while being reasonably fast.
against cmark (CommonMark reference implementation written in C)
As you can see, goldmark's performance is on par with cmark's. Extensions
goldmark internal(for extension developers)Overviewgoldmark's Markdown processing is outlined in the diagram below.
ParsingMarkdown documents are read through AST nodes do not have concrete text. AST nodes have segment information of the documents, represented by
(TBC) TODO See Summary:
DonationBTC: 1NEDSyUmo4SMTDP83JJQSWi1MvQUGGNMZB LicenseMIT AuthorYusuke Inuzuka |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论