mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-04 05:25:15 +01:00 
			
		
		
		
	Change all license headers to comply with REUSE specification. Fix #16132 Co-authored-by: flynnnnnnnnnn <flynnnnnnnnnn@github> Co-authored-by: John Olheiser <john.olheiser@gmail.com>
		
			
				
	
	
		
			93 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			93 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2022 The Gitea Authors. All rights reserved.
 | 
						|
// SPDX-License-Identifier: MIT
 | 
						|
 | 
						|
package vars
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"strings"
 | 
						|
	"unicode"
 | 
						|
	"unicode/utf8"
 | 
						|
)
 | 
						|
 | 
						|
// ErrWrongSyntax represents a wrong syntax with a template
 | 
						|
type ErrWrongSyntax struct {
 | 
						|
	Template string
 | 
						|
}
 | 
						|
 | 
						|
func (err ErrWrongSyntax) Error() string {
 | 
						|
	return fmt.Sprintf("wrong syntax found in %s", err.Template)
 | 
						|
}
 | 
						|
 | 
						|
// ErrVarMissing represents an error that no matched variable
 | 
						|
type ErrVarMissing struct {
 | 
						|
	Template string
 | 
						|
	Var      string
 | 
						|
}
 | 
						|
 | 
						|
func (err ErrVarMissing) Error() string {
 | 
						|
	return fmt.Sprintf("the variable %s is missing for %s", err.Var, err.Template)
 | 
						|
}
 | 
						|
 | 
						|
// Expand replaces all variables like {var} by `vars` map, it always returns the expanded string regardless of errors
 | 
						|
// if error occurs, the error part doesn't change and is returned as it is.
 | 
						|
func Expand(template string, vars map[string]string) (string, error) {
 | 
						|
	// in the future, if necessary, we can introduce some escape-char,
 | 
						|
	// for example: it will use `#' as a reversed char, templates will use `{#{}` to do escape and output char '{'.
 | 
						|
	var buf strings.Builder
 | 
						|
	var err error
 | 
						|
 | 
						|
	posBegin := 0
 | 
						|
	strLen := len(template)
 | 
						|
	for posBegin < strLen {
 | 
						|
		// find the next `{`
 | 
						|
		pos := strings.IndexByte(template[posBegin:], '{')
 | 
						|
		if pos == -1 {
 | 
						|
			buf.WriteString(template[posBegin:])
 | 
						|
			break
 | 
						|
		}
 | 
						|
 | 
						|
		// copy texts between vars
 | 
						|
		buf.WriteString(template[posBegin : posBegin+pos])
 | 
						|
 | 
						|
		// find the var between `{` and `}`/end
 | 
						|
		posBegin += pos
 | 
						|
		posEnd := posBegin + 1
 | 
						|
		for posEnd < strLen {
 | 
						|
			if template[posEnd] == '}' {
 | 
						|
				posEnd++
 | 
						|
				break
 | 
						|
			} // in the future, if we need to support escape chars, we can do: if (isEscapeChar) { posEnd+=2 }
 | 
						|
			posEnd++
 | 
						|
		}
 | 
						|
 | 
						|
		// the var part, it can be "{", "{}", "{..." or or "{...}"
 | 
						|
		part := template[posBegin:posEnd]
 | 
						|
		posBegin = posEnd
 | 
						|
		if part == "{}" || part[len(part)-1] != '}' {
 | 
						|
			// treat "{}" or "{..." as error
 | 
						|
			err = ErrWrongSyntax{Template: template}
 | 
						|
			buf.WriteString(part)
 | 
						|
		} else {
 | 
						|
			// now we get a valid key "{...}"
 | 
						|
			key := part[1 : len(part)-1]
 | 
						|
			keyFirst, _ := utf8.DecodeRuneInString(key)
 | 
						|
			if unicode.IsSpace(keyFirst) || unicode.IsPunct(keyFirst) || unicode.IsControl(keyFirst) {
 | 
						|
				// the if key doesn't start with a letter, then we do not treat it as a var now
 | 
						|
				buf.WriteString(part)
 | 
						|
			} else {
 | 
						|
				// look up in the map
 | 
						|
				if val, ok := vars[key]; ok {
 | 
						|
					buf.WriteString(val)
 | 
						|
				} else {
 | 
						|
					// write the non-existing var as it is
 | 
						|
					buf.WriteString(part)
 | 
						|
					err = ErrVarMissing{Template: template, Var: key}
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return buf.String(), err
 | 
						|
}
 |