package main import ( "io/ioutil" "log" "net/http" "os" "path/filepath" "strings" "time" ) const GeneratedFolderName = "generated" func genStaticFiles(rootURL string) { log.SetFlags(log.Lshortfile) wd, err := os.Getwd() if err != nil { log.Fatalln("Can't get current path:", err) } fullPath := func(relPath ...string) string { return filepath.Join(append([]string{wd}, relPath...)...) } _, err = os.Stat(fullPath("web", "static", "go101")) if err != nil { if os.IsNotExist(err) { //errors.Is(err, os.ErrNotExist) { log.Fatal("File web/static/go101 not found. Not run in go101 folder?") } log.Fatal(err) } // load from http server loadFile := func(uri string) []byte { fullURL := rootURL + uri res, err := http.Get(fullURL) if err != nil { log.Fatalf("Load file %s error: %s", uri, err) } content, err := ioutil.ReadAll(res.Body) log.Println(len(content), fullURL) res.Body.Close() if err != nil { log.Fatal(err) } return content } // read from OS file system readFile := func(path string) []byte { data, err := ioutil.ReadFile(path) if err != nil { log.Fatalf("Read file %s error: %s", path, err) } return data } readFolder := func(path string) (filenames, subfolders []string) { fds, err := ioutil.ReadDir(path) if err != nil { log.Fatalf("Read folder %s error: %s", path, err) } subfolders, filenames = make([]string, 0, len(fds)), make([]string, 0, len(fds)) for _, fd := range fds { // ignore links, ... if fd.IsDir() { subfolders = append(subfolders, filepath.Join(path, fd.Name())) continue } filenames = append(filenames, filepath.Join(path, fd.Name())) } return } var readFolderRecursively func(path string) (filenames []string) readFolderRecursively = func(path string) (filenames []string) { type Folder struct { Path string Next *Folder } var head, tail *Folder regSubfolders := func(folders []string) { if len(folders) == 0 { return } start := 0 if head == nil { head = &Folder{ Path: folders[0], } tail = head start = 1 } for i := start; i < len(folders); i++ { fldr := &Folder{ Path: folders[i], } tail.Next = fldr tail = fldr } } var subfolders []string filenames, subfolders = readFolder(path) regSubfolders(subfolders) for head != nil { files, subfolders := readFolder(head.Path) head = head.Next regSubfolders(subfolders) filenames = append(filenames, files...) } return } // md -> html md2htmls := func(group string) { dir := fullPath("pages", group) outputs, err := runShellCommand(time.Minute/2, dir, "ebooktool", "-md2htmls") if err != nil { log.Fatalf("ebooktool failed to execute in directory: %s.\n%s", dir, outputs) } } // tmd -> html tmd2htmls := func(group string) { dir := fullPath("pages", group) filenames, _ := readFolder(dir) for _, filename := range filenames { if strings.HasSuffix(filename, ".tmd") { outputs, err := runShellCommand(time.Minute/2, dir, "tmd", "render", filename) if err != nil { log.Fatalf("tmd failed to execute in directory: %s.\n%s", dir, outputs) } } } } // collect ... files := make(map[string][]byte, 128) files["index.html"] = loadFile("") { dir := fullPath("web", "static") filenames := readFolderRecursively(dir) for _, f := range filenames { name, err := filepath.Rel(dir, f) if err != nil { log.Fatalf("filepath.Rel(%s, %s) error: %s", dir, f, err) } files["static/"+name] = readFile(f) } } collectPageGroupFiles := func(group, urlPrefix string, collectRes bool) { if collectRes { dir := fullPath("pages", group, "res") filenames, _ := readFolder(dir) for _, f := range filenames { if strings.HasSuffix(f, ".png") || strings.HasSuffix(f, ".jpg") { name, err := filepath.Rel(dir, f) if err != nil { log.Fatalf("filepath.Rel(%s, %s) error: %s", dir, f, err) } files[urlPrefix+"res/"+name] = readFile(f) } } } md2htmls(group) tmd2htmls(group) { dir := fullPath("pages", group) filenames, _ := readFolder(dir) for _, f := range filenames { if strings.HasSuffix(f, ".html") { name, err := filepath.Rel(dir, f) if err != nil { log.Fatalf("filepath.Rel(%s, %s) error: %s", dir, f, err) } files[urlPrefix+name] = loadFile(urlPrefix + name) } } } } { infos, err := ioutil.ReadDir(fullPath("pages")) if err != nil { panic("collect page groups error: " + err.Error()) } for _, e := range infos { if e.IsDir() { group := e.Name() var urlPrefix string if group == "fundamentals" { // For history reason, fundamentals pages use "/article/xxx" URLs. urlPrefix = "article/" } else if group != "website" { urlPrefix = group + "/" } var collectRes bool if _, err := os.Stat(fullPath("pages", group, "res")); err == nil { collectRes = true } collectPageGroupFiles(group, urlPrefix, collectRes) } } } // write ... err = os.RemoveAll(fullPath(GeneratedFolderName)) if err != nil { log.Fatalf("Remove folder %s error: %s", GeneratedFolderName, err) } for name, data := range files { fullFilename := fullPath(GeneratedFolderName, name) fullFilename = strings.Replace(fullFilename, "/", string(filepath.Separator), -1) fullFilename = strings.Replace(fullFilename, "\\", string(filepath.Separator), -1) if err := os.MkdirAll(filepath.Dir(fullFilename), 0700); err != nil { log.Fatalln("Mkdir error:", err) } if err := ioutil.WriteFile(fullFilename, data, 0644); err != nil { log.Fatalln("Write file error:", err) } log.Printf("Generated %s (size: %d).", name, len(data)) } }