mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 16:40:24 +08:00 
			
		
		
		
	Refactor backend SVG package and add tests (#26335)
Introduce a well-tested `svg.Normalize` function. Make `RenderHTML` faster and more stable.
This commit is contained in:
		
							
								
								
									
										59
									
								
								modules/svg/processor.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								modules/svg/processor.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,59 @@
 | 
			
		||||
// Copyright 2023 The Gitea Authors. All rights reserved.
 | 
			
		||||
// SPDX-License-Identifier: MIT
 | 
			
		||||
 | 
			
		||||
package svg
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"sync"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type normalizeVarsStruct struct {
 | 
			
		||||
	reXMLDoc,
 | 
			
		||||
	reComment,
 | 
			
		||||
	reAttrXMLNs,
 | 
			
		||||
	reAttrSize,
 | 
			
		||||
	reAttrClassPrefix *regexp.Regexp
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	normalizeVars     *normalizeVarsStruct
 | 
			
		||||
	normalizeVarsOnce sync.Once
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Normalize normalizes the SVG content: set default width/height, remove unnecessary tags/attributes
 | 
			
		||||
// It's designed to work with valid SVG content. For invalid SVG content, the returned content is not guaranteed.
 | 
			
		||||
func Normalize(data []byte, size int) []byte {
 | 
			
		||||
	normalizeVarsOnce.Do(func() {
 | 
			
		||||
		normalizeVars = &normalizeVarsStruct{
 | 
			
		||||
			reXMLDoc:  regexp.MustCompile(`(?s)<\?xml.*?>`),
 | 
			
		||||
			reComment: regexp.MustCompile(`(?s)<!--.*?-->`),
 | 
			
		||||
 | 
			
		||||
			reAttrXMLNs:       regexp.MustCompile(`(?s)\s+xmlns\s*=\s*"[^"]*"`),
 | 
			
		||||
			reAttrSize:        regexp.MustCompile(`(?s)\s+(width|height)\s*=\s*"[^"]+"`),
 | 
			
		||||
			reAttrClassPrefix: regexp.MustCompile(`(?s)\s+class\s*=\s*"`),
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
	data = normalizeVars.reXMLDoc.ReplaceAll(data, nil)
 | 
			
		||||
	data = normalizeVars.reComment.ReplaceAll(data, nil)
 | 
			
		||||
 | 
			
		||||
	data = bytes.TrimSpace(data)
 | 
			
		||||
	svgTag, svgRemaining, ok := bytes.Cut(data, []byte(">"))
 | 
			
		||||
	if !ok || !bytes.HasPrefix(svgTag, []byte(`<svg`)) {
 | 
			
		||||
		return data
 | 
			
		||||
	}
 | 
			
		||||
	normalized := bytes.Clone(svgTag)
 | 
			
		||||
	normalized = normalizeVars.reAttrXMLNs.ReplaceAll(normalized, nil)
 | 
			
		||||
	normalized = normalizeVars.reAttrSize.ReplaceAll(normalized, nil)
 | 
			
		||||
	normalized = normalizeVars.reAttrClassPrefix.ReplaceAll(normalized, []byte(` class="`))
 | 
			
		||||
	normalized = bytes.TrimSpace(normalized)
 | 
			
		||||
	normalized = fmt.Appendf(normalized, ` width="%d" height="%d"`, size, size)
 | 
			
		||||
	if !bytes.Contains(normalized, []byte(` class="`)) {
 | 
			
		||||
		normalized = append(normalized, ` class="svg"`...)
 | 
			
		||||
	}
 | 
			
		||||
	normalized = append(normalized, '>')
 | 
			
		||||
	normalized = append(normalized, svgRemaining...)
 | 
			
		||||
	return normalized
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user