github.com/geniusesgroup/libgo@v0.0.0-20220713101832-828057a9d3d4/www/combine.go (about) 1 /* For license and copyright information please see LEGAL file in repository */ 2 3 package www 4 5 import ( 6 "strings" 7 8 "../convert" 9 "../file" 10 language "../language" 11 "../mediatype" 12 "../protocol" 13 ) 14 15 type combine struct { 16 guiDir protocol.FileDirectory 17 dlDir protocol.FileDirectory 18 pagesDir protocol.FileDirectory 19 widgetsDir protocol.FileDirectory 20 landingsDir protocol.FileDirectory 21 mainHTMLDir protocol.FileDirectory // files name is just language in iso format e.g. "en", "fa", 22 23 inlined map[string]protocol.File // map key is file path 24 mainHTMLFiles map[string]protocol.File // map key is language in iso format e.g. "en", "fa", ... 25 mainJSFiles map[string]protocol.File // map key is language in iso format e.g. "en", "fa", ... 26 27 contentEncodings []string 28 } 29 30 // Update use to add needed repo files that get from disk or network to the assets!! 31 func (c *combine) update() { 32 c.inlined = make(map[string]protocol.File) 33 c.mainHTMLFiles = make(map[string]protocol.File) 34 c.mainJSFiles = make(map[string]protocol.File) 35 36 c.guiDir, _ = protocol.App.Files().Directory(guiDirectoryName) 37 c.dlDir, _ = c.guiDir.Directory("design-languages") 38 c.pagesDir, _ = c.guiDir.Directory("pages") 39 c.widgetsDir, _ = c.guiDir.Directory("widgets") 40 c.landingsDir, _ = c.guiDir.Directory("landings") 41 c.mainHTMLDir, _ = c.guiDir.Directory(mainHTMLDirectoryName) 42 43 c.readyLandingsFiles() 44 switch "js" { 45 case "go": 46 c.readyAppGoToJSFile() 47 case "js": 48 c.readyAppJSFiles() 49 } 50 c.readySWFile() 51 c.readyDesignLanguagesFiles() 52 } 53 54 func (c *combine) readyAppGoToJSFile() { 55 var mainGOFile, _ = c.guiDir.File("main.go") 56 if mainGOFile == nil { 57 protocol.App.Log(protocol.LogType_Warning, "WWW - no main.go file exist to ready UI apps to serve!") 58 return 59 } 60 61 // TODO:: compile to JS by https://github.com/gopherjs/gopherjs 62 } 63 64 func (c *combine) readyAppJSFiles() { 65 var mainHTMLFile, _ = c.landingsDir.File("main.html") 66 if mainHTMLFile == nil { 67 protocol.App.Log(protocol.LogType_Warning, "WWW - no main.html file exist to ready UI apps to serve!") 68 return 69 } 70 71 var mainJSFile, _ = c.guiDir.File("main.js") 72 if mainJSFile == nil { 73 protocol.App.Log(protocol.LogType_Warning, "WWW - no main.js file exist to ready UI apps to serve!") 74 return 75 } 76 77 var lj = make(localize, 8) 78 var jsonFile, _ = c.guiDir.File("main.json") 79 if jsonFile == nil { 80 protocol.App.Log(protocol.LogType_Warning, "WWW - Can't find json localize file for /main.js") 81 return 82 } 83 lj.jsonDecoder(jsonFile.Data().Marshal()) 84 if len(lj) == 0 { 85 protocol.App.Log(protocol.LogType_Warning, "WWW - Founded json not meet standards to localize for main.js") 86 return 87 } 88 89 var mainJSCreator = JS{ 90 imports: make([]protocol.File, 1, 100), 91 inlined: c.inlined, 92 } 93 mainJSCreator.imports[0] = mainJSFile 94 _ = mainJSCreator.extractJSImportsRecursively(mainJSFile) 95 if protocol.AppDevMode { 96 var name strings.Builder 97 for _, imp := range mainJSCreator.imports { 98 name.WriteString(imp.Metadata().URI().Name()) 99 name.WriteByte(',') 100 } 101 protocol.App.Log(protocol.LogType_Warning, "WWW - main.js imports recursively:", name.String()) 102 } 103 104 for lang := range lj { 105 var localeJSFileName = "main-" + lang + ".js" 106 var localeJSFile, _ = c.guiDir.File(localeJSFileName) 107 // write some data if file exist before 108 localeJSFile.Data().Unmarshal([]byte("\n")) 109 c.mainJSFiles[lang] = localeJSFile 110 } 111 112 for i := len(mainJSCreator.imports) - 1; i >= 0; i-- { 113 c.addLocalized(mainJSCreator.imports[i]) 114 } 115 116 for lang, localeMainJSFile := range c.mainJSFiles { 117 // Complete main JS file making proccess 118 var sdk, _ = protocol.App.ErrorsSDK(language.GetLanguageByISO(lang), mediatype.JavaScript) 119 // Add platfrom errors! 120 localeMainJSFile.Data().Append(sdk) 121 file.AddHashToFileName(localeMainJSFile) 122 file.Compress(localeMainJSFile, c.contentEncodings, protocol.BestCompression) 123 124 // make main.html 125 var localeJSFileName = localeMainJSFile.Metadata().URI().Name() 126 var localeMainHTMLFileName = "main-" + lang + ".html" 127 var localeMainHTMLFile, _ = c.guiDir.File(localeMainHTMLFileName) 128 var err = file.Minify(localeMainHTMLFile) 129 if err != nil && protocol.AppDebugMode { 130 protocol.App.Log(protocol.LogType_Warning, "Minify -", localeMainHTMLFileName, "occur this error:", err) 131 } 132 localeMainHTMLFile.Data().Replace([]byte("/main.js"), []byte(localeJSFileName), 1) 133 file.AddHashToFileName(localeMainHTMLFile) 134 file.Compress(localeMainHTMLFile, c.contentEncodings, protocol.BestCompression) 135 c.mainHTMLFiles[lang] = localeMainHTMLFile 136 137 // Add localized main html files without any compression to specific serve directory 138 var localeMainHTMLFileLangName, _ = c.mainHTMLDir.File(lang) 139 localeMainHTMLFileLangName.Data().Unmarshal(localeMainHTMLFile.Data().Marshal()) 140 } 141 } 142 143 func (c *combine) addLocalized(file protocol.File) { 144 if c.isInlined(file.Metadata().URI().Path()) { 145 return 146 } 147 c.inlined[file.Metadata().URI().Path()] = file 148 149 var mixedData = localeAndMixJSFile(file) 150 for lang, mainFile := range c.mainJSFiles { 151 var localeData = mixedData[lang] 152 if localeData != nil { 153 mainFile.Data().Append(localeData) 154 } else { 155 if protocol.AppDevMode { 156 protocol.App.Log(protocol.LogType_Warning, "WWW - ", file.Metadata().URI().Name(), "don't have locale files in '", lang, "' language that main.js support this language. WWW Use pure file in combine proccess.") 157 } 158 } 159 } 160 161 // reset file to storage state to undo extract import from file 162 file.Data().Unmarshal(nil) 163 } 164 165 func (c *combine) isInlined(uriPath string) (ok bool) { 166 _, ok = c.inlined[uriPath] 167 return 168 } 169 170 // readyDesignLanguagesFiles read needed files from given repo folder and do some logic and return files. 171 func (c *combine) readyDesignLanguagesFiles() { 172 var err protocol.Error 173 for _, dlFile := range c.dlDir.Files(0, 0) { 174 if dlFile.Metadata().URI().Extension() == "css" { 175 var cssName = dlFile.Metadata().URI().Name() 176 var cssFile, _ = c.dlDir.File("h-" + cssName) 177 cssFile.Data().Unmarshal(dlFile.Data().Marshal()) 178 err = file.Minify(cssFile) 179 if err != nil && protocol.AppDebugMode { 180 protocol.App.Log(protocol.LogType_Warning, "Minify -", cssName, "occur this error:", err) 181 } 182 file.AddHashToFileName(cssFile) 183 file.Compress(cssFile, c.contentEncodings, protocol.BestCompression) 184 185 for _, mainFile := range c.mainJSFiles { 186 var fileNameWithoutHashAdded = convert.UnsafeStringToByteSlice(cssName) 187 var fileNameWithHashAdded = convert.UnsafeStringToByteSlice(cssFile.Metadata().URI().Name()) 188 mainFile.Data().Replace(fileNameWithoutHashAdded, fileNameWithHashAdded, -1) 189 } 190 } 191 } 192 for _, dir := range c.dlDir.Directories(0, 0) { 193 var combinedFileName = dir.Metadata().URI().Name() + ".css" 194 var combinedFile, _ = c.dlDir.File(combinedFileName) 195 var combinedFileData []byte 196 for _, file := range dir.Files(0, 0) { 197 if file.Metadata().URI().Extension() == "css" { 198 combinedFileData = append(combinedFileData, file.Data().Marshal()...) 199 } 200 } 201 combinedFile.Data().Unmarshal(combinedFileData) 202 err = file.Minify(combinedFile) 203 if err != nil && protocol.AppDebugMode { 204 protocol.App.Log(protocol.LogType_Warning, "Minify -", combinedFileName, "occur this error:", err) 205 } 206 file.AddHashToFileName(combinedFile) 207 file.Compress(combinedFile, c.contentEncodings, protocol.BestCompression) 208 209 for _, mainFile := range c.mainJSFiles { 210 var fileNameWithoutHashAdded = convert.UnsafeStringToByteSlice(combinedFileName) 211 var fileNameWithHashAdded = convert.UnsafeStringToByteSlice(combinedFile.Metadata().URI().Name()) 212 mainFile.Data().Replace(fileNameWithoutHashAdded, fileNameWithHashAdded, -1) 213 } 214 } 215 } 216 217 // readyLandingsFiles read needed files from given repo folder and do some logic and return files. 218 func (c *combine) readyLandingsFiles() { 219 var err protocol.Error 220 // TODO::: Need to change landings file name to hash of data?? 221 for _, landing := range c.landingsDir.Files(0, 0) { 222 switch landing.Metadata().URI().Extension() { 223 case "html": 224 var landingName = landing.Metadata().URI().NameWithoutExtension() 225 var landingJsonFile, _ = c.landingsDir.File(landingName + ".json") 226 if landingJsonFile == nil { 227 protocol.App.Log(protocol.LogType_Warning, "WWW - Can't find json localize json file for ", landing.Metadata().URI().Name()) 228 continue 229 } 230 var lj = make(localize) 231 lj.jsonDecoder(landingJsonFile.Data().Marshal()) 232 if len(lj) == 0 { 233 protocol.App.Log(protocol.LogType_Warning, "WWW - Founded json not meet standards to localize for ", landing.Metadata().URI().Name()) 234 continue 235 } 236 237 var landingCssFile, _ = c.landingsDir.File(landingName + ".css") 238 var mixedHTMLFile = mixCSSToHTML(landing.Data().Marshal(), landingCssFile.Data().Marshal()) 239 240 var localized map[string][]byte 241 localized, err = localizeHTMLFile(mixedHTMLFile, lj) 242 if err != nil { 243 protocol.App.Log(protocol.LogType_Warning, "WWW - Can't localize ", landing.Metadata().URI().Name(), " landing page due to ", err) 244 } 245 for lang, data := range localized { 246 var localizedFileName = landingName + "-" + lang + ".html" 247 var localizedLanding, _ = c.landingsDir.File(localizedFileName) 248 localizedLanding.Data().Unmarshal(data) 249 err = file.Minify(localizedLanding) 250 if err != nil && protocol.AppDebugMode { 251 protocol.App.Log(protocol.LogType_Warning, "WWW Minify -", localizedFileName, "occur this error:", err) 252 } 253 file.Compress(localizedLanding, c.contentEncodings, protocol.BestCompression) 254 } 255 } 256 } 257 } 258 259 // readySWFile read needed files from given repo folder and do some logic to make main.html. 260 func (c *combine) readySWFile() { 261 var libJSDir, _ = c.guiDir.Directory("libjs") 262 var osDir, _ = libJSDir.Directory("os") 263 var swFile, _ = osDir.File("sw.js") 264 if swFile == nil { 265 protocol.App.Log(protocol.LogType_Warning, "WWW - Service-Worker(sw.js) not exist in /gui/libjs/os/sw.js to make locales sw-{{lang}}.js files") 266 return 267 } 268 269 for lang, mainHTMLFile := range c.mainHTMLFiles { 270 var localeSWFileName = "sw-" + lang + ".js" 271 var localeSWFile, _ = c.guiDir.File(localeSWFileName) 272 localeSWFile.Data().Unmarshal(swFile.Data().Marshal()) 273 localeSWFile.Data().Replace([]byte("main.html"), []byte(mainHTMLFile.Metadata().URI().Name()), -1) 274 var err = file.Minify(localeSWFile) 275 if err != nil && protocol.AppDebugMode { 276 protocol.App.Log(protocol.LogType_Warning, "Minify -", localeSWFileName, "occur this error:", err) 277 } 278 file.Compress(localeSWFile, c.contentEncodings, protocol.BestCompression) 279 } 280 }