// Creates a new source. Returns the source, if it has been // loaded from cache or not, and an error. func NewSource(dest, filename, base string) (*Source, bool, error) { src := cache.ReadData(dest+filename, new(Source)).(*Source) // Return the file from cache if possible if modified, err := cache.Modified(dest, filename); err != nil { return nil, false, err } else if !modified { return src, true, nil } // Reset the source info src.Provides = []string{} src.Requires = []string{} src.Base = (filename == base) src.Filename = filename // Open the file f, err := os.Open(filename) if err != nil { return nil, false, app.Error(err) } defer f.Close() r := bufio.NewReader(f) for { // Read it line by line line, _, err := r.ReadLine() if err != nil { if err == io.EOF { break } return nil, false, err } // Find the goog.provide() calls if strings.Contains(string(line), "goog.provide") { matchs := provideRe.FindSubmatch(line) if matchs != nil { src.Provides = append(src.Provides, string(matchs[1])) continue } } // Find the goog.require() calls if strings.Contains(string(line), "goog.require") { matchs := requiresRe.FindSubmatch(line) if matchs != nil { src.Requires = append(src.Requires, string(matchs[1])) continue } } } // Validates the base file if src.Base { if len(src.Provides) > 0 || len(src.Requires) > 0 { return nil, false, app.Errorf("base files should not provide or require namespaces: %s", filename) } src.Provides = append(src.Provides, "goog") } return src, false, nil }
// Compile all modified templates func Compile() error { conf := config.Current() if conf.Soy == nil || conf.Soy.Root == "" { return nil } if err := os.MkdirAll(path.Join(conf.Build, "templates"), 0755); err != nil { return app.Error(err) } buildPrefix := filepath.Join(conf.Build, "templates") oldSoy, err := scan.Do(buildPrefix, ".js") if err != nil { return err } soy, err := scan.Do(conf.Soy.Root, ".soy") if err != nil { return err } indexed := map[string]bool{} for _, f := range soy { f = f[len(conf.Soy.Root):] indexed[f] = true } // Delete compiled templates no longer present in the sources for _, f := range oldSoy { compare := f[len(buildPrefix) : len(f)-3] if _, ok := indexed[compare]; !ok { if err := os.Remove(f); err != nil { return app.Error(err) } } } if len(soy) == 0 { return nil } for _, t := range soy { if modified, err := cache.Modified("compile", t); err != nil { return err } else if !modified { continue } prel, err := filepath.Rel(conf.Soy.Root, t) if err != nil { return app.Error(err) } out := path.Join(conf.Build, "templates", prel+".js") if err := os.MkdirAll(path.Dir(out), 0755); err != nil { return app.Error(err) } log.Println("Compiling template", t, "...") // Run the compiler command cmd := exec.Command( "java", "-jar", path.Join(conf.Soy.Compiler, "build", "SoyToJsSrcCompiler.jar"), "--outputPathFormat", out, "--shouldGenerateJsdoc", "--shouldProvideRequireSoyNamespaces", "--cssHandlingScheme", "goog", t) output, err := cmd.CombinedOutput() if err != nil { return app.Errorf("exec error with %s: %s\n%s", t, err, string(output)) } log.Println("Done compiling template!") } return nil }
// Compiles the .gss files func Compile() error { conf := config.Current() target := conf.Gss.CurTarget() // Output early if there's no GSS files. if conf.Gss == nil { if err := cleanRenamingMap(); err != nil { return err } return nil } // Check if the cached version is still ok modified := false for _, input := range conf.Gss.Inputs { if m, err := cache.Modified("compile", input.File); err != nil { return err } else if m { modified = true break } } if !modified { return nil } log.Println("Compiling GSS:", target.Name) if err := cleanRenamingMap(); err != nil { return err } // Prepare the list of non-standard functions. funcs := []string{} for _, f := range conf.Gss.Funcs { funcs = append(funcs, "--allowed-non-standard-function") funcs = append(funcs, f.Name) } // Prepare the renaming map args renaming := []string{} if target.Rename == "true" { renaming = []string{ "--output-renaming-map-format", "CLOSURE_COMPILED", "--rename", "CLOSURE", "--output-renaming-map", path.Join(conf.Build, config.RENAMING_MAP_NAME), } } // Prepare the defines defines := []string{} for _, define := range target.Defines { defines = append(defines, "--define", define.Name) } // Prepare the inputs inputs := []string{} for _, input := range conf.Gss.Inputs { inputs = append(inputs, input.File) } // Prepare the command cmd := exec.Command( "java", "-jar", path.Join(conf.Gss.Compiler, "build", "closure-stylesheets.jar"), "--output-file", filepath.Join(conf.Build, config.CSS_NAME)) cmd.Args = append(cmd.Args, funcs...) cmd.Args = append(cmd.Args, renaming...) cmd.Args = append(cmd.Args, inputs...) cmd.Args = append(cmd.Args, defines...) // Output the command if asked to if config.OutputCmd { fmt.Println("java", strings.Join(cmd.Args, " ")) } // Run the compiler output, err := cmd.CombinedOutput() if err != nil { if len(output) != 0 { fmt.Println(string(output)) } return app.Errorf("exec error: %s", err) } if len(output) > 0 { log.Println("Output from GSS compiler:\n", string(output)) } log.Println("Done compiling GSS!") return nil }