summaryrefslogtreecommitdiff
path: root/vendor/github.com/a-h/templ/watchmode.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/a-h/templ/watchmode.go')
-rw-r--r--vendor/github.com/a-h/templ/watchmode.go105
1 files changed, 105 insertions, 0 deletions
diff --git a/vendor/github.com/a-h/templ/watchmode.go b/vendor/github.com/a-h/templ/watchmode.go
new file mode 100644
index 0000000..a94dab2
--- /dev/null
+++ b/vendor/github.com/a-h/templ/watchmode.go
@@ -0,0 +1,105 @@
+package templ
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "os"
+ "runtime"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+)
+
+// WriteWatchModeString is used when rendering templates in development mode.
+// the generator would have written non-go code to the _templ.txt file, which
+// is then read by this function and written to the output.
+//
+// Deprecated: since templ v0.3.x generated code uses WriteString.
+func WriteWatchModeString(w io.Writer, lineNum int) error {
+ _, path, _, _ := runtime.Caller(1)
+ if !strings.HasSuffix(path, "_templ.go") {
+ return errors.New("templ: WriteWatchModeString can only be called from _templ.go")
+ }
+ txtFilePath := strings.Replace(path, "_templ.go", "_templ.txt", 1)
+
+ literals, err := getWatchedStrings(txtFilePath)
+ if err != nil {
+ return fmt.Errorf("templ: failed to cache strings: %w", err)
+ }
+
+ if lineNum > len(literals) {
+ return fmt.Errorf("templ: failed to find line %d in %s", lineNum, txtFilePath)
+ }
+
+ s, err := strconv.Unquote(`"` + literals[lineNum-1] + `"`)
+ if err != nil {
+ return err
+ }
+ _, err = io.WriteString(w, s)
+ return err
+}
+
+var (
+ watchModeCache = map[string]watchState{}
+ watchStateMutex sync.Mutex
+)
+
+type watchState struct {
+ modTime time.Time
+ strings []string
+}
+
+func getWatchedStrings(txtFilePath string) ([]string, error) {
+ watchStateMutex.Lock()
+ defer watchStateMutex.Unlock()
+
+ state, cached := watchModeCache[txtFilePath]
+ if !cached {
+ return cacheStrings(txtFilePath)
+ }
+
+ if time.Since(state.modTime) < time.Millisecond*100 {
+ return state.strings, nil
+ }
+
+ info, err := os.Stat(txtFilePath)
+ if err != nil {
+ return nil, fmt.Errorf("templ: failed to stat %s: %w", txtFilePath, err)
+ }
+
+ if !info.ModTime().After(state.modTime) {
+ return state.strings, nil
+ }
+
+ return cacheStrings(txtFilePath)
+}
+
+func cacheStrings(txtFilePath string) ([]string, error) {
+ txtFile, err := os.Open(txtFilePath)
+ if err != nil {
+ return nil, fmt.Errorf("templ: failed to open %s: %w", txtFilePath, err)
+ }
+ defer func() {
+ _ = txtFile.Close()
+ }()
+
+ info, err := txtFile.Stat()
+ if err != nil {
+ return nil, fmt.Errorf("templ: failed to stat %s: %w", txtFilePath, err)
+ }
+
+ all, err := io.ReadAll(txtFile)
+ if err != nil {
+ return nil, fmt.Errorf("templ: failed to read %s: %w", txtFilePath, err)
+ }
+
+ literals := strings.Split(string(all), "\n")
+ watchModeCache[txtFilePath] = watchState{
+ modTime: info.ModTime(),
+ strings: literals,
+ }
+
+ return literals, nil
+}