Skip to content

Commit

Permalink
internal/htmltempl
Browse files Browse the repository at this point in the history
  • Loading branch information
xushiwei committed Mar 12, 2024
1 parent fa12101 commit db43ff2
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 187 deletions.
5 changes: 4 additions & 1 deletion demo/classfile_nestetemplate/gop_autogen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

75 changes: 75 additions & 0 deletions internal/htmltempl/template.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright (c) 2023 The GoPlus Authors (goplus.org). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package htmltempl

import (
"bytes"
"fmt"
"html/template"
"io/fs"
"log"
"path"
"strings"
_ "unsafe"

"github.com/goplus/yap/internal/templ"
)

// Template is the representation of a parsed template. The *parse.Tree
// field is exported only for use by html/template and should be treated
// as unexported by all other clients.
type Template struct {
*template.Template
}

func (p *Template) InitTemplates(fsys fs.FS, delimLeft, delimRight, suffix string) {
tpl, err := parseFS(fsys, delimLeft, delimRight, suffix)
if err != nil {
log.Panicln(err)
}
p.Template = tpl
}

//go:linkname parseFiles html/template.parseFiles
func parseFiles(t *template.Template, readFile func(string) (string, []byte, error), filenames ...string) (*template.Template, error)

func parseFS(fsys fs.FS, delimLeft, delimRight, suffix string) (*template.Template, error) {
pattern := "*" + suffix
filenames, err := fs.Glob(fsys, pattern)
if err != nil {
return nil, err
}
if len(filenames) == 0 {
return nil, fmt.Errorf("template: pattern matches no files: %#q", pattern)
}
t := template.New("").Delims(delimLeft, delimRight)
return parseFiles(t, readFileFS(fsys, delimLeft, delimRight, suffix), filenames...)
}

func readFileFS(fsys fs.FS, delimLeft, delimRight, suffix string) func(string) (string, []byte, error) {
return func(file string) (name string, b []byte, err error) {
name = strings.TrimSuffix(path.Base(file), suffix)
if b, err = fs.ReadFile(fsys, file); err != nil {
return
}
var buf bytes.Buffer
if templ.TranslateEx(&buf, string(b), delimLeft, delimRight) {
b = buf.Bytes()
}
return
}
}
32 changes: 26 additions & 6 deletions internal/templ/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,35 @@ import (
)

func Translate(text string) string {
var b strings.Builder
if TranslateEx(&b, text, "{{", "}}") {
return b.String()
}
return text
}

type iBuilder interface {
Grow(n int)
WriteString(s string) (int, error)
String() string
}

func TranslateEx[Builder iBuilder](b Builder, text, delimLeft, delimRight string) bool {
offs := make([]int, 0, 16)
base := 0
if delimLeft == "" {
delimLeft = "{{"
}
if delimRight == "" {
delimRight = "}}"
}
for {
pos := strings.Index(text[base:], "{{")
pos := strings.Index(text[base:], delimLeft)
if pos < 0 {
break
}
begin := base + pos + 2 // script begin
n := strings.Index(text[begin:], "}}")
n := strings.Index(text[begin:], delimRight)
if n < 0 {
n = len(text) - begin // script length
}
Expand All @@ -51,19 +71,19 @@ func Translate(text string) string {
}
n := len(offs)
if n == 0 {
return text
return false
}
var b strings.Builder
b.Grow(len(text) + n*4)
base = 0
delimRightLeft := delimRight + delimLeft
for i := 0; i < n; i++ {
off := offs[i]
b.WriteString(text[base:off])
b.WriteString("}}{{")
b.WriteString(delimRightLeft)
base = off
}
b.WriteString(text[base:])
return b.String()
return true
}

func isSpace(c byte) bool {
Expand Down
10 changes: 9 additions & 1 deletion internal/templ/template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@

package templ

import "testing"
import (
"bytes"
"testing"
)

const yapScriptIn = `
<html>
Expand Down Expand Up @@ -95,4 +98,9 @@ efg
if ret := Translate(noScriptEnd); ret != noScriptEndOut {
t.Fatal("translate(noScriptEnd):", ret)
}
var b bytes.Buffer
TranslateEx(&b, yapScriptIn, "", "")
if b.String() != yapScriptOut {
t.Fatal("TranslateEx:", b.String())
}
}
164 changes: 0 additions & 164 deletions template.go

This file was deleted.

24 changes: 12 additions & 12 deletions yap.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"os"
"strings"

"github.com/goplus/yap/internal/htmltempl"
"github.com/goplus/yap/noredirect"
)

Expand All @@ -33,7 +34,9 @@ type Engine struct {
router
Mux *http.ServeMux

tpl *Template
delimLeft, delimRight string

tpl htmltempl.Template
fs fs.FS
las func(addr string, handler http.Handler) error
}
Expand Down Expand Up @@ -68,15 +71,6 @@ func (p *Engine) initYapFS(fsys fs.FS) {
p.fs = fsys
}

// Load template
func (p *Engine) loadTemplate() {
t, err := parseFS(NewTemplate(""), p.yapFS(), []string{"*_yap.html"})
if err != nil {
log.Panicln(err)
}
p.tpl = t
}

func (p *Engine) yapFS() fs.FS {
if p.fs == nil {
p.initYapFS(os.DirFS("."))
Expand Down Expand Up @@ -163,9 +157,15 @@ func (p *Engine) SetLAS(listenAndServe func(addr string, handler http.Handler) e
p.las = listenAndServe
}

// SetDelims sets the action delimiters to the specified strings. Nested template definitions
// will inherit the settings. An empty delimiter stands for the corresponding default: {{ or }}.
func (p *Engine) SetDelims(left, right string) {
p.delimLeft, p.delimRight = left, right
}

func (p *Engine) templ(path string) *template.Template {
if p.tpl == nil {
p.loadTemplate()
if p.tpl.Template == nil {
p.tpl.InitTemplates(p.yapFS(), p.delimLeft, p.delimRight, "_yap.html")
}
return p.tpl.Lookup(path)
}
Expand Down
Loading

0 comments on commit db43ff2

Please sign in to comment.