11package runtime
22
33import (
4+ "crypto/sha256"
5+ "encoding/hex"
46 "errors"
57 "fmt"
68 "io"
79 "os"
10+ "path/filepath"
811 "runtime"
912 "strconv"
1013 "strings"
@@ -14,6 +17,42 @@ import (
1417
1518var developmentMode = os .Getenv ("TEMPL_DEV_MODE" ) == "true"
1619
20+ func GetDevModeTextFileName (templFileName string ) string {
21+ if strings .HasSuffix (templFileName , "_templ.go" ) {
22+ templFileName = strings .TrimSuffix (templFileName , "_templ.go" ) + ".templ"
23+ }
24+ absFileName , err := filepath .Abs (templFileName )
25+ if err != nil {
26+ absFileName = templFileName
27+ }
28+ absFileName , err = filepath .EvalSymlinks (absFileName )
29+ if err != nil {
30+ absFileName = templFileName
31+ }
32+ absFileName = normalizePath (absFileName )
33+
34+ hashedFileName := sha256 .Sum256 ([]byte (absFileName ))
35+ outputFileName := fmt .Sprintf ("templ_%s.txt" , hex .EncodeToString (hashedFileName [:]))
36+
37+ root := os .TempDir ()
38+ if os .Getenv ("TEMPL_DEV_MODE_ROOT" ) != "" {
39+ root = os .Getenv ("TEMPL_DEV_MODE_ROOT" )
40+ }
41+
42+ return filepath .Join (root , outputFileName )
43+ }
44+
45+ // normalizePath converts Windows paths to Unix style paths.
46+ func normalizePath (p string ) string {
47+ p = strings .ReplaceAll (filepath .Clean (p ), `\` , `/` )
48+ parts := strings .SplitN (p , ":" , 2 )
49+ if len (parts ) == 2 && len (parts [0 ]) == 1 {
50+ drive := strings .ToLower (parts [0 ])
51+ p = "/" + drive + parts [1 ]
52+ }
53+ return p
54+ }
55+
1756// WriteString writes the string to the writer. If development mode is enabled
1857// s is replaced with the string at the index in the _templ.txt file.
1958func WriteString (w io.Writer , index int , s string ) (err error ) {
@@ -22,13 +61,16 @@ func WriteString(w io.Writer, index int, s string) (err error) {
2261 if ! strings .HasSuffix (path , "_templ.go" ) {
2362 return errors .New ("templ: attempt to use WriteString from a non templ file" )
2463 }
25- txtFilePath := strings .Replace (path , "_templ.go" , "_templ.txt" , 1 )
64+ path , err := filepath .EvalSymlinks (path )
65+ if err != nil {
66+ return fmt .Errorf ("templ: failed to eval symlinks for %q: %w" , path , err )
67+ }
2668
69+ txtFilePath := GetDevModeTextFileName (path )
2770 literals , err := getWatchedStrings (txtFilePath )
2871 if err != nil {
29- return fmt .Errorf ("templ: failed to cache strings: %w" , err )
72+ return fmt .Errorf ("templ: failed to get watched strings for %q : %w" , path , err )
3073 }
31-
3274 if index > len (literals ) {
3375 return fmt .Errorf ("templ: failed to find line %d in %s" , index , txtFilePath )
3476 }
0 commit comments