go-twig/whitespace.go
semihalev b44bad903b Implement spaceless filter and apply tag
1. Added spaceless filter that removes whitespace between HTML tags
2. Implemented {% apply filter %} ... {% endapply %} tag
3. Updated spaceless tag to use the spaceless filter internally
4. Fixed endverbatim tag handling
5. Added tests for all new functionality

The apply tag allows applying filters to blocks of content, which is the
modern recommended approach in Twig, replacing the deprecated spaceless tag.

🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-03-11 17:28:57 +03:00

69 lines
1.6 KiB
Go

package twig
import (
"bytes"
"io"
"strings"
)
// trimLeadingWhitespace removes leading whitespace from a string
// This is only used for whitespace control in templates ({{- and -}})
func trimLeadingWhitespace(s string) string {
return strings.TrimLeft(s, " \t\n\r")
}
// trimTrailingWhitespace removes trailing whitespace from a string
// This is only used for whitespace control in templates ({{- and -}})
func trimTrailingWhitespace(s string) string {
return strings.TrimRight(s, " \t\n\r")
}
// SpacelessNode represents a {% spaceless %} ... {% endspaceless %} block
type SpacelessNode struct {
body []Node
line int
}
// NewSpacelessNode creates a new spaceless node
func NewSpacelessNode(body []Node, line int) *SpacelessNode {
return &SpacelessNode{
body: body,
line: line,
}
}
// Render renders the node to a writer
func (n *SpacelessNode) Render(w io.Writer, ctx *RenderContext) error {
// First render body content to a buffer
var buf bytes.Buffer
// Render all body nodes
for _, node := range n.body {
err := node.Render(&buf, ctx)
if err != nil {
return err
}
}
// Apply spaceless filter to the rendered content
result, err := ctx.ApplyFilter("spaceless", buf.String())
if err != nil {
// Fall back to original content on filter error
_, err = w.Write(buf.Bytes())
return err
}
// Write the processed result
_, err = WriteString(w, ctx.ToString(result))
return err
}
// Line returns the line number of the node
func (n *SpacelessNode) Line() int {
return n.line
}
// Type returns the node type
func (n *SpacelessNode) Type() NodeType {
return NodeSpaceless
}