github.com/goplus/yap@v0.8.1/internal/templ/template.go (about)

     1  /*
     2   * Copyright (c) 2023 The GoPlus Authors (goplus.org). All rights reserved.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package templ
    18  
    19  import (
    20  	"strings"
    21  )
    22  
    23  func Translate(text string) string {
    24  	var b strings.Builder
    25  	if TranslateEx(&b, text, "{{", "}}") {
    26  		return b.String()
    27  	}
    28  	return text
    29  }
    30  
    31  type iBuilder interface {
    32  	Grow(n int)
    33  	WriteString(s string) (int, error)
    34  	String() string
    35  }
    36  
    37  func TranslateEx[Builder iBuilder](b Builder, text, delimLeft, delimRight string) bool {
    38  	offs := make([]int, 0, 16)
    39  	base := 0
    40  	for {
    41  		pos := strings.Index(text[base:], delimLeft)
    42  		if pos < 0 {
    43  			break
    44  		}
    45  		begin := base + pos + 2 // script begin
    46  		n := strings.Index(text[begin:], delimRight)
    47  		if n < 0 {
    48  			n = len(text) - begin // script length
    49  		}
    50  		base = begin + n
    51  		code := text[begin:base]
    52  		nonBlank := false
    53  		for i := 0; i < n; i++ {
    54  			c := code[i]
    55  			if !isSpace(c) {
    56  				nonBlank = true
    57  			} else if c == '\n' && nonBlank {
    58  				off := begin + i
    59  				if i, nonBlank = findScript(code, i+1, n); !nonBlank {
    60  					break // script not found
    61  				}
    62  				offs = append(offs, off) // insert }}{{
    63  			}
    64  		}
    65  	}
    66  	n := len(offs)
    67  	if n == 0 {
    68  		return false
    69  	}
    70  	b.Grow(len(text) + n*4)
    71  	base = 0
    72  	delimRightLeft := delimRight + delimLeft
    73  	for i := 0; i < n; i++ {
    74  		off := offs[i]
    75  		b.WriteString(text[base:off])
    76  		b.WriteString(delimRightLeft)
    77  		base = off
    78  	}
    79  	b.WriteString(text[base:])
    80  	return true
    81  }
    82  
    83  func isSpace(c byte) bool {
    84  	switch c {
    85  	case ' ', '\t', '\n', '\v', '\f', '\r', 0x85, 0xA0:
    86  		return true
    87  	}
    88  	return false
    89  }
    90  
    91  func findScript(code string, i, n int) (int, bool) {
    92  	for i < n {
    93  		if !isSpace(code[i]) {
    94  			return i, true
    95  		}
    96  		i++
    97  	}
    98  	return -1, false
    99  }