From d9c03f07f08c2d36f23afe52dda865f05320ac86 Mon Sep 17 00:00:00 2001 From: yuin Date: Wed, 16 Oct 2024 20:47:30 +0900 Subject: [PATCH] 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. --- ast/ast.go | 6 +++++- ast/block.go | 10 ++++++++++ ast/inline.go | 24 +++++++++++++++++++----- ast_test.go | 16 ++++++++++------ extension/ast_test.go | 18 ++++++++++++------ renderer/html/html.go | 15 +++++---------- 6 files changed, 61 insertions(+), 28 deletions(-) diff --git a/ast/ast.go b/ast/ast.go index 8bc38e6..36ba606 100644 --- a/ast/ast.go +++ b/ast/ast.go @@ -127,6 +127,8 @@ type Node interface { // 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 // HasBlankPreviousLines returns true if the row before this node is blank, @@ -378,7 +380,9 @@ func (n *BaseNode) OwnerDocument() *Document { 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 { var buf bytes.Buffer for c := n.firstChild; c != nil; c = c.NextSibling() { diff --git a/ast/block.go b/ast/block.go index 467819e..eae7acd 100644 --- a/ast/block.go +++ b/ast/block.go @@ -131,6 +131,8 @@ func (n *TextBlock) Kind() NodeKind { } // 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 { return n.Lines().Value(source) } @@ -161,6 +163,8 @@ func (n *Paragraph) Kind() NodeKind { } // 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 { return n.Lines().Value(source) } @@ -260,6 +264,8 @@ func (n *CodeBlock) Kind() NodeKind { } // 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 { return n.Lines().Value(source) } @@ -320,6 +326,8 @@ func (n *FencedCodeBlock) Kind() NodeKind { } // 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 { return n.Lines().Value(source) } @@ -519,6 +527,8 @@ func (n *HTMLBlock) Kind() NodeKind { } // 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 { ret := n.Lines().Value(source) if n.HasClosure() { diff --git a/ast/inline.go b/ast/inline.go index 9df8470..613eb1e 100644 --- a/ast/inline.go +++ b/ast/inline.go @@ -143,17 +143,25 @@ func (n *Text) Merge(node Node, source []byte) bool { } // 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 { 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. func (n *Text) Dump(source []byte, level int) { fs := textFlagsString(n.flags) if len(fs) != 0 { 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. @@ -258,6 +266,8 @@ func (n *String) SetCode(v bool) { } // 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 { 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 = append(ret, n.Protocol...) ret = append(ret, ':', '/', '/') - ret = append(ret, n.value.Text(source)...) + ret = append(ret, n.value.Value(source)...) return ret } - return n.value.Text(source) + return n.value.Value(source) } // Label returns a label of this node. func (n *AutoLink) Label(source []byte) []byte { - return n.value.Text(source) + return n.value.Value(source) } // 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 { - return n.value.Text(source) + return n.value.Value(source) } // NewAutoLink returns a new AutoLink node. @@ -547,6 +559,8 @@ func (n *RawHTML) Kind() NodeKind { } // 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 { return n.Segments.Value(source) } diff --git a/ast_test.go b/ast_test.go index e5e6016..0fcb3c8 100644 --- a/ast_test.go +++ b/ast_test.go @@ -141,11 +141,15 @@ l4`, c1 = c1.FirstChild() c2 = c2.FirstChild() } - if !bytes.Equal(c1.Text(s), []byte(cs.T1)) { - t.Errorf("%s unmatch: %s", cs.Name, testutil.DiffPretty(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))) // nolint: staticcheck + } - if !bytes.Equal(c2.Text(s), []byte(cs.T2)) { - t.Errorf("%s(EOF) unmatch: %s", cs.Name, testutil.DiffPretty(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))) // nolint: staticcheck + } }) } @@ -191,8 +195,8 @@ func TestASTInlineNodeText(t *testing.T) { md := New() n := md.Parser().Parse(text.NewReader(s)) c1 := n.FirstChild().FirstChild() - if !bytes.Equal(c1.Text(s), []byte(cs.T1)) { - t.Errorf("%s unmatch:\n%s", cs.Name, testutil.DiffPretty(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))) // nolint: staticcheck } }) } diff --git a/extension/ast_test.go b/extension/ast_test.go index e0c24b1..8fb4039 100644 --- a/extension/ast_test.go +++ b/extension/ast_test.go @@ -71,11 +71,15 @@ a c1 = c1.FirstChild() c2 = c2.FirstChild() } - if !bytes.Equal(c1.Text(s), []byte(cs.T1)) { - t.Errorf("%s unmatch:\n%s", cs.Name, testutil.DiffPretty(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))) // nolint: staticcheck + } - if !bytes.Equal(c2.Text(s), []byte(cs.T2)) { - t.Errorf("%s(EOF) unmatch: %s", cs.Name, testutil.DiffPretty(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))) // nolint: staticcheck + } }) } @@ -108,8 +112,10 @@ func TestASTInlineNodeText(t *testing.T) { ) n := md.Parser().Parse(text.NewReader(s)) c1 := n.FirstChild().FirstChild() - if !bytes.Equal(c1.Text(s), []byte(cs.T1)) { - t.Errorf("%s unmatch:\n%s", cs.Name, testutil.DiffPretty(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))) // nolint: staticcheck + } }) } diff --git a/renderer/html/html.go b/renderer/html/html.go index 9ebd0a3..aac8d2d 100644 --- a/renderer/html/html.go +++ b/renderer/html/html.go @@ -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.WriteString(`" alt="`) - r.renderAttribute(w, source, n) + r.renderTexts(w, source, n) _ = w.WriteByte('"') if n.Title != nil { _, _ = 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 { sibling := node.NextSibling() 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) siblingFirstRune, _ := utf8.DecodeRune(siblingText) 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 } -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() { if s, ok := c.(*ast.String); ok { _, _ = 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) - } else if !c.HasChildren() { - r.Writer.Write(w, c.Text(source)) - if t, ok := c.(*ast.Text); ok && t.SoftLineBreak() { - _ = w.WriteByte('\n') - } } else { - r.renderAttribute(w, source, c) + r.renderTexts(w, source, c) } } }