github.com/geniusesgroup/libgo@v0.0.0-20220713101832-828057a9d3d4/www/js.go (about) 1 /* For license and copyright information please see LEGAL file in repository */ 2 3 package www 4 5 import ( 6 "bytes" 7 "strconv" 8 "strings" 9 10 "../file" 11 "../protocol" 12 ) 13 14 // JS store data for its method 15 type JS struct { 16 imports []protocol.File 17 inlined map[string]protocol.File 18 } 19 20 func (js *JS) checkInlined(srcJS protocol.File) (inlined bool) { 21 _, inlined = js.inlined[srcJS.Metadata().URI().Path()] 22 return 23 } 24 25 // AddJSToJS use to add a JS file to other! 26 func (js *JS) addJSToJS(srcJS, desJS protocol.File) { 27 if js.checkInlined(srcJS) { 28 return 29 } 30 js.inlined[srcJS.Metadata().URI().Path()] = srcJS 31 desJS.Data().Append(srcJS.Data().Marshal()) 32 } 33 34 // AddJSToJSRecursively use to add JSS and all import to JS file! 35 func (js *JS) addJSToJSRecursively(srcJS, desJS protocol.File) { 36 if js.checkInlined(srcJS) { 37 return 38 } 39 // Tell other this file will add to desJS later! 40 js.inlined[srcJS.Metadata().URI().Path()] = srcJS 41 42 var imports = make([]protocol.File, 0, 16) 43 _ = js.extractJSImports(srcJS) 44 for _, imp := range imports { 45 js.addJSToJSRecursively(imp, desJS) 46 } 47 desJS.Data().Append(srcJS.Data().Marshal()) 48 } 49 50 func (js *JS) extractJSImportsRecursively(jsFile protocol.File) (err protocol.Error) { 51 var lastImportIndex = len(js.imports) 52 _ = js.extractJSImports(jsFile) 53 for _, imp := range js.imports[lastImportIndex:] { 54 err = js.extractJSImportsRecursively(imp) 55 } 56 return 57 } 58 59 func (js *JS) extractJSImports(jsFile protocol.File) (err protocol.Error) { 60 var jsData = jsFile.Data().Marshal() 61 var importKeywordIndex, st, en int 62 for { 63 importKeywordIndex = bytes.Index(jsData, []byte("import ")) 64 if importKeywordIndex == -1 { 65 break 66 } 67 68 // TODO::: check and don't parse dynamically import 69 70 // Find start and end of import file location! 71 st = importKeywordIndex + bytes.IndexByte(jsData[importKeywordIndex:], '\'') + 1 72 en = st + bytes.IndexByte(jsData[st:], '\'') 73 var importPath = string(jsData[st:en]) 74 var importFile = file.FindByRelativeFrom(jsFile, importPath) 75 if importFile == nil { 76 if protocol.AppDevMode { 77 protocol.App.Log(protocol.LogType_Warning, "WWW - '", importPath, "' indicate as import in", jsFile.Metadata().URI().Name(), "not found") 78 } 79 // err = 80 } else { 81 js.imports = append(js.imports, importFile) 82 } 83 84 copy(jsData[importKeywordIndex-1:], jsData[en+1:]) 85 jsData = jsData[:len(jsData)-(en-importKeywordIndex)-2] 86 } 87 jsFile.Data().Unmarshal(jsData) 88 return 89 } 90 91 func localeAndMixJSFile(jsFile protocol.File) (mixedData map[string][]byte) { 92 var js = jsFile.Data().Marshal() 93 var jsFileNameWithoutExtension = jsFile.Metadata().URI().NameWithoutExtension() 94 95 var lj = make(localize, 8) 96 var jsonFile, _ = jsFile.ParentDirectory().File(jsFileNameWithoutExtension + ".json") 97 if protocol.AppDevMode && jsonFile == nil { 98 protocol.App.Log(protocol.LogType_Warning, "WWW - ", jsFile.Metadata().URI().Name(), "Can't find JSON localize file, Localization skipped") 99 return 100 } 101 102 var cssFile, _ = jsFile.ParentDirectory().File(jsFileNameWithoutExtension + ".css") 103 if protocol.AppDevMode && cssFile == nil { 104 protocol.App.Log(protocol.LogType_Warning, "WWW - ", jsFile.Metadata().URI().Name(), "Can't find CSS style file, Mix CSS to JS file skipped") 105 } 106 if cssFile != nil { 107 js, _ = mixCSSToJS(js, cssFile.Data().Marshal()) 108 } 109 110 lj.jsonDecoder(jsonFile.Data().Marshal()) 111 mixedData, _ = localizeJSFile(js, lj) 112 113 var htmlFile, _ = jsFile.ParentDirectory().File(jsFileNameWithoutExtension + ".html") 114 if protocol.AppDevMode && htmlFile == nil { 115 protocol.App.Log(protocol.LogType_Warning, "WWW - ", jsFile.Metadata().URI().Name(), "Can't find HTML style file, Mix HTML to JS file skipped") 116 } 117 if htmlFile != nil { 118 var htmlMixedData, _ = localizeHTMLFile(htmlFile.Data().Marshal(), lj) 119 for lang, html := range htmlMixedData { 120 mixHTMLToJS(mixedData[lang], html) 121 } 122 } 123 124 for _, f := range jsFile.ParentDirectory().FindFiles(jsFileNameWithoutExtension+"-template-", 0) { 125 var namesPart = strings.Split(f.Metadata().URI().Name(), "-template-") 126 var htmlMixedData, _ = localizeHTMLFile(f.Data().Marshal(), lj) 127 for lang, f := range htmlMixedData { 128 mixHTMLTemplateToJS(mixedData[lang], f, namesPart[1]) 129 } 130 } 131 132 return 133 } 134 135 // localizeJSFile make and returns number of localize file by number of language indicate in JSON localize text 136 func localizeJSFile(js []byte, lj localize) (mixedData map[string][]byte, err protocol.Error) { 137 mixedData = make(map[string][]byte, len(lj)) 138 for lang, text := range lj { 139 mixedData[lang], _ = replaceLocalizeTextInJS(js, text) 140 } 141 return 142 } 143 144 func replaceLocalizeTextInJS(js []byte, text []string) (mixData []byte, err protocol.Error) { 145 mixData = make([]byte, 0, len(js)) 146 147 var replacerIndex int 148 var bracketIndex int 149 for { 150 replacerIndex = bytes.Index(js, []byte("LocaleText[")) 151 if replacerIndex < 0 { 152 mixData = append(mixData, js...) 153 return 154 } 155 mixData = append(mixData, js[:replacerIndex]...) 156 js = js[replacerIndex:] 157 158 bracketIndex = bytes.IndexByte(js, ']') 159 var textIndex, err = strconv.ParseUint(string(js[11:bracketIndex]), 10, 8) 160 if err != nil { 161 // err = "Index numbers in desire file is not valid, double check your file for bad structures" 162 } else { 163 mixData = append(mixData, text[textIndex]...) 164 } 165 166 js = js[bracketIndex+1:] 167 } 168 }