Compare commits

...

7 commits

Author SHA1 Message Date
Yusuke Inuzuka
04410ff159
Merge pull request #487 from n-peugnet/patch-1
Fix GitHub actions badge URL
2025-02-19 03:38:00 +09:00
Yusuke Inuzuka
f7b2d24c09
Merge pull request #489 from lyricat/master
chore: update `goldmark-enclave` repo URL and information
2025-02-19 03:37:26 +09:00
Lyric Wai
ba49c5c69d
Merge pull request #1 from lyricat/lyricat-patch-enclave
Update README.md
2025-02-18 23:34:09 +09:00
Lyric Wai
c05fb087a4
Update README.md
Update `goldmark-enclave` url and information
2025-02-18 23:33:14 +09:00
Nicolas Peugnet
b39daae79e
Fix GitHub actions badge URL 2025-02-02 15:58:36 +01:00
yuin
d9c03f07f0 Deprecate Node.Text
Node.Text was intended to get a text value from some inline nodes.
A 'text value' of a Text node is clear.

But

- BaseNode had a default implementation of Node.Text
- Lacks of GoDoc description that Node.Text is valid only for
  some inline nodes

So, some users are using Node.Text for BlockNodes.

A 'text value' for a BlockNode is not clear.

e.g. : Text value of a ListNode

- It should be contains list markers?
- What do characters concatinate List items with? newlines? spaces?
- If it contains codeblocks, codeblocks should be fenced or indented?

Now we would like to avoid such ambiguous method.
2024-10-16 20:47:35 +09:00
yuin
65dcf6cd0a Add warning to Node.Text GoDoc 2024-10-15 19:22:00 +09:00
7 changed files with 67 additions and 30 deletions

View file

@ -2,7 +2,7 @@ goldmark
========================================== ==========================================
[![https://pkg.go.dev/github.com/yuin/goldmark](https://pkg.go.dev/badge/github.com/yuin/goldmark.svg)](https://pkg.go.dev/github.com/yuin/goldmark) [![https://pkg.go.dev/github.com/yuin/goldmark](https://pkg.go.dev/badge/github.com/yuin/goldmark.svg)](https://pkg.go.dev/github.com/yuin/goldmark)
[![https://github.com/yuin/goldmark/actions?query=workflow:test](https://github.com/yuin/goldmark/workflows/test/badge.svg?branch=master&event=push)](https://github.com/yuin/goldmark/actions?query=workflow:test) [![https://github.com/yuin/goldmark/actions?query=workflow:test](https://github.com/yuin/goldmark/actions/workflows/test.yaml/badge.svg?branch=master&event=push)](https://github.com/yuin/goldmark/actions?query=workflow:test)
[![https://coveralls.io/github/yuin/goldmark](https://coveralls.io/repos/github/yuin/goldmark/badge.svg?branch=master)](https://coveralls.io/github/yuin/goldmark) [![https://coveralls.io/github/yuin/goldmark](https://coveralls.io/repos/github/yuin/goldmark/badge.svg?branch=master)](https://coveralls.io/github/yuin/goldmark)
[![https://goreportcard.com/report/github.com/yuin/goldmark](https://goreportcard.com/badge/github.com/yuin/goldmark)](https://goreportcard.com/report/github.com/yuin/goldmark) [![https://goreportcard.com/report/github.com/yuin/goldmark](https://goreportcard.com/badge/github.com/yuin/goldmark)](https://goreportcard.com/report/github.com/yuin/goldmark)
@ -493,7 +493,7 @@ Extensions
- [goldmark-d2](https://github.com/FurqanSoftware/goldmark-d2): Adds support for [D2](https://d2lang.com/) diagrams. - [goldmark-d2](https://github.com/FurqanSoftware/goldmark-d2): Adds support for [D2](https://d2lang.com/) diagrams.
- [goldmark-katex](https://github.com/FurqanSoftware/goldmark-katex): Adds support for [KaTeX](https://katex.org/) math and equations. - [goldmark-katex](https://github.com/FurqanSoftware/goldmark-katex): Adds support for [KaTeX](https://katex.org/) math and equations.
- [goldmark-img64](https://github.com/tenkoh/goldmark-img64): Adds support for embedding images into the document as DataURL (base64 encoded). - [goldmark-img64](https://github.com/tenkoh/goldmark-img64): Adds support for embedding images into the document as DataURL (base64 encoded).
- [goldmark-enclave](https://github.com/quail-ink/goldmark-enclave): Adds support for embedding youtube/bilibili video, X's [oembed tweet](https://publish.twitter.com/), [tradingview](https://www.tradingview.com/widget/)'s chart, [quail](https://quail.ink)'s widget into the document. - [goldmark-enclave](https://github.com/quailyquaily/goldmark-enclave): Adds support for embedding youtube/bilibili video, X's [oembed X](https://publish.x.com/), [tradingview chart](https://www.tradingview.com/widget/)'s chart, [quaily widget](https://quaily.com), [spotify embeds](https://developer.spotify.com/documentation/embeds), [dify embed](https://dify.ai/) and html audio into the document.
- [goldmark-wiki-table](https://github.com/movsb/goldmark-wiki-table): Adds support for embedding Wiki Tables. - [goldmark-wiki-table](https://github.com/movsb/goldmark-wiki-table): Adds support for embedding Wiki Tables.
- [goldmark-tgmd](https://github.com/Mad-Pixels/goldmark-tgmd): A Telegram markdown renderer that can be passed to `goldmark.WithRenderer()`. - [goldmark-tgmd](https://github.com/Mad-Pixels/goldmark-tgmd): A Telegram markdown renderer that can be passed to `goldmark.WithRenderer()`.

View file

@ -123,6 +123,12 @@ type Node interface {
Dump(source []byte, level int) Dump(source []byte, level int)
// Text returns text values of this node. // Text returns text values of this node.
// This method is valid only for some inline nodes.
// If this node is a block node, Text returns a text value as reasonable as possible.
// Notice that there are no 'correct' text values for the block nodes.
// Result for the block nodes may be different from your expectation.
//
// Deprecated: Use other properties of the node to get the text value(i.e. Pragraph.Lines, Text.Value).
Text(source []byte) []byte Text(source []byte) []byte
// HasBlankPreviousLines returns true if the row before this node is blank, // HasBlankPreviousLines returns true if the row before this node is blank,
@ -374,7 +380,9 @@ func (n *BaseNode) OwnerDocument() *Document {
return nil return nil
} }
// Text implements Node.Text . // Text implements Node.Text .
//
// Deprecated: Use other properties of the node to get the text value(i.e. Pragraph.Lines, Text.Value).
func (n *BaseNode) Text(source []byte) []byte { func (n *BaseNode) Text(source []byte) []byte {
var buf bytes.Buffer var buf bytes.Buffer
for c := n.firstChild; c != nil; c = c.NextSibling() { for c := n.firstChild; c != nil; c = c.NextSibling() {

View file

@ -131,6 +131,8 @@ func (n *TextBlock) Kind() NodeKind {
} }
// Text implements Node.Text. // Text implements Node.Text.
//
// Deprecated: Use other properties of the node to get the text value(i.e. TextBlock.Lines).
func (n *TextBlock) Text(source []byte) []byte { func (n *TextBlock) Text(source []byte) []byte {
return n.Lines().Value(source) return n.Lines().Value(source)
} }
@ -161,6 +163,8 @@ func (n *Paragraph) Kind() NodeKind {
} }
// Text implements Node.Text. // Text implements Node.Text.
//
// Deprecated: Use other properties of the node to get the text value(i.e. Paragraph.Lines).
func (n *Paragraph) Text(source []byte) []byte { func (n *Paragraph) Text(source []byte) []byte {
return n.Lines().Value(source) return n.Lines().Value(source)
} }
@ -260,6 +264,8 @@ func (n *CodeBlock) Kind() NodeKind {
} }
// Text implements Node.Text. // Text implements Node.Text.
//
// Deprecated: Use other properties of the node to get the text value(i.e. CodeBlock.Lines).
func (n *CodeBlock) Text(source []byte) []byte { func (n *CodeBlock) Text(source []byte) []byte {
return n.Lines().Value(source) return n.Lines().Value(source)
} }
@ -320,6 +326,8 @@ func (n *FencedCodeBlock) Kind() NodeKind {
} }
// Text implements Node.Text. // Text implements Node.Text.
//
// Deprecated: Use other properties of the node to get the text value(i.e. FencedCodeBlock.Lines).
func (n *FencedCodeBlock) Text(source []byte) []byte { func (n *FencedCodeBlock) Text(source []byte) []byte {
return n.Lines().Value(source) return n.Lines().Value(source)
} }
@ -519,6 +527,8 @@ func (n *HTMLBlock) Kind() NodeKind {
} }
// Text implements Node.Text. // Text implements Node.Text.
//
// Deprecated: Use other properties of the node to get the text value(i.e. HTMLBlock.Lines).
func (n *HTMLBlock) Text(source []byte) []byte { func (n *HTMLBlock) Text(source []byte) []byte {
ret := n.Lines().Value(source) ret := n.Lines().Value(source)
if n.HasClosure() { if n.HasClosure() {

View file

@ -143,17 +143,25 @@ func (n *Text) Merge(node Node, source []byte) bool {
} }
// Text implements Node.Text. // Text implements Node.Text.
//
// Deprecated: Use other properties of the node to get the text value(i.e. Text.Value).
func (n *Text) Text(source []byte) []byte { func (n *Text) Text(source []byte) []byte {
return n.Segment.Value(source) return n.Segment.Value(source)
} }
// Value returns a value of this node.
// SoftLineBreaks are not included in the returned value.
func (n *Text) Value(source []byte) []byte {
return n.Segment.Value(source)
}
// Dump implements Node.Dump. // Dump implements Node.Dump.
func (n *Text) Dump(source []byte, level int) { func (n *Text) Dump(source []byte, level int) {
fs := textFlagsString(n.flags) fs := textFlagsString(n.flags)
if len(fs) != 0 { if len(fs) != 0 {
fs = "(" + fs + ")" fs = "(" + fs + ")"
} }
fmt.Printf("%sText%s: \"%s\"\n", strings.Repeat(" ", level), fs, strings.TrimRight(string(n.Text(source)), "\n")) fmt.Printf("%sText%s: \"%s\"\n", strings.Repeat(" ", level), fs, strings.TrimRight(string(n.Value(source)), "\n"))
} }
// KindText is a NodeKind of the Text node. // KindText is a NodeKind of the Text node.
@ -258,6 +266,8 @@ func (n *String) SetCode(v bool) {
} }
// Text implements Node.Text. // Text implements Node.Text.
//
// Deprecated: Use other properties of the node to get the text value(i.e. String.Value).
func (n *String) Text(source []byte) []byte { func (n *String) Text(source []byte) []byte {
return n.Value return n.Value
} }
@ -492,20 +502,22 @@ func (n *AutoLink) URL(source []byte) []byte {
ret := make([]byte, 0, len(n.Protocol)+s.Len()+3) ret := make([]byte, 0, len(n.Protocol)+s.Len()+3)
ret = append(ret, n.Protocol...) ret = append(ret, n.Protocol...)
ret = append(ret, ':', '/', '/') ret = append(ret, ':', '/', '/')
ret = append(ret, n.value.Text(source)...) ret = append(ret, n.value.Value(source)...)
return ret return ret
} }
return n.value.Text(source) return n.value.Value(source)
} }
// Label returns a label of this node. // Label returns a label of this node.
func (n *AutoLink) Label(source []byte) []byte { func (n *AutoLink) Label(source []byte) []byte {
return n.value.Text(source) return n.value.Value(source)
} }
// Text implements Node.Text. // Text implements Node.Text.
//
// Deprecated: Use other properties of the node to get the text value(i.e. AutoLink.Label).
func (n *AutoLink) Text(source []byte) []byte { func (n *AutoLink) Text(source []byte) []byte {
return n.value.Text(source) return n.value.Value(source)
} }
// NewAutoLink returns a new AutoLink node. // NewAutoLink returns a new AutoLink node.
@ -547,6 +559,8 @@ func (n *RawHTML) Kind() NodeKind {
} }
// Text implements Node.Text. // Text implements Node.Text.
//
// Deprecated: Use other properties of the node to get the text value(i.e. RawHTML.Segments).
func (n *RawHTML) Text(source []byte) []byte { func (n *RawHTML) Text(source []byte) []byte {
return n.Segments.Value(source) return n.Segments.Value(source)
} }

View file

@ -141,11 +141,15 @@ l4`,
c1 = c1.FirstChild() c1 = c1.FirstChild()
c2 = c2.FirstChild() c2 = c2.FirstChild()
} }
if !bytes.Equal(c1.Text(s), []byte(cs.T1)) { if !bytes.Equal(c1.Text(s), []byte(cs.T1)) { // nolint: staticcheck
t.Errorf("%s unmatch: %s", cs.Name, testutil.DiffPretty(c1.Text(s), []byte(cs.T1)))
t.Errorf("%s unmatch: %s", cs.Name, testutil.DiffPretty(c1.Text(s), []byte(cs.T1))) // nolint: staticcheck
} }
if !bytes.Equal(c2.Text(s), []byte(cs.T2)) { if !bytes.Equal(c2.Text(s), []byte(cs.T2)) { // nolint: staticcheck
t.Errorf("%s(EOF) unmatch: %s", cs.Name, testutil.DiffPretty(c2.Text(s), []byte(cs.T2)))
t.Errorf("%s(EOF) unmatch: %s", cs.Name, testutil.DiffPretty(c2.Text(s), []byte(cs.T2))) // nolint: staticcheck
} }
}) })
} }
@ -191,8 +195,8 @@ func TestASTInlineNodeText(t *testing.T) {
md := New() md := New()
n := md.Parser().Parse(text.NewReader(s)) n := md.Parser().Parse(text.NewReader(s))
c1 := n.FirstChild().FirstChild() c1 := n.FirstChild().FirstChild()
if !bytes.Equal(c1.Text(s), []byte(cs.T1)) { if !bytes.Equal(c1.Text(s), []byte(cs.T1)) { // nolint: staticcheck
t.Errorf("%s unmatch:\n%s", cs.Name, testutil.DiffPretty(c1.Text(s), []byte(cs.T1))) t.Errorf("%s unmatch:\n%s", cs.Name, testutil.DiffPretty(c1.Text(s), []byte(cs.T1))) // nolint: staticcheck
} }
}) })
} }

View file

@ -71,11 +71,15 @@ a
c1 = c1.FirstChild() c1 = c1.FirstChild()
c2 = c2.FirstChild() c2 = c2.FirstChild()
} }
if !bytes.Equal(c1.Text(s), []byte(cs.T1)) { if !bytes.Equal(c1.Text(s), []byte(cs.T1)) { // nolint: staticcheck
t.Errorf("%s unmatch:\n%s", cs.Name, testutil.DiffPretty(c1.Text(s), []byte(cs.T1)))
t.Errorf("%s unmatch:\n%s", cs.Name, testutil.DiffPretty(c1.Text(s), []byte(cs.T1))) // nolint: staticcheck
} }
if !bytes.Equal(c2.Text(s), []byte(cs.T2)) { if !bytes.Equal(c2.Text(s), []byte(cs.T2)) { // nolint: staticcheck
t.Errorf("%s(EOF) unmatch: %s", cs.Name, testutil.DiffPretty(c2.Text(s), []byte(cs.T2)))
t.Errorf("%s(EOF) unmatch: %s", cs.Name, testutil.DiffPretty(c2.Text(s), []byte(cs.T2))) // nolint: staticcheck
} }
}) })
} }
@ -108,8 +112,10 @@ func TestASTInlineNodeText(t *testing.T) {
) )
n := md.Parser().Parse(text.NewReader(s)) n := md.Parser().Parse(text.NewReader(s))
c1 := n.FirstChild().FirstChild() c1 := n.FirstChild().FirstChild()
if !bytes.Equal(c1.Text(s), []byte(cs.T1)) { if !bytes.Equal(c1.Text(s), []byte(cs.T1)) { // nolint: staticcheck
t.Errorf("%s unmatch:\n%s", cs.Name, testutil.DiffPretty(c1.Text(s), []byte(cs.T1)))
t.Errorf("%s unmatch:\n%s", cs.Name, testutil.DiffPretty(c1.Text(s), []byte(cs.T1))) // nolint: staticcheck
} }
}) })
} }

View file

@ -680,7 +680,7 @@ func (r *Renderer) renderImage(w util.BufWriter, source []byte, node ast.Node, e
_, _ = w.Write(util.EscapeHTML(util.URLEscape(n.Destination, true))) _, _ = w.Write(util.EscapeHTML(util.URLEscape(n.Destination, true)))
} }
_, _ = w.WriteString(`" alt="`) _, _ = w.WriteString(`" alt="`)
r.renderAttribute(w, source, n) r.renderTexts(w, source, n)
_ = w.WriteByte('"') _ = w.WriteByte('"')
if n.Title != nil { if n.Title != nil {
_, _ = w.WriteString(` title="`) _, _ = w.WriteString(` title="`)
@ -737,7 +737,7 @@ func (r *Renderer) renderText(w util.BufWriter, source []byte, node ast.Node, en
if r.EastAsianLineBreaks != EastAsianLineBreaksNone && len(value) != 0 { if r.EastAsianLineBreaks != EastAsianLineBreaksNone && len(value) != 0 {
sibling := node.NextSibling() sibling := node.NextSibling()
if sibling != nil && sibling.Kind() == ast.KindText { if sibling != nil && sibling.Kind() == ast.KindText {
if siblingText := sibling.(*ast.Text).Text(source); len(siblingText) != 0 { if siblingText := sibling.(*ast.Text).Value(source); len(siblingText) != 0 {
thisLastRune := util.ToRune(value, len(value)-1) thisLastRune := util.ToRune(value, len(value)-1)
siblingFirstRune, _ := utf8.DecodeRune(siblingText) siblingFirstRune, _ := utf8.DecodeRune(siblingText)
if r.EastAsianLineBreaks.softLineBreak(thisLastRune, siblingFirstRune) { if r.EastAsianLineBreaks.softLineBreak(thisLastRune, siblingFirstRune) {
@ -770,19 +770,14 @@ func (r *Renderer) renderString(w util.BufWriter, source []byte, node ast.Node,
return ast.WalkContinue, nil return ast.WalkContinue, nil
} }
func (r *Renderer) renderAttribute(w util.BufWriter, source []byte, n ast.Node) { func (r *Renderer) renderTexts(w util.BufWriter, source []byte, n ast.Node) {
for c := n.FirstChild(); c != nil; c = c.NextSibling() { for c := n.FirstChild(); c != nil; c = c.NextSibling() {
if s, ok := c.(*ast.String); ok { if s, ok := c.(*ast.String); ok {
_, _ = r.renderString(w, source, s, true) _, _ = r.renderString(w, source, s, true)
} else if t, ok := c.(*ast.String); ok { } else if t, ok := c.(*ast.Text); ok {
_, _ = r.renderText(w, source, t, true) _, _ = r.renderText(w, source, t, true)
} else if !c.HasChildren() {
r.Writer.Write(w, c.Text(source))
if t, ok := c.(*ast.Text); ok && t.SoftLineBreak() {
_ = w.WriteByte('\n')
}
} else { } else {
r.renderAttribute(w, source, c) r.renderTexts(w, source, c)
} }
} }
} }