diff options
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/fork_go_templates/.gitignore | 1 | ||||
-rw-r--r-- | scripts/fork_go_templates/main.go | 207 |
2 files changed, 208 insertions, 0 deletions
diff --git a/scripts/fork_go_templates/.gitignore b/scripts/fork_go_templates/.gitignore new file mode 100644 index 000000000..81af73f40 --- /dev/null +++ b/scripts/fork_go_templates/.gitignore @@ -0,0 +1 @@ +fork_go_templates diff --git a/scripts/fork_go_templates/main.go b/scripts/fork_go_templates/main.go new file mode 100644 index 000000000..148785883 --- /dev/null +++ b/scripts/fork_go_templates/main.go @@ -0,0 +1,207 @@ +package main + +import ( + "fmt" + "io/ioutil" + "log" + "os" + "os/exec" + "path/filepath" + "regexp" + "strings" + + "github.com/gohugoio/hugo/common/hugio" + + "github.com/spf13/afero" +) + +func main() { + // TODO(bep) git checkout tag + // The current is built with Go version 9341fe073e6f7742c9d61982084874560dac2014 / go1.13.5 + fmt.Println("Forking ...") + defer fmt.Println("Done ...") + + cleanFork() + + htmlRoot := filepath.Join(forkRoot, "htmltemplate") + + for _, pkg := range goPackages { + copyGoPackage(pkg.dstPkg, pkg.srcPkg) + } + + for _, pkg := range goPackages { + doWithGoFiles(pkg.dstPkg, pkg.rewriter, pkg.replacer) + } + + goimports(htmlRoot) + gofmt(forkRoot) + +} + +const ( + // TODO(bep) + goSource = "/Users/bep/dev/go/dump/go/src" + forkRoot = "../../tpl/internal/go_templates" +) + +type goPackage struct { + srcPkg string + dstPkg string + replacer func(name, content string) string + rewriter func(name string) +} + +var ( + textTemplateReplacers = strings.NewReplacer( + `"text/template/`, `"github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate/`, + `"internal/fmtsort"`, `"github.com/gohugoio/hugo/tpl/internal/go_templates/fmtsort"`, + // Rename types and function that we want to overload. + "type state struct", "type stateOld struct", + ) + + htmlTemplateReplacers = strings.NewReplacer( + `. "html/template"`, `. "github.com/gohugoio/hugo/tpl/internal/go_templates/htmltemplate"`, + `"html/template"`, `template "github.com/gohugoio/hugo/tpl/internal/go_templates/htmltemplate"`, + "\"text/template\"\n", "template \"github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate\"\n", + `"html/template"`, `htmltemplate "html/template"`, + `"fmt"`, `htmltemplate "html/template"`, + ) +) + +func commonReplace(name, content string) string { + if strings.HasSuffix(name, "_test.go") { + content = strings.Replace(content, "package template\n", `// +build go1.13,!windows + +package template +`, 1) + content = strings.Replace(content, "package template_test\n", `// +build go1.13 + +package template_test +`, 1) + + content = strings.Replace(content, "package parse\n", `// +build go1.13 + +package parse +`, 1) + + } + + return content + +} + +var goPackages = []goPackage{ + goPackage{srcPkg: "text/template", dstPkg: "texttemplate", + replacer: func(name, content string) string { return textTemplateReplacers.Replace(commonReplace(name, content)) }}, + goPackage{srcPkg: "html/template", dstPkg: "htmltemplate", replacer: func(name, content string) string { + if strings.HasSuffix(name, "content.go") { + // Remove template.HTML types. We need to use the Go types. + content = removeAll(`(?s)// Strings of content.*?\)\n`, content) + } + + content = commonReplace(name, content) + + return htmlTemplateReplacers.Replace(content) + }, + rewriter: func(name string) { + for _, s := range []string{"CSS", "HTML", "HTMLAttr", "JS", "JSStr", "URL", "Srcset"} { + rewrite(name, fmt.Sprintf("%s -> htmltemplate.%s", s, s)) + } + rewrite(name, `"text/template/parse" -> "github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate/parse"`) + }}, + goPackage{srcPkg: "internal/fmtsort", dstPkg: "fmtsort", rewriter: func(name string) { + rewrite(name, `"internal/fmtsort" -> "github.com/gohugoio/hugo/tpl/internal/go_templates/fmtsort"`) + }}, +} + +var fs = afero.NewOsFs() + +// Removes all non-Hugo files in the go_templates folder. +func cleanFork() { + must(filepath.Walk(filepath.Join(forkRoot), func(path string, info os.FileInfo, err error) error { + if !info.IsDir() && len(path) > 10 && !strings.Contains(path, "hugo") { + must(fs.Remove(path)) + } + return nil + })) +} + +func must(err error, what ...string) { + if err != nil { + log.Fatal(what, " ERROR: ", err) + } +} + +func copyGoPackage(dst, src string) { + from := filepath.Join(goSource, src) + to := filepath.Join(forkRoot, dst) + fmt.Println("Copy", from, "to", to) + must(hugio.CopyDir(fs, from, to, func(s string) bool { return true })) +} + +func doWithGoFiles(dir string, + rewrite func(name string), + transform func(name, in string) string) { + if rewrite == nil && transform == nil { + return + } + must(filepath.Walk(filepath.Join(forkRoot, dir), func(path string, info os.FileInfo, err error) error { + if info.IsDir() { + return nil + } + + if !strings.HasSuffix(path, ".go") || strings.Contains(path, "hugo_") { + return nil + } + + fmt.Println("Handle", path) + + if rewrite != nil { + rewrite(path) + } + + if transform == nil { + return nil + } + + data, err := ioutil.ReadFile(path) + must(err) + f, err := os.Create(path) + must(err) + defer f.Close() + _, err = f.WriteString(transform(path, string(data))) + must(err) + + return nil + })) +} + +func removeAll(expression, content string) string { + re := regexp.MustCompile(expression) + return re.ReplaceAllString(content, "") + +} + +func rewrite(filename, rule string) { + cmf := exec.Command("gofmt", "-w", "-r", rule, filename) + out, err := cmf.CombinedOutput() + if err != nil { + log.Fatal("gofmt failed:", string(out)) + } +} + +func goimports(dir string) { + cmf := exec.Command("goimports", "-w", dir) + out, err := cmf.CombinedOutput() + if err != nil { + log.Fatal("goimports failed:", string(out)) + } +} + +func gofmt(dir string) { + cmf := exec.Command("gofmt", "-w", dir) + out, err := cmf.CombinedOutput() + if err != nil { + log.Fatal("gofmt failed:", string(out)) + } +} |