github.com/ernestokarim/closurer@v0.0.0-20130119214741-f245d086c750/domain/source.go (about) 1 package domain 2 3 import ( 4 "bufio" 5 "encoding/gob" 6 "io" 7 "os" 8 "regexp" 9 "strings" 10 11 "github.com/ernestokarim/closurer/app" 12 "github.com/ernestokarim/closurer/cache" 13 ) 14 15 var ( 16 provideRe = regexp.MustCompile(`^\s*goog\.provide\(\s*[\'"](.+)[\'"]\s*\)`) 17 requiresRe = regexp.MustCompile(`^\s*goog\.require\(\s*[\'"](.+)[\'"]\s*\)`) 18 ) 19 20 func init() { 21 gob.Register(&Source{}) 22 } 23 24 // Represents a JS source 25 type Source struct { 26 // List of namespaces this file provides. 27 Provides []string 28 29 // List of required namespaces for this file. 30 Requires []string 31 32 // Whether this is the base.js file of the Closure Library. 33 Base bool 34 35 // Name of the source file. 36 Filename string 37 } 38 39 // Creates a new source. Returns the source, if it has been 40 // loaded from cache or not, and an error. 41 func NewSource(dest, filename, base string) (*Source, bool, error) { 42 src := cache.ReadData(dest+filename, new(Source)).(*Source) 43 44 // Return the file from cache if possible 45 if modified, err := cache.Modified(dest, filename); err != nil { 46 return nil, false, err 47 } else if !modified { 48 return src, true, nil 49 } 50 51 // Reset the source info 52 src.Provides = []string{} 53 src.Requires = []string{} 54 src.Base = (filename == base) 55 src.Filename = filename 56 57 // Open the file 58 f, err := os.Open(filename) 59 if err != nil { 60 return nil, false, app.Error(err) 61 } 62 defer f.Close() 63 64 r := bufio.NewReader(f) 65 for { 66 // Read it line by line 67 line, _, err := r.ReadLine() 68 if err != nil { 69 if err == io.EOF { 70 break 71 } 72 return nil, false, err 73 } 74 75 // Find the goog.provide() calls 76 if strings.Contains(string(line), "goog.provide") { 77 matchs := provideRe.FindSubmatch(line) 78 if matchs != nil { 79 src.Provides = append(src.Provides, string(matchs[1])) 80 continue 81 } 82 } 83 84 // Find the goog.require() calls 85 if strings.Contains(string(line), "goog.require") { 86 matchs := requiresRe.FindSubmatch(line) 87 if matchs != nil { 88 src.Requires = append(src.Requires, string(matchs[1])) 89 continue 90 } 91 } 92 } 93 94 // Validates the base file 95 if src.Base { 96 if len(src.Provides) > 0 || len(src.Requires) > 0 { 97 return nil, false, 98 app.Errorf("base files should not provide or require namespaces: %s", filename) 99 } 100 src.Provides = append(src.Provides, "goog") 101 } 102 103 return src, false, nil 104 }