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 }