func main() { flag.Usage = usage flag.Parse() if *help { usage() } // Read the configuration c, err := config.ReadConfigFromFile(cfgfile, source) HandleError(err) // Add the missing sourcePath c.SourcePath = *source // Create a Process process := &Process{Done: make(chan bool), Source: *source, Started: true, PagesFileInfo: make(map[string]*os.FileInfo), AssetsFileInfo: make(map[string]*os.FileInfo), } // Create a plugin configuration object configPlugin := &gutenberg.PluginConfig{SourcePath: *source, OutputDirectory: c.OutputDirectory} // Get the custom HTML transformer process.CustomTransformer = gutenberg.NewCustomHtml(c) // Add new Custom Plugins to the transformer process.CustomTransformer.AddPlugin("dot", plugins.NewDotPlugin(configPlugin)) process.CustomTransformer.AddPlugin("note", plugins.NewNotePlugin()) // Create output directory if it does not exist err = os.Mkdir(c.OutputDirectory, 0755) // Rebuild the entire book if *rebuild { GenerateWholeBook(process) } else { HandleError(ReadAllModTimes(c, process)) } // Go into watch mode if *watchMode { WatchMode(*interval, process) } }
func WatchMode(delay int64, p *Process) { go func() { for true { // Get the parts of the config file sourcePath := config.SourcePath(source) configFileLocation := config.ConfigFile(sourcePath, cfgfile) // Set the config file name configFileInfo, err := os.Stat(configFileLocation) if err != nil { log.Printf("Failed to read configuration file from %s\n", configFileLocation) continue } // Read the configuration c, err := config.ReadConfigFromFile(cfgfile, source) if err != nil { log.Printf("Failed to read configuration file from %s\n", configFileLocation) continue } // Point to the actual instance configFileInfoInstance := *p.ConfigFileInfo // If config time finished if !configFileInfo.ModTime().Equal(configFileInfoInstance.ModTime()) { log.Printf("Configuration file changed, regenerating whole book\n") // Re-generate the whole book GenerateWholeBook(p) // Save the new configuration file info p.ConfigFileInfo = &configFileInfo // Done, let's watch again continue } // Read all the layouts for html htmlLayouts := c.Layouts["html"] indexLayout := htmlLayouts.Index pageLayout := htmlLayouts.Page // Get the file info for the pageLayout file pageLayoutFile := fmt.Sprintf("%s/%s", p.Source, pageLayout) pageLayoutFileInfo, err := os.Stat(pageLayoutFile) if err != nil { log.Printf("Index layout file changed, regenerating whole book\n") // Re-generate the whole book GenerateWholeBook(p) // Update the time p.PageLayoutFileInfo = &pageLayoutFileInfo continue } // Get the file info for the pageLayout file indexLayoutFile := fmt.Sprintf("%s/%s", p.Source, indexLayout) indexLayoutFileInfo, err := os.Stat(indexLayoutFile) if err != nil { log.Printf("Index layout file changed, regenerating whole book\n") // Re-generate the whole book GenerateWholeBook(p) // Update the time p.IndexFileInfo = &indexLayoutFileInfo continue } // Read the page layout file in layoutBytes, err := ioutil.ReadFile(pageLayoutFile) if err != nil { log.Printf("no layout file found for %s\n", pageLayoutFile) } // Parse the template into an object pageTemplate, err := template.New("pageTemplate").Parse(string(layoutBytes)) if err != nil { log.Printf("invalid template found in %s page template file\n", pageLayoutFile) } // Copy over all the assets for _, asset := range c.Assets { assetLocation := fmt.Sprintf("%s/%s", p.Source, asset) fileContent, err := ioutil.ReadFile(assetLocation) // Get the file info for the pageLayout file assetFileInfo, err := os.Stat(assetLocation) if err == nil { modTime := *p.AssetsFileInfo[asset] if modTime != nil && modTime.ModTime().Equal(assetFileInfo.ModTime()) { continue } p.AssetsFileInfo[asset] = &assetFileInfo } if err == nil { assetOutputLocation := fmt.Sprintf("%s/%s", c.OutputDirectory, filepath.Base(asset)) log.Printf("Saving asset to %s\n", assetOutputLocation) err = ioutil.WriteFile(assetOutputLocation, fileContent, 0755) if err != nil { log.Fatalf("Failed to save the asset %s to %s\n", asset, assetOutputLocation) } } else { log.Fatalf("Could not locate the asset %s\n", asset) } } // We only re-generate pages that have changed // Read all the pages in for _, page := range c.TableOfContents { // Split the file up so we can get the "name" fileNameParts := strings.Split(page.File, ".") fileName := strings.Join(fileNameParts[0:(len(fileNameParts)-1)], ".") // Read the page pageFile := fmt.Sprintf("%s/%s", p.Source, page.File) // Get the file info for the pageLayout file pageFileInfo, err := os.Stat(pageFile) if err == nil { modTime := *p.PagesFileInfo[page.File] if modTime != nil && modTime.ModTime().Equal(pageFileInfo.ModTime()) { continue } log.Printf("Generate page %s\n", page.File) p.PagesFileInfo[page.File] = &pageFileInfo } // Read the page into memory data, err := ioutil.ReadFile(pageFile) if err != nil { continue } // Get the custom Html transformer customTransformer := gutenberg.NewCustomHtml(c) // Render the mardown html := customTransformer.Transform(data) // Pass to the template if it's defined if pageTemplate != nil { // var buffer bytes.Buffer buffer := bytes.NewBuffer(nil) err = pageTemplate.Execute(buffer, BuildContext(string(html), c)) if err != nil { log.Fatalf("Failed to execute template %s\n", pageLayoutFile) os.Exit(0) } // Save the data as the new page html = buffer.Bytes() } // Let's write the resulting page out err = ioutil.WriteFile(fmt.Sprintf("%s/%s.html", c.OutputDirectory, fileName), html, 0755) if err != nil { continue } } // Just sleep a bit and watch again time.Sleep(time.Duration(delay) * time.Millisecond) } }() // Wait until we are done <-p.Done }
func GenerateBook(p *Process, c *config.Config) error { // Read all the layouts for html htmlLayouts := c.Layouts["html"] indexLayout := htmlLayouts.Index pageLayout := htmlLayouts.Page // Get the parts of the config file sourcePath := config.SourcePath(source) // Set the config file name configFile := config.ConfigFile(sourcePath, cfgfile) configFileInfo, err := os.Stat(configFile) if err == nil { p.ConfigFileInfo = &configFileInfo } // Get the right location for the page layout file indexLayoutFile := fmt.Sprintf("%s/%s", p.Source, indexLayout) // Get the file info for the pageLayout file indexLayoutFileInfo, err := os.Stat(indexLayoutFile) if err == nil { p.IndexFileInfo = &indexLayoutFileInfo } // Get the right location for the page layout file pageLayoutFile := fmt.Sprintf("%s/%s", p.Source, pageLayout) // Get the file info for the pageLayout file pageLayoutFileInfo, err := os.Stat(pageLayoutFile) if err == nil { p.PageLayoutFileInfo = &pageLayoutFileInfo } // Read the page layout file in layoutBytes, err := ioutil.ReadFile(pageLayoutFile) if err != nil { log.Printf("no layout file found for %s\n", pageLayoutFile) } // Parse the template into an object pageTemplate, err := template.New("pageTemplate").Parse(string(layoutBytes)) if err != nil { log.Printf("invalid template found in %s page template file\n", pageLayoutFile) } // Copy over all the assets for _, asset := range c.Assets { assetLocation := fmt.Sprintf("%s/%s", p.Source, asset) fileContent, err := ioutil.ReadFile(assetLocation) // Get the file info for the pageLayout file assetFileInfo, err := os.Stat(assetLocation) if err == nil { p.AssetsFileInfo[asset] = &assetFileInfo } if err == nil { assetOutputLocation := fmt.Sprintf("%s/%s", c.OutputDirectory, filepath.Base(asset)) log.Printf("Saving asset to %s\n", assetOutputLocation) err = ioutil.WriteFile(assetOutputLocation, fileContent, 0755) if err != nil { log.Fatalf("Failed to save the asset %s to %s\n", asset, assetOutputLocation) } } else { log.Fatalf("Could not locate the asset %s\n", asset) } } // Read all the pages in for _, page := range c.TableOfContents { log.Printf("Generate page %s\n", page.File) // Split the file up so we can get the "name" fileNameParts := strings.Split(page.File, ".") fileName := strings.Join(fileNameParts[0:(len(fileNameParts)-1)], ".") // Read the page pageFile := fmt.Sprintf("%s/%s", p.Source, page.File) // Get the file info for the pageLayout file pageFileInfo, err := os.Stat(pageFile) if err != nil { return err } if err == nil { p.PagesFileInfo[page.File] = &pageFileInfo } // Read the page into memory data, err := ioutil.ReadFile(pageFile) if err != nil { return err } // Get the custom Html transformer customTransformer := gutenberg.NewCustomHtml(c) // Render the mardown html := customTransformer.Transform(data) // Pass to the template if it's defined if pageTemplate != nil { // var buffer bytes.Buffer buffer := bytes.NewBuffer(nil) err = pageTemplate.Execute(buffer, BuildContext(string(html), c)) if err != nil { log.Fatalf("Failed to execute template %s\n", pageLayoutFile) os.Exit(0) } // Save the data as the new page html = buffer.Bytes() } // Let's write the resulting page out err = ioutil.WriteFile(fmt.Sprintf("%s/%s.html", c.OutputDirectory, fileName), html, 0755) if err != nil { return err } } return nil }