├── .gitignore ├── LICENSE ├── README.md ├── gojs ├── goja.go ├── gojs.go ├── otto.go ├── parser.go └── templates │ ├── bindata.go │ ├── goja.tmpl │ ├── goja_namespace.tmpl │ ├── otto.tmpl │ └── otto_namespace.tmpl └── main.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.dll 4 | *.so 5 | *.dylib 6 | 7 | # Test binary, build with `go test -c` 8 | *.test 9 | 10 | # Output of the go coverage tool, specifically when used with LiteIDE 11 | *.out 12 | 13 | # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 14 | .glide/ 15 | 16 | modules/ 17 | 18 | gojs-tool -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2017 GoGap 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gojs-tool 2 | 3 | A tool for export package funcs, types, vars for VM (like goja and otto) to use 4 | 5 | ### Install 6 | 7 | ``` 8 | go get -u -v github.com/gogap/gojs-tool 9 | ``` 10 | 11 | 12 | ### Command 13 | 14 | ```bash 15 | > gojs-tool gen --help 16 | 17 | NAME: 18 | gojs-tool gen - generate modules 19 | 20 | USAGE: 21 | gojs-tool gen [command options] packages 22 | 23 | OPTIONS: 24 | --template value, -t value template filename in templates folder without extension (default: "goja") 25 | --recusive, -r recusive generate code 26 | --namespace, -n generate submodules loader, access object by dot, only work while recusive enabled 27 | --gopath value the package in which GOPATH [$GOPATH] 28 | ``` 29 | 30 | 31 | ### Example 32 | 33 | ```bash 34 | example> pwd 35 | github.com/xujinzheng/playgo/example 36 | 37 | example> gojs-tool gen -t otto -r -n github.com/sirupsen/logrus ## for otto 38 | example> gojs-tool gen -t goja -r -n github.com/sirupsen/logrus ## for goja 39 | 40 | example> tree modules 41 | modules 42 | └── github.com 43 | └── sirupsen 44 | └── logrus 45 | ├── hooks 46 | │   ├── hooks.go 47 | │   ├── syslog 48 | │   │   └── syslog.go 49 | │   └── test 50 | │   └── test.go 51 | └── logrus.go 52 | 53 | ``` 54 | 55 | #### Auto generated code (goja) 56 | 57 | `modules/github.com/sirupsen/logrus/logrus.go` 58 | 59 | ```go 60 | package logrus 61 | 62 | import ( 63 | original_logrus "github.com/sirupsen/logrus" 64 | ) 65 | 66 | import ( 67 | "github.com/dop251/goja" 68 | "github.com/gogap/gojs-tool/gojs" 69 | ) 70 | 71 | var ( 72 | module = gojs.NewGojaModule("logrus") 73 | ) 74 | 75 | func init() { 76 | module.Set( 77 | gojs.Objects{ 78 | // Functions 79 | "AddHook": original_logrus.AddHook, 80 | "Debug": original_logrus.Debug, 81 | "Debugf": original_logrus.Debugf, 82 | "Debugln": original_logrus.Debugln, 83 | "Error": original_logrus.Error, 84 | "Errorf": original_logrus.Errorf, 85 | "Errorln": original_logrus.Errorln, 86 | "Exit": original_logrus.Exit, 87 | "Fatal": original_logrus.Fatal, 88 | //..........more funcs.......... 89 | 90 | // Var and consts 91 | "AllLevels": original_logrus.AllLevels, 92 | "DebugLevel": original_logrus.DebugLevel, 93 | "ErrorKey": original_logrus.ErrorKey, 94 | "ErrorLevel": original_logrus.ErrorLevel, 95 | "FatalLevel": original_logrus.FatalLevel, 96 | "FieldKeyLevel": original_logrus.FieldKeyLevel, 97 | "FieldKeyMsg": original_logrus.FieldKeyMsg, 98 | "FieldKeyTime": original_logrus.FieldKeyTime, 99 | "InfoLevel": original_logrus.InfoLevel, 100 | "PanicLevel": original_logrus.PanicLevel, 101 | "WarnLevel": original_logrus.WarnLevel, 102 | 103 | // Types (value type) 104 | "Entry": func() original_logrus.Entry { return original_logrus.Entry{} }, 105 | "JSONFormatter": func() original_logrus.JSONFormatter { return original_logrus.JSONFormatter{} }, 106 | "Logger": func() original_logrus.Logger { return original_logrus.Logger{} }, 107 | "MutexWrap": func() original_logrus.MutexWrap { return original_logrus.MutexWrap{} }, 108 | "TextFormatter": func() original_logrus.TextFormatter { return original_logrus.TextFormatter{} }, 109 | 110 | // Types (pointer type) 111 | "NewJSONFormatter": func() *original_logrus.JSONFormatter { return &original_logrus.JSONFormatter{} }, 112 | "NewLogger": func() *original_logrus.Logger { return &original_logrus.Logger{} }, 113 | "NewMutexWrap": func() *original_logrus.MutexWrap { return &original_logrus.MutexWrap{} }, 114 | "NewTextFormatter": func() *original_logrus.TextFormatter { return &original_logrus.TextFormatter{} }, 115 | }, 116 | ).Register() 117 | } 118 | 119 | func Enable(runtime *goja.Runtime) { 120 | module.Enable(runtime) 121 | } 122 | 123 | 124 | ``` 125 | 126 | #### Auto generated code (otto) 127 | 128 | ```go 129 | package logrus 130 | 131 | import ( 132 | original_logrus "github.com/sirupsen/logrus" 133 | ) 134 | 135 | import ( 136 | "github.com/robertkrimen/otto" 137 | ) 138 | 139 | type Logrus struct { 140 | // Functions 141 | AddHook interface{} 142 | Debug interface{} 143 | Debugf interface{} 144 | Debugln interface{} 145 | Error interface{} 146 | //..........more funcs.......... 147 | 148 | // Var and consts 149 | AllLevels interface{} 150 | DebugLevel interface{} 151 | ErrorKey interface{} 152 | ErrorLevel interface{} 153 | //..........more vars.......... 154 | 155 | // Types (value type) 156 | Entry interface{} 157 | JSONFormatter interface{} 158 | Logger interface{} 159 | MutexWrap interface{} 160 | TextFormatter interface{} 161 | 162 | // Types (pointer type) 163 | NewJSONFormatter interface{} 164 | NewLogger interface{} 165 | NewMutexWrap interface{} 166 | NewTextFormatter interface{} 167 | } 168 | 169 | var ( 170 | module = &Logrus{ 171 | // Functions 172 | AddHook: original_logrus.AddHook, 173 | Debug: original_logrus.Debug, 174 | Debugf: original_logrus.Debugf, 175 | Debugln: original_logrus.Debugln, 176 | //..........more funcs.......... 177 | 178 | // Var and consts 179 | AllLevels: original_logrus.AllLevels, 180 | DebugLevel: original_logrus.DebugLevel, 181 | ErrorKey: original_logrus.ErrorKey, 182 | ErrorLevel: original_logrus.ErrorLevel, 183 | //..........more vars.......... 184 | 185 | // Types (value type) 186 | Entry: func() original_logrus.Entry { return original_logrus.Entry{} }, 187 | JSONFormatter: func() original_logrus.JSONFormatter { return original_logrus.JSONFormatter{} }, 188 | Logger: func() original_logrus.Logger { return original_logrus.Logger{} }, 189 | MutexWrap: func() original_logrus.MutexWrap { return original_logrus.MutexWrap{} }, 190 | TextFormatter: func() original_logrus.TextFormatter { return original_logrus.TextFormatter{} }, 191 | 192 | // Types (pointer type) 193 | NewJSONFormatter: func() *original_logrus.JSONFormatter { return &original_logrus.JSONFormatter{} }, 194 | NewLogger: func() *original_logrus.Logger { return &original_logrus.Logger{} }, 195 | NewMutexWrap: func() *original_logrus.MutexWrap { return &original_logrus.MutexWrap{} }, 196 | NewTextFormatter: func() *original_logrus.TextFormatter { return &original_logrus.TextFormatter{} }, 197 | } 198 | ) 199 | 200 | func Enable(o *otto.Otto) { 201 | o.Set("logrus", module) 202 | } 203 | 204 | ``` 205 | 206 | 207 | #### Use native module in goja 208 | 209 | ```go 210 | 211 | package main 212 | 213 | import ( 214 | "fmt" 215 | ) 216 | 217 | import ( 218 | "github.com/xujinzheng/playgo/example/modules/github.com/denverdino/aliyungo" 219 | "github.com/xujinzheng/playgo/example/modules/github.com/sirupsen/logrus" 220 | ) 221 | 222 | import ( 223 | "github.com/dop251/goja" 224 | "github.com/dop251/goja_nodejs/require" 225 | ) 226 | 227 | func main() { 228 | 229 | registry := new(require.Registry) 230 | 231 | runtime := goja.New() 232 | 233 | registry.Enable(runtime) 234 | logrus.Enable(runtime) 235 | aliyungo.Enable(runtime) 236 | 237 | _, err := runtime.RunString(` 238 | var entryA = logrus.NewEntry() 239 | var entryB = logrus.Entry() 240 | 241 | logrus.Println("entryA:",entryA) 242 | logrus.Println("entryB:",entryB) 243 | 244 | logrus.WithField("Hello", "World").Println("I am gojs") 245 | 246 | // gojs-tool gen --template goja --recusive --namespace github.com/denverdino/aliyungo 247 | // wrapper packages in namespace, access by dot 248 | var client = aliyungo.cs.NewClient() 249 | 250 | logrus.Println("client", client) 251 | `) 252 | 253 | if err != nil { 254 | fmt.Println(err) 255 | return 256 | } 257 | } 258 | 259 | 260 | ``` 261 | 262 | 263 | ```bash 264 | example> go run main.go 265 | INFO[0000] entryA: &{ map[] 0001-01-01 00:00:00 +0000 UTC panic } 266 | INFO[0000] entryB: { map[] 0001-01-01 00:00:00 +0000 UTC panic } 267 | INFO[0000] I am gojs Hello=World 268 | INFO[0000] client &{ https://cs.aliyuncs.com 2015-12-15 false 0xc420399e60} 269 | ``` 270 | 271 | 272 | #### Use native module in otto 273 | 274 | ```go 275 | 276 | package main 277 | 278 | import ( 279 | "fmt" 280 | ) 281 | 282 | import ( 283 | "github.com/xujinzheng/playgo/example/modules/github.com/denverdino/aliyungo" 284 | "github.com/xujinzheng/playgo/example/modules/github.com/sirupsen/logrus" 285 | ) 286 | 287 | import ( 288 | "github.com/robertkrimen/otto" 289 | ) 290 | 291 | func main() { 292 | 293 | runtime := otto.New() 294 | 295 | logrus.Enable(runtime) 296 | aliyungo.Enable(runtime) 297 | 298 | _, err := runtime.Run(` 299 | var entryA = logrus.NewEntry(undefined) 300 | var entryB = logrus.Entry() 301 | 302 | logrus.Println("entryA:",entryA) 303 | logrus.Println("entryB:",entryB) 304 | 305 | logrus.WithField("Hello", "World").Println("I am gojs") 306 | 307 | // gojs-tool gen --template otto --recusive --namespace github.com/denverdino/aliyungo 308 | // wrapper packages in namespace, access by dot 309 | var client = aliyungo.cs.NewClient("","") 310 | 311 | logrus.Println("client", client) 312 | `) 313 | 314 | if err != nil { 315 | fmt.Println(err) 316 | return 317 | } 318 | } 319 | 320 | ``` 321 | 322 | 323 | ```bash 324 | example> go run main.go 325 | INFO[0000] entryA: &{ map[] 0001-01-01 00:00:00 +0000 UTC panic } 326 | INFO[0000] entryB: { map[] 0001-01-01 00:00:00 +0000 UTC panic } 327 | INFO[0000] I am gojs Hello=World 328 | INFO[0000] client &{ https://cs.aliyuncs.com 2015-12-15 false 0xc4201824b0} 329 | ``` -------------------------------------------------------------------------------- /gojs/goja.go: -------------------------------------------------------------------------------- 1 | package gojs 2 | 3 | import ( 4 | "sync" 5 | 6 | "github.com/dop251/goja" 7 | "github.com/dop251/goja_nodejs/require" 8 | ) 9 | 10 | type GojaModule struct { 11 | name string 12 | sets map[string]interface{} 13 | 14 | runtime *goja.Runtime 15 | once sync.Once 16 | } 17 | 18 | func NewGojaModule(name string) Module { 19 | return &GojaModule{ 20 | name: name, 21 | sets: make(map[string]interface{}), 22 | } 23 | } 24 | 25 | func (p *GojaModule) String() string { 26 | return p.name 27 | } 28 | 29 | func (p *GojaModule) Name() string { 30 | return p.name 31 | } 32 | 33 | func (p *GojaModule) Set(objects Objects) Module { 34 | 35 | for k, v := range objects { 36 | p.sets[k] = v 37 | } 38 | 39 | return p 40 | } 41 | 42 | func (p *GojaModule) Require(runtime *goja.Runtime, module *goja.Object) { 43 | 44 | o := module.Get("exports").(*goja.Object) 45 | 46 | for k, v := range p.sets { 47 | o.Set(k, v) 48 | } 49 | } 50 | 51 | func (p *GojaModule) Enable(runtime Runtime) { 52 | runtime.Set(p.Name(), require.Require(runtime.(*goja.Runtime), p.Name())) 53 | } 54 | 55 | func (p *GojaModule) Register() Module { 56 | p.once.Do(func() { 57 | require.RegisterNativeModule(p.Name(), p.Require) 58 | }) 59 | 60 | return p 61 | } 62 | -------------------------------------------------------------------------------- /gojs/gojs.go: -------------------------------------------------------------------------------- 1 | package gojs 2 | 3 | type Objects map[string]interface{} 4 | 5 | type Runtime interface { 6 | Set(string, interface{}) 7 | } 8 | 9 | type Object interface { 10 | Set(string, interface{}) 11 | Get(string) interface{} 12 | } 13 | 14 | type Module interface { 15 | Name() string 16 | Set(objects Objects) Module 17 | Enable(Runtime) 18 | Register() Module 19 | } 20 | 21 | type TemplateVars struct { 22 | PackageName string 23 | PackagePath string 24 | PackageVars map[string]string 25 | PackageTypes map[string]string 26 | PackageFuncs map[string]string 27 | 28 | Args map[string]interface{} 29 | } 30 | -------------------------------------------------------------------------------- /gojs/otto.go: -------------------------------------------------------------------------------- 1 | package gojs 2 | 3 | import ( 4 | "github.com/robertkrimen/otto" 5 | ) 6 | 7 | type OttoModule struct { 8 | name string 9 | sets map[string]interface{} 10 | 11 | runtime *otto.Otto 12 | } 13 | 14 | func NewOttoModule(name string) Module { 15 | return &OttoModule{ 16 | name: name, 17 | sets: make(map[string]interface{}), 18 | } 19 | } 20 | 21 | func (p *OttoModule) String() string { 22 | return p.name 23 | } 24 | 25 | func (p *OttoModule) Name() string { 26 | return p.name 27 | } 28 | 29 | func (p *OttoModule) Register() Module { 30 | return p 31 | } 32 | 33 | func (p *OttoModule) Set(objects Objects) Module { 34 | 35 | for k, v := range objects { 36 | p.sets[k] = v 37 | } 38 | 39 | return p 40 | } 41 | 42 | func (p *OttoModule) Enable(runtime Runtime) { 43 | for k, v := range p.sets { 44 | runtime.Set(k, v) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /gojs/parser.go: -------------------------------------------------------------------------------- 1 | package gojs 2 | 3 | import ( 4 | "bytes" 5 | "go/format" 6 | "strings" 7 | "text/template" 8 | 9 | "github.com/gogap/gocoder" 10 | "github.com/gogap/gojs-tool/gojs/templates" 11 | ) 12 | 13 | type GenerateOptions struct { 14 | TemplateName string 15 | PackagePath string 16 | PackageAlias string 17 | GoPath string 18 | ProjectPath string 19 | 20 | TemplateVars *TemplateVars 21 | 22 | Args interface{} 23 | } 24 | 25 | func Parser(pkgPath string, gopath string) (vars *TemplateVars, err error) { 26 | pkg, err := gocoder.NewGoPackage(pkgPath, 27 | gocoder.OptionGoPath(gopath), 28 | ) 29 | 30 | if err != nil { 31 | return 32 | } 33 | 34 | tmplVars := &TemplateVars{ 35 | PackageName: pkg.Name(), 36 | PackagePath: pkg.Path(), 37 | PackageFuncs: make(map[string]string), 38 | PackageTypes: make(map[string]string), 39 | PackageVars: make(map[string]string), 40 | } 41 | 42 | numFuncs := pkg.NumFuncs() 43 | 44 | for i := 0; i < numFuncs; i++ { 45 | goFunc := pkg.Func(i) 46 | 47 | if !isExported(goFunc.Name()) { 48 | continue 49 | } 50 | 51 | if len(goFunc.Receiver()) > 0 { 52 | continue 53 | } 54 | 55 | tmplVars.PackageFuncs[goFunc.Name()] = goFunc.Name() 56 | } 57 | 58 | numVars := pkg.NumVars() 59 | 60 | for i := 0; i < numVars; i++ { 61 | goVar := pkg.Var(i) 62 | 63 | if !isExported(goVar.Name()) { 64 | continue 65 | } 66 | 67 | tmplVars.PackageVars[goVar.Name()] = goVar.Name() 68 | } 69 | 70 | numTypes := pkg.NumTypes() 71 | 72 | for i := 0; i < numTypes; i++ { 73 | goType := pkg.Type(i) 74 | 75 | if !isExported(goType.Name()) { 76 | continue 77 | } 78 | 79 | if goType.IsStruct() { 80 | tmplVars.PackageTypes[goType.Name()] = goType.Name() 81 | } 82 | 83 | } 84 | 85 | vars = tmplVars 86 | 87 | return 88 | } 89 | 90 | func GenerateCode(options GenerateOptions) (code string, err error) { 91 | 92 | tmplBytes, err := templates.Asset(options.TemplateName + ".tmpl") 93 | if err != nil { 94 | return 95 | } 96 | 97 | tmpl, err := template.New(options.TemplateName).Funcs(templateFuncs()).Parse(string(tmplBytes)) 98 | if err != nil { 99 | return 100 | } 101 | 102 | buf := bytes.NewBuffer(nil) 103 | 104 | err = tmpl.Execute(buf, options.TemplateVars) 105 | 106 | if err != nil { 107 | return 108 | } 109 | 110 | if len(options.PackageAlias) > 0 { 111 | options.TemplateVars.PackageName = options.PackageAlias 112 | } 113 | 114 | codeBytes, err := format.Source(buf.Bytes()) 115 | 116 | if err != nil { 117 | return 118 | } 119 | 120 | code = string(codeBytes) 121 | 122 | return 123 | } 124 | 125 | func isExported(v string) bool { 126 | if len(v) == 0 { 127 | return false 128 | } 129 | 130 | if v[0] >= 'A' && v[0] <= 'Z' { 131 | return true 132 | } 133 | 134 | return false 135 | } 136 | 137 | func templateFuncs() map[string]interface{} { 138 | return map[string]interface{}{ 139 | "exist": func(v map[string]string, key string) bool { 140 | _, exist := v[key] 141 | return exist 142 | }, 143 | "toTitle": func(v string) string { 144 | if len(v) == 0 { 145 | return v 146 | } 147 | 148 | return strings.ToUpper(string(v[0])) + v[1:] 149 | }, 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /gojs/templates/bindata.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-bindata. 2 | // sources: 3 | // goja.tmpl 4 | // goja_namespace.tmpl 5 | // otto.tmpl 6 | // otto_namespace.tmpl 7 | // DO NOT EDIT! 8 | 9 | package templates 10 | 11 | import ( 12 | "bytes" 13 | "compress/gzip" 14 | "fmt" 15 | "io" 16 | "io/ioutil" 17 | "os" 18 | "path/filepath" 19 | "strings" 20 | "time" 21 | ) 22 | 23 | func bindataRead(data []byte, name string) ([]byte, error) { 24 | gz, err := gzip.NewReader(bytes.NewBuffer(data)) 25 | if err != nil { 26 | return nil, fmt.Errorf("Read %q: %v", name, err) 27 | } 28 | 29 | var buf bytes.Buffer 30 | _, err = io.Copy(&buf, gz) 31 | clErr := gz.Close() 32 | 33 | if err != nil { 34 | return nil, fmt.Errorf("Read %q: %v", name, err) 35 | } 36 | if clErr != nil { 37 | return nil, err 38 | } 39 | 40 | return buf.Bytes(), nil 41 | } 42 | 43 | type asset struct { 44 | bytes []byte 45 | info os.FileInfo 46 | } 47 | 48 | type bindataFileInfo struct { 49 | name string 50 | size int64 51 | mode os.FileMode 52 | modTime time.Time 53 | } 54 | 55 | func (fi bindataFileInfo) Name() string { 56 | return fi.name 57 | } 58 | func (fi bindataFileInfo) Size() int64 { 59 | return fi.size 60 | } 61 | func (fi bindataFileInfo) Mode() os.FileMode { 62 | return fi.mode 63 | } 64 | func (fi bindataFileInfo) ModTime() time.Time { 65 | return fi.modTime 66 | } 67 | func (fi bindataFileInfo) IsDir() bool { 68 | return false 69 | } 70 | func (fi bindataFileInfo) Sys() interface{} { 71 | return nil 72 | } 73 | 74 | var _gojaTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x53\x4d\x6b\x1b\x31\x10\x3d\xaf\x7e\xc5\x20\xe2\x22\x85\x78\x4d\x0b\xbd\x18\x7c\xeb\xc7\xa9\x4e\x48\x4b\xae\x45\x5e\x8f\x37\x72\x76\xa5\x45\xd2\xc6\x0d\x62\xfe\x7b\x91\x36\x5b\x6f\x82\x4b\x31\xcd\x4d\xa3\x79\xef\xe9\xcd\x68\xa6\x53\xd5\x83\xaa\x11\x62\x2c\x6f\x86\xe3\x5a\xb5\x48\xc4\x58\x8c\x17\xdd\x43\x9d\xa2\xe5\x4a\x74\x4e\x9b\xb0\x03\x6e\x9d\xae\xb5\x51\xcd\xcf\x99\xe7\x30\x65\x48\x98\x13\x31\xdd\x76\xd6\x05\x10\xac\x38\xb2\x89\x80\x1f\xd5\x6f\x54\xb8\x27\xe2\x4c\xb2\x09\x98\xd7\x3a\xdc\xf7\x9b\xb2\xb2\xed\x62\x6b\xbb\x0f\x1f\xdf\x2f\x6a\xbb\x57\xfc\x65\xa6\xb6\xb5\xea\x52\xc2\xcf\x83\xb5\x4d\x3e\x65\xa1\x47\xe5\x92\x4a\x6b\xb7\x7d\x83\xb0\x82\x94\x28\xd7\x78\xf8\x6a\xf7\xea\x5b\xbe\x14\xfc\x75\x7d\x5c\x26\xe6\xae\x37\x15\x68\xa3\x83\x90\x10\x47\x85\xf2\x3b\x06\xc1\x8a\x22\xcb\x5c\x6f\xf6\x58\x05\x1f\x59\x51\x14\x31\xce\x21\x55\xf5\xa5\x37\x95\x5f\xae\x46\xc1\x1c\x12\x25\xc4\x62\x01\x29\x0a\xda\x1a\x3f\x32\x9c\x32\x35\xc2\x85\xdd\xec\xd3\xcb\x57\xf9\xf4\x09\x77\xda\x20\x2c\x57\x70\x42\x84\xc7\x38\xa2\x89\xf8\x12\xa6\xad\x2c\x87\xdc\xc0\x27\xba\x1a\x1f\x41\xb3\x4d\x7f\x36\x58\xb8\x53\x0e\x94\xd9\x42\x65\x8d\x0f\x67\xfa\xb8\x53\xee\xad\x6c\xfc\x78\xea\xd0\x83\x78\x54\x4d\x8f\x10\x9e\x3a\x94\xe7\x59\xc9\xfc\xbf\x79\x19\x07\x32\xfd\xa0\x90\x30\xf3\xe5\xcc\x43\x04\x87\xa1\x77\x66\x08\x23\x01\x71\x18\x4d\x4f\x1f\x39\x71\xf7\x8f\x22\x3a\xab\x4d\x40\x37\x2d\xe3\xec\x22\xf2\xf8\x18\x3c\x5c\x0f\x8c\x84\x1a\xab\x98\xf9\xb4\x4f\x7c\x8d\x07\xfe\x47\x31\x2f\xd4\x33\x4d\xef\xc0\xd8\x00\x02\x7f\x69\x1f\x8e\x33\x38\x95\x93\x23\x3e\xf5\xea\x78\x7d\xba\x5d\x97\xaf\xfa\xf5\xee\x3f\x1a\x86\x66\x3b\xb5\x3a\x09\x33\x42\x96\xb7\x58\x6b\x1f\xd0\x09\xc9\xe8\x79\xe5\x3e\x1b\xb5\x69\x50\xb8\xde\x04\xdd\x22\x5c\xa6\x6d\x2f\x6f\x87\x68\xba\x89\x2f\x71\x92\xd1\xef\x00\x00\x00\xff\xff\xa0\xd7\xad\xc5\xaf\x04\x00\x00") 75 | 76 | func gojaTmplBytes() ([]byte, error) { 77 | return bindataRead( 78 | _gojaTmpl, 79 | "goja.tmpl", 80 | ) 81 | } 82 | 83 | func gojaTmpl() (*asset, error) { 84 | bytes, err := gojaTmplBytes() 85 | if err != nil { 86 | return nil, err 87 | } 88 | 89 | info := bindataFileInfo{name: "goja.tmpl", size: 1199, mode: os.FileMode(420), modTime: time.Unix(1509100893, 0)} 90 | a := &asset{bytes: bytes, info: info} 91 | return a, nil 92 | } 93 | 94 | var _goja_namespaceTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x92\xcd\x6a\xe3\x30\x14\x85\xd7\xd2\x53\x5c\xc4\x30\xd8\x83\x47\x61\x06\x66\x13\x98\x45\x17\xa5\xab\xa6\x21\x79\x80\x22\xdb\xb7\x8a\x92\xd8\x72\x65\xb9\xb4\x08\xbd\x7b\x11\x72\x7e\x9c\x1f\x93\xec\x92\x6b\xe9\x9c\xf3\xe9\xdc\x46\x14\x1b\x21\x11\x9c\xe3\xf3\xf8\x73\x26\x2a\xf4\x9e\x52\x55\x35\xda\x58\x48\x28\x61\x52\xd9\x55\x97\xf3\x42\x57\x93\x52\x37\x7f\xff\xfd\x99\x48\xbd\x16\xec\xea\x97\xd7\x5a\x97\xb8\x6e\x27\x06\xdf\x3b\x65\x90\xd1\xf4\x58\xce\xb9\xdf\x60\x44\x2d\x11\x7e\xb4\x5d\xfe\xac\xcb\x6e\x8b\x30\xfd\x0f\xfc\xc1\xc8\x96\x2f\x77\xa3\xd6\x7b\x4a\x98\x73\x87\x43\xbb\x84\x73\x61\x57\xde\xb3\xa8\x84\x75\xe9\x7d\x30\xb0\x5f\xcd\x39\x06\xb4\xd6\x74\x85\x05\x77\x9f\xed\x25\xd7\x5e\xf0\x57\x00\xe4\x2f\xf9\x1a\x0b\xbb\x4f\x00\xde\x53\x4f\xe9\x5b\x57\x17\xa0\x6a\x65\x93\x34\x38\xf6\xf8\x7c\x81\x52\xb5\x16\xcd\x4c\x58\xf5\x81\x51\x35\x61\xa7\x51\x59\x06\x8b\x78\x21\xdd\x6b\xf5\x83\xc4\x74\xb5\x55\x15\xf6\xe6\x8b\xf8\x2f\x83\x2a\x42\x1c\x47\x0a\xc6\x94\x34\x1b\x19\xd0\x7e\x9e\x7a\x38\x4a\x6e\x7e\x87\xc0\x44\xc6\x5e\x62\x0a\x07\xc0\x41\xcc\x0c\x2e\xd6\xd6\x63\xa6\x3c\x19\x04\xce\xfa\x4c\xb1\x48\xe2\x29\x25\x3a\xe4\x89\x70\xfc\x09\x6d\xc2\xf0\x33\x2c\x4f\x7b\x76\x97\x86\x06\x6e\x86\xd1\x7c\x19\xc4\x46\xb2\x65\xd0\x6c\x24\xbf\x7e\x20\xbd\xd8\xf8\x63\x2d\xf2\xed\x95\x92\xd2\x7b\x56\x0f\xc6\x77\x8f\x0f\x8d\x86\x61\x28\xe9\xc7\x3b\xc8\x33\xb4\xb1\xb6\x4e\x3b\x0a\x2b\xf8\x1d\x00\x00\xff\xff\x27\x41\xa9\x49\x1b\x04\x00\x00") 95 | 96 | func goja_namespaceTmplBytes() ([]byte, error) { 97 | return bindataRead( 98 | _goja_namespaceTmpl, 99 | "goja_namespace.tmpl", 100 | ) 101 | } 102 | 103 | func goja_namespaceTmpl() (*asset, error) { 104 | bytes, err := goja_namespaceTmplBytes() 105 | if err != nil { 106 | return nil, err 107 | } 108 | 109 | info := bindataFileInfo{name: "goja_namespace.tmpl", size: 1051, mode: os.FileMode(420), modTime: time.Unix(1509097895, 0)} 110 | a := &asset{bytes: bytes, info: info} 111 | return a, nil 112 | } 113 | 114 | var _ottoTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x95\xd1\x6f\xda\x30\x10\xc6\x9f\xf1\x5f\x71\xb2\xa0\x4a\x2a\x08\xef\x48\xbc\x6d\x7b\x6c\x2b\xad\xea\xeb\x64\xc2\x41\x3d\xc0\x8e\xec\x4b\xbb\xca\xba\xff\x7d\x72\xbc\x94\x10\xd0\xa6\x64\x6f\x76\xf8\xee\xbe\x2f\xf6\xef\x42\xa5\xca\x83\xda\x23\x84\x50\x3c\xa5\xe5\x83\x3a\x21\xb3\x10\x21\x4c\xab\xc3\x3e\xee\x56\xeb\xac\x72\xda\xd0\x0e\xa4\x75\x7a\xaf\x8d\x3a\xfe\x98\x79\x09\xdd\x8a\x1c\x16\xcc\x42\x9f\x2a\xeb\x08\x32\x31\x39\x57\x33\x83\x3c\x77\x7f\x52\xf4\xca\x2c\x45\x2e\x3a\x62\xb9\xd7\xf4\x5a\x6f\x8a\xd2\x9e\x96\xce\x6e\xd0\xd1\xc1\xe9\x13\x9a\xa5\x25\xb2\x8d\x36\x84\xa9\x27\x57\x97\x94\xf2\x40\x46\xf6\x59\xd3\x11\x2f\x33\xc4\xd8\xf4\x51\xc5\xb7\xe9\xc8\x99\x21\x6d\x20\xc4\x5c\x0b\x88\xc9\xbe\xd5\xa6\xf4\xab\x75\x5b\xde\x6c\x99\xc5\x64\xb9\x84\xb8\x26\x6d\x8d\x4f\x6a\xa7\xcc\x1e\x61\x6a\x37\x3f\x63\xb3\x79\xb3\xfa\x82\x3b\x6d\x10\x56\x6b\xb8\x6a\x10\x42\x2b\x65\x06\x6d\x08\xdd\x4e\x95\x18\x38\x35\x43\xb3\x8d\x21\xa3\xcd\x8b\x72\xa0\xcc\x16\x4a\x6b\x3c\x0d\xf2\x7a\x51\x6e\x98\xd5\xf3\x47\x85\x1e\xb2\x37\x75\xac\x11\xe2\x01\xe5\x43\xec\x9a\xea\x31\x7e\x95\x6d\x44\x67\xc7\xc1\x7e\x0b\x98\x1a\x7c\x7f\x4c\xfa\xa8\x69\x39\x9c\xf9\x08\xa0\x7c\xc0\x77\xf9\xd9\xaf\x21\xb0\x29\xd2\x3b\x30\x96\x20\xc3\x5f\xda\xd3\xf9\xba\xbb\xcd\xf2\x56\xdd\x79\x76\xfd\x56\x68\xb6\xe7\xae\xed\x86\x85\x10\x6f\xca\x45\x70\x4f\x76\x5b\x1f\x11\xd6\x70\xd7\x27\x2e\x88\xc9\x3f\x59\xeb\xc1\x36\x86\xb6\x8b\x3b\x59\x41\x77\xea\x8a\xf4\x53\x2a\x66\x9e\xff\x31\x68\xaf\xe9\x16\x82\x23\x18\xfc\xbf\x00\xb7\xc0\x1c\x43\xe6\x55\x8a\x96\x93\x5d\x6d\xca\x2c\x87\x99\x2f\x66\x1e\x02\x38\xa4\xda\x99\xb4\x0d\x0c\x2c\xa1\x8d\xdb\x75\xb8\xf1\xec\xaf\xf1\x7b\x9c\x0f\x07\x7d\x1c\xe9\x03\x51\xef\xb3\x7e\xe3\x98\xee\x7b\xe7\x74\x37\xfe\xa0\x3e\x27\xe7\x62\x74\x26\x1c\x3f\xe6\xd1\x0d\xbe\x1a\xb5\x39\x62\x66\xe1\x3e\x7e\xe4\x8b\x47\x22\x9b\xc7\xa9\xb1\xc5\x77\xa4\x4c\xf6\xff\x8f\xe4\x1c\xd2\xb0\xe5\x82\x7f\x07\x00\x00\xff\xff\x53\xa2\xbf\xfd\xb4\x06\x00\x00") 115 | 116 | func ottoTmplBytes() ([]byte, error) { 117 | return bindataRead( 118 | _ottoTmpl, 119 | "otto.tmpl", 120 | ) 121 | } 122 | 123 | func ottoTmpl() (*asset, error) { 124 | bytes, err := ottoTmplBytes() 125 | if err != nil { 126 | return nil, err 127 | } 128 | 129 | info := bindataFileInfo{name: "otto.tmpl", size: 1716, mode: os.FileMode(420), modTime: time.Unix(1509119304, 0)} 130 | a := &asset{bytes: bytes, info: info} 131 | return a, nil 132 | } 133 | 134 | var _otto_namespaceTmpl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x92\x41\x6f\xe2\x30\x10\x85\xcf\xf6\xaf\x98\x8d\xf6\x90\x20\xd6\xdc\x57\xca\xa1\x07\xd4\x53\x5b\x24\xaa\x5e\x10\x07\x3b\x0c\xc1\x10\xdb\x91\xe3\x54\x95\x5c\xff\xf7\xca\x31\xa1\xb4\xa2\x88\x1e\x22\xc5\xce\xcc\x7c\xef\xbd\x49\xcb\xab\x03\xaf\x11\xbc\x67\x8b\xf4\xfa\xc8\x15\x86\x40\xa9\x54\xad\xb1\x0e\x72\x4a\xb2\x5a\xba\x5d\x2f\x58\x65\xd4\xcc\x1a\x81\xd6\x1d\xac\x54\xa8\x67\xc6\x39\x93\xd1\xe2\xbc\xd6\xfb\x7f\x60\xb9\xae\x11\xfe\x76\xbd\x78\x30\x9b\xbe\x41\xf8\x5f\x02\xbb\xb3\x75\xc7\x96\xe3\x55\x17\x02\x25\x99\xf7\x9f\x45\x23\x7e\xc1\xdd\x2e\x84\x2c\x4d\x42\xbd\x09\x21\x02\xb6\xbd\xae\x60\xae\xb9\x68\x30\xb7\xbd\x76\x52\x21\x4c\x22\x9e\x3d\x39\x67\x0a\xf0\xb7\x93\x21\xa2\x2f\x91\x93\x71\xf6\x95\x52\x9c\x84\xc4\x3e\x4a\x5e\xb9\x05\xb4\xc3\x63\x6c\x3a\x1a\xb1\x87\x41\xca\x0b\x6f\x7a\x4c\x77\xb5\x19\x0e\x20\xb5\x43\xbb\xe5\x15\xfa\xd8\xac\x4e\xa2\x14\x3f\x60\xae\x78\xbb\xea\x9c\x95\xba\x5e\x9f\xd5\x15\xf4\x77\x5e\x28\x31\x62\x3f\x1d\x44\x95\x70\x54\xcd\xee\xd1\xe5\x17\xe3\x4d\x26\xb3\x82\x12\xb9\x8d\x3d\x7f\x4a\x2d\x9b\x18\x1f\x69\xb9\x96\x55\x8e\xd6\x16\x94\xc4\xa9\x47\x0b\xe3\x64\x23\xf6\x6c\xfe\x16\xd7\x9c\xdf\xd0\x9c\x9c\xae\xae\x49\x58\x43\x39\xc6\xc4\xf2\xc9\x95\x85\xfc\xf4\xe9\xdd\x99\x67\xe9\x1a\x0c\xa7\xc8\xd2\xef\x42\xc9\x98\xc2\x32\xa5\xf0\x0d\x3c\x85\xa4\xae\xa0\x81\x7e\x04\x00\x00\xff\xff\xc6\x90\x6e\x8a\xff\x02\x00\x00") 135 | 136 | func otto_namespaceTmplBytes() ([]byte, error) { 137 | return bindataRead( 138 | _otto_namespaceTmpl, 139 | "otto_namespace.tmpl", 140 | ) 141 | } 142 | 143 | func otto_namespaceTmpl() (*asset, error) { 144 | bytes, err := otto_namespaceTmplBytes() 145 | if err != nil { 146 | return nil, err 147 | } 148 | 149 | info := bindataFileInfo{name: "otto_namespace.tmpl", size: 767, mode: os.FileMode(420), modTime: time.Unix(1509120267, 0)} 150 | a := &asset{bytes: bytes, info: info} 151 | return a, nil 152 | } 153 | 154 | // Asset loads and returns the asset for the given name. 155 | // It returns an error if the asset could not be found or 156 | // could not be loaded. 157 | func Asset(name string) ([]byte, error) { 158 | cannonicalName := strings.Replace(name, "\\", "/", -1) 159 | if f, ok := _bindata[cannonicalName]; ok { 160 | a, err := f() 161 | if err != nil { 162 | return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) 163 | } 164 | return a.bytes, nil 165 | } 166 | return nil, fmt.Errorf("Asset %s not found", name) 167 | } 168 | 169 | // MustAsset is like Asset but panics when Asset would return an error. 170 | // It simplifies safe initialization of global variables. 171 | func MustAsset(name string) []byte { 172 | a, err := Asset(name) 173 | if err != nil { 174 | panic("asset: Asset(" + name + "): " + err.Error()) 175 | } 176 | 177 | return a 178 | } 179 | 180 | // AssetInfo loads and returns the asset info for the given name. 181 | // It returns an error if the asset could not be found or 182 | // could not be loaded. 183 | func AssetInfo(name string) (os.FileInfo, error) { 184 | cannonicalName := strings.Replace(name, "\\", "/", -1) 185 | if f, ok := _bindata[cannonicalName]; ok { 186 | a, err := f() 187 | if err != nil { 188 | return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) 189 | } 190 | return a.info, nil 191 | } 192 | return nil, fmt.Errorf("AssetInfo %s not found", name) 193 | } 194 | 195 | // AssetNames returns the names of the assets. 196 | func AssetNames() []string { 197 | names := make([]string, 0, len(_bindata)) 198 | for name := range _bindata { 199 | names = append(names, name) 200 | } 201 | return names 202 | } 203 | 204 | // _bindata is a table, holding each asset generator, mapped to its name. 205 | var _bindata = map[string]func() (*asset, error){ 206 | "goja.tmpl": gojaTmpl, 207 | "goja_namespace.tmpl": goja_namespaceTmpl, 208 | "otto.tmpl": ottoTmpl, 209 | "otto_namespace.tmpl": otto_namespaceTmpl, 210 | } 211 | 212 | // AssetDir returns the file names below a certain 213 | // directory embedded in the file by go-bindata. 214 | // For example if you run go-bindata on data/... and data contains the 215 | // following hierarchy: 216 | // data/ 217 | // foo.txt 218 | // img/ 219 | // a.png 220 | // b.png 221 | // then AssetDir("data") would return []string{"foo.txt", "img"} 222 | // AssetDir("data/img") would return []string{"a.png", "b.png"} 223 | // AssetDir("foo.txt") and AssetDir("notexist") would return an error 224 | // AssetDir("") will return []string{"data"}. 225 | func AssetDir(name string) ([]string, error) { 226 | node := _bintree 227 | if len(name) != 0 { 228 | cannonicalName := strings.Replace(name, "\\", "/", -1) 229 | pathList := strings.Split(cannonicalName, "/") 230 | for _, p := range pathList { 231 | node = node.Children[p] 232 | if node == nil { 233 | return nil, fmt.Errorf("Asset %s not found", name) 234 | } 235 | } 236 | } 237 | if node.Func != nil { 238 | return nil, fmt.Errorf("Asset %s not found", name) 239 | } 240 | rv := make([]string, 0, len(node.Children)) 241 | for childName := range node.Children { 242 | rv = append(rv, childName) 243 | } 244 | return rv, nil 245 | } 246 | 247 | type bintree struct { 248 | Func func() (*asset, error) 249 | Children map[string]*bintree 250 | } 251 | var _bintree = &bintree{nil, map[string]*bintree{ 252 | "goja.tmpl": &bintree{gojaTmpl, map[string]*bintree{}}, 253 | "goja_namespace.tmpl": &bintree{goja_namespaceTmpl, map[string]*bintree{}}, 254 | "otto.tmpl": &bintree{ottoTmpl, map[string]*bintree{}}, 255 | "otto_namespace.tmpl": &bintree{otto_namespaceTmpl, map[string]*bintree{}}, 256 | }} 257 | 258 | // RestoreAsset restores an asset under the given directory 259 | func RestoreAsset(dir, name string) error { 260 | data, err := Asset(name) 261 | if err != nil { 262 | return err 263 | } 264 | info, err := AssetInfo(name) 265 | if err != nil { 266 | return err 267 | } 268 | err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) 269 | if err != nil { 270 | return err 271 | } 272 | err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) 273 | if err != nil { 274 | return err 275 | } 276 | err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) 277 | if err != nil { 278 | return err 279 | } 280 | return nil 281 | } 282 | 283 | // RestoreAssets restores an asset under the given directory recursively 284 | func RestoreAssets(dir, name string) error { 285 | children, err := AssetDir(name) 286 | // File 287 | if err != nil { 288 | return RestoreAsset(dir, name) 289 | } 290 | // Dir 291 | for _, child := range children { 292 | err = RestoreAssets(dir, filepath.Join(name, child)) 293 | if err != nil { 294 | return err 295 | } 296 | } 297 | return nil 298 | } 299 | 300 | func _filePath(dir, name string) string { 301 | cannonicalName := strings.Replace(name, "\\", "/", -1) 302 | return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) 303 | } 304 | 305 | -------------------------------------------------------------------------------- /gojs/templates/goja.tmpl: -------------------------------------------------------------------------------- 1 | package {{.PackageName}} 2 | 3 | {{$pkgName:=(printf "original_%s" .PackageName) -}} 4 | import ( 5 | {{$pkgName}} "{{.PackagePath}}" 6 | ) 7 | 8 | import ( 9 | "github.com/dop251/goja" 10 | "github.com/gogap/gojs-tool/gojs" 11 | ) 12 | 13 | var ( 14 | module = gojs.NewGojaModule("{{.PackageName}}") 15 | ) 16 | 17 | func init() { 18 | module.Set( 19 | gojs.Objects{ 20 | {{- $pkgFuncs:=.PackageFuncs}} 21 | // Functions 22 | {{- range $objName, $objDefine := .PackageFuncs}} 23 | "{{$objName}}": {{$pkgName}}.{{$objDefine}}, 24 | {{- end}} 25 | 26 | // Var and consts 27 | {{- range $objName, $objDefine := .PackageVars}} 28 | "{{$objName}}": {{$pkgName}}.{{$objDefine}}, 29 | {{- end}} 30 | 31 | // Types (value type) 32 | {{- range $objName, $objDefine := .PackageTypes}} 33 | "{{$objName}}": {{printf "func() %s.%s { return %s.%s{} }" $pkgName $objDefine $pkgName $objDefine}}, 34 | {{- end}} 35 | 36 | // Types (pointer type) 37 | {{range $objName, $objDefine := .PackageTypes}} 38 | {{- $newObjName := printf "%s%s" "New" $objName -}} 39 | {{- if not (exist $pkgFuncs $newObjName) -}} 40 | "{{$newObjName}}": {{printf "func() *%s.%s { return &%s.%s{} }" $pkgName $objDefine $pkgName $objDefine}}, 41 | {{end -}} 42 | {{- end -}} 43 | }, 44 | ).Register() 45 | } 46 | 47 | func Enable(runtime *goja.Runtime) { 48 | module.Enable(runtime) 49 | } -------------------------------------------------------------------------------- /gojs/templates/goja_namespace.tmpl: -------------------------------------------------------------------------------- 1 | package {{.PackageName}} 2 | 3 | import ( 4 | "github.com/dop251/goja" 5 | "github.com/dop251/goja_nodejs/require" 6 | ) 7 | 8 | import ( 9 | {{- range $subModule := .Args.SubModules}} 10 | "{{$subModule.PackagePath}}" 11 | {{- end}} 12 | ) 13 | 14 | type {{.PackageName}} struct { 15 | {{- range $subModule := .Args.SubModules}} 16 | {{$subModule.PackageName}} *goja.Object 17 | {{- end }} 18 | } 19 | 20 | func init() { 21 | require.RegisterNativeModule("{{.PackageName}}", Require) 22 | } 23 | 24 | func Require(runtime *goja.Runtime, module *goja.Object) { 25 | 26 | pkg := &{{.PackageName}}{ 27 | {{- range $subModule := .Args.SubModules }} 28 | {{$subModule.PackageName}} : require.Require(runtime, "{{$subModule.PackageName}}").(*goja.Object), 29 | {{- end}} 30 | } 31 | 32 | o := module.Get("exports").(*goja.Object) 33 | 34 | {{range $subModule := .Args.SubModules }} 35 | o.Set("{{$subModule.PackageName}}", pkg.{{$subModule.PackageName}}) 36 | {{- end }} 37 | } 38 | 39 | func Enable(runtime *goja.Runtime) { 40 | {{- range $subModule := .Args.SubModules }} 41 | {{$subModule.PackageName}}.Enable(runtime) 42 | {{- end }} 43 | 44 | runtime.Set("{{.PackageName}}", require.Require(runtime, "{{.PackageName}}")) 45 | } 46 | -------------------------------------------------------------------------------- /gojs/templates/otto.tmpl: -------------------------------------------------------------------------------- 1 | package {{.PackageName}} 2 | 3 | {{$pkgName:=(printf "original_%s" .PackageName) -}} 4 | import ( 5 | {{$pkgName}} "{{.PackagePath}}" 6 | ) 7 | 8 | import ( 9 | "github.com/robertkrimen/otto" 10 | ) 11 | 12 | {{$structName:= (toTitle .PackageName)}} 13 | 14 | type {{$structName}} struct { 15 | {{- $pkgFuncs:=.PackageFuncs}} 16 | // Functions 17 | {{- range $objName, $objDefine := .PackageFuncs}} 18 | {{$objName}} interface{} 19 | {{- end}} 20 | 21 | // Var and consts 22 | {{- range $objName, $objDefine := .PackageVars}} 23 | {{$objName}} interface{} 24 | {{- end}} 25 | 26 | // Types (value type) 27 | {{- range $objName, $objDefine := .PackageTypes}} 28 | {{$objName}} interface{} 29 | {{- end}} 30 | 31 | // Types (pointer type) 32 | {{range $objName, $objDefine := .PackageTypes}} 33 | {{- $newObjName := printf "%s%s" "New" $objName -}} 34 | {{- if not (exist $pkgFuncs $newObjName) -}} 35 | {{$newObjName}} interface{} 36 | {{end -}} 37 | {{- end -}} 38 | } 39 | 40 | 41 | var ( 42 | module = &{{$structName}} { 43 | {{- $pkgFuncs:=.PackageFuncs}} 44 | // Functions 45 | {{- range $objName, $objDefine := .PackageFuncs}} 46 | {{$objName}}: {{$pkgName}}.{{$objDefine}}, 47 | {{- end}} 48 | 49 | // Var and consts 50 | {{- range $objName, $objDefine := .PackageVars}} 51 | {{$objName}}: {{$pkgName}}.{{$objDefine}}, 52 | {{- end}} 53 | 54 | // Types (value type) 55 | {{- range $objName, $objDefine := .PackageTypes}} 56 | {{$objName}}: {{printf "func() %s.%s { return %s.%s{} }" $pkgName $objDefine $pkgName $objDefine}}, 57 | {{- end}} 58 | 59 | // Types (pointer type) 60 | {{range $objName, $objDefine := .PackageTypes}} 61 | {{- $newObjName := printf "%s%s" "New" $objName -}} 62 | {{- if not (exist $pkgFuncs $newObjName) -}} 63 | {{$newObjName}}: {{printf "func() *%s.%s { return &%s.%s{} }" $pkgName $objDefine $pkgName $objDefine}}, 64 | {{end -}} 65 | {{- end -}} 66 | } 67 | ) 68 | 69 | func Enable(o *otto.Otto) { 70 | o.Set("{{.PackageName}}", module) 71 | } -------------------------------------------------------------------------------- /gojs/templates/otto_namespace.tmpl: -------------------------------------------------------------------------------- 1 | package {{.PackageName}} 2 | 3 | import ( 4 | "github.com/robertkrimen/otto" 5 | ) 6 | 7 | import ( 8 | {{- range $subModule := .Args.SubModules}} 9 | "{{$subModule.PackagePath}}" 10 | {{- end}} 11 | ) 12 | 13 | func Enable(runtime *otto.Otto) { 14 | {{- range $subModule := .Args.SubModules }} 15 | {{$subModule.PackageName}}.Enable(runtime) 16 | {{- end }} 17 | 18 | var err error 19 | var obj otto.Value 20 | var goValue interface{} 21 | 22 | module := make(map[string]interface{}) 23 | 24 | {{- range $subModule := .Args.SubModules }} 25 | 26 | obj, err = runtime.Get("{{$subModule.PackageName}}") 27 | if err!=nil { 28 | panic(err) 29 | } 30 | 31 | goValue, err = obj.Export() 32 | if err!=nil { 33 | panic(err) 34 | } 35 | 36 | module["{{$subModule.PackageName}}"] = goValue.(*{{$subModule.PackageName}}.{{$subModule.PackageName|toTitle}}) 37 | 38 | {{- end}} 39 | 40 | runtime.Set("{{.PackageName}}", module) 41 | } 42 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "io/ioutil" 6 | "os" 7 | "path/filepath" 8 | "strings" 9 | 10 | "github.com/gogap/gojs-tool/gojs" 11 | "github.com/urfave/cli" 12 | ) 13 | 14 | type Module struct { 15 | PackageName string 16 | PackagePath string 17 | } 18 | 19 | func main() { 20 | 21 | app := cli.NewApp() 22 | 23 | app.Usage = "A tool for export package funcs, types, vars for VM (like goja) to use" 24 | 25 | app.Version = "0.0.1" 26 | 27 | app.Commands = cli.Commands{ 28 | cli.Command{ 29 | Name: "gen", 30 | Action: gen, 31 | Usage: "generate modules", 32 | ArgsUsage: "packages", 33 | Flags: []cli.Flag{ 34 | cli.StringFlag{ 35 | Name: "template, t", 36 | Value: "goja", 37 | Usage: "template filename in templates folder without extension", 38 | }, 39 | cli.BoolFlag{ 40 | Name: "recusive, r", 41 | Usage: "recusive generate code", 42 | }, 43 | cli.BoolFlag{ 44 | Name: "namespace, n", 45 | Usage: "generate submodules loader, access object by dot, only work while recusive enabled", 46 | }, 47 | cli.StringFlag{ 48 | Name: "gopath", 49 | EnvVar: "GOPATH", 50 | Usage: "the package in which GOPATH", 51 | }, 52 | }, 53 | }, 54 | } 55 | 56 | err := app.Run(os.Args) 57 | 58 | if err != nil { 59 | os.Stderr.WriteString(err.Error() + "\n") 60 | os.Exit(128) 61 | } 62 | } 63 | 64 | func gen(ctx *cli.Context) (err error) { 65 | 66 | if len(ctx.Args()) == 0 { 67 | err = errors.New("no package input") 68 | return 69 | } 70 | 71 | recusive := ctx.Bool("recusive") 72 | gopath := ctx.String("gopath") 73 | template := ctx.String("template") 74 | namespace := ctx.Bool("namespace") 75 | 76 | wd, err := os.Getwd() 77 | if err != nil { 78 | return 79 | } 80 | 81 | modulesDir := filepath.Join(wd, "modules") 82 | 83 | if !recusive { 84 | for i := 0; i < len(ctx.Args()); i++ { 85 | pkgPath := ctx.Args()[i] 86 | 87 | err = generateModulePackage(template, modulesDir, pkgPath, gopath) 88 | if err != nil { 89 | return 90 | } 91 | } 92 | 93 | return 94 | } 95 | 96 | for i := 0; i < len(ctx.Args()); i++ { 97 | pkgPath := ctx.Args()[i] 98 | 99 | walkFn := func(path string, info os.FileInfo, err error) error { 100 | 101 | if info == nil { 102 | return errors.New("read path error:" + path) 103 | } 104 | 105 | if !info.IsDir() { 106 | return nil 107 | } 108 | 109 | if strings.HasPrefix(info.Name(), ".") { 110 | return filepath.SkipDir 111 | } 112 | 113 | matched, e := filepath.Glob(filepath.Join(path, "*.go")) 114 | if e != nil { 115 | return e 116 | } 117 | 118 | if len(matched) == 0 { 119 | return nil 120 | } 121 | 122 | e = generateModulePackage(template, modulesDir, strings.TrimPrefix(path, filepath.Join(gopath, "src")+"/"), gopath) 123 | 124 | if e != nil { 125 | return e 126 | } 127 | 128 | return nil 129 | } 130 | 131 | err = filepath.Walk(filepath.Join(gopath, "src", pkgPath), walkFn) 132 | if err != nil { 133 | return 134 | } 135 | } 136 | 137 | if namespace { 138 | 139 | for i := 0; i < len(ctx.Args()); i++ { 140 | 141 | pkgPath := ctx.Args()[i] 142 | 143 | pkgModules := make(map[string][]string) 144 | 145 | walkFn := func(path string, info os.FileInfo, err error) error { 146 | 147 | if info == nil { 148 | return errors.New("read path error:" + path) 149 | } 150 | 151 | if !info.IsDir() { 152 | return nil 153 | } 154 | 155 | if strings.HasPrefix(info.Name(), ".") { 156 | return filepath.SkipDir 157 | } 158 | 159 | files, e := ioutil.ReadDir(path) 160 | if e != nil { 161 | return e 162 | } 163 | 164 | for j := 0; j < len(files); j++ { 165 | 166 | if files[j] == nil { 167 | return errors.New("read path error:" + filepath.Join(path, files[j].Name())) 168 | } 169 | 170 | if !files[j].IsDir() { 171 | continue 172 | } 173 | 174 | if strings.HasPrefix(files[j].Name(), ".") { 175 | continue 176 | } 177 | 178 | hasGoFiles, e := filepath.Glob(filepath.Join(path, "*.go")) 179 | if e != nil { 180 | return e 181 | } 182 | 183 | if len(hasGoFiles) > 0 { 184 | return nil 185 | } 186 | 187 | pkgModules[path] = append(pkgModules[path], files[j].Name()) 188 | } 189 | 190 | return nil 191 | } 192 | 193 | err = filepath.Walk(filepath.Join(modulesDir, pkgPath), walkFn) 194 | if err != nil { 195 | return 196 | } 197 | 198 | for path, moduleNames := range pkgModules { 199 | pkgPath := strings.TrimPrefix(path, modulesDir+"/") 200 | rootPath := strings.TrimPrefix(path, filepath.Join(gopath, "src")+"/") 201 | 202 | var modules []Module 203 | for _, moduleName := range moduleNames { 204 | m := Module{ 205 | PackagePath: filepath.Join(rootPath, moduleName), 206 | PackageName: moduleName, 207 | } 208 | 209 | modules = append(modules, m) 210 | } 211 | 212 | err = generateNamespace(template+"_namespace", modulesDir, pkgPath, gopath, modules) 213 | if err != nil { 214 | return 215 | } 216 | } 217 | } 218 | } 219 | 220 | return 221 | } 222 | 223 | func generateModulePackage(tmplName, modulesDir, pkgPath, gopath string) (err error) { 224 | 225 | vars, err := gojs.Parser(pkgPath, gopath) 226 | if err != nil { 227 | return 228 | } 229 | 230 | options := gojs.GenerateOptions{ 231 | TemplateName: tmplName, 232 | PackagePath: pkgPath, 233 | GoPath: gopath, 234 | TemplateVars: vars, 235 | } 236 | 237 | codeDir := filepath.Join(modulesDir, pkgPath) 238 | 239 | code, err := gojs.GenerateCode(options) 240 | if err != nil { 241 | return 242 | } 243 | 244 | err = os.MkdirAll(codeDir, 0755) 245 | if err != nil { 246 | return 247 | } 248 | 249 | codeFile := filepath.Join(codeDir, filepath.Base(pkgPath)+".go") 250 | 251 | err = ioutil.WriteFile(codeFile, []byte(code), 0644) 252 | if err != nil { 253 | return 254 | } 255 | 256 | return 257 | } 258 | 259 | func generateNamespace(tmplName, modulesDir, pkgPath, gopath string, modules []Module) (err error) { 260 | 261 | options := gojs.GenerateOptions{ 262 | TemplateName: tmplName, 263 | PackagePath: pkgPath, 264 | GoPath: gopath, 265 | TemplateVars: &gojs.TemplateVars{ 266 | PackageName: filepath.Base(pkgPath), 267 | PackagePath: strings.TrimPrefix(pkgPath, filepath.Join(gopath, "src")+"/"), 268 | Args: map[string]interface{}{ 269 | "SubModules": modules, 270 | }, 271 | }, 272 | } 273 | 274 | code, err := gojs.GenerateCode(options) 275 | if err != nil { 276 | return 277 | } 278 | 279 | codeDir := filepath.Join(modulesDir, pkgPath) 280 | 281 | err = os.MkdirAll(codeDir, 0755) 282 | if err != nil { 283 | return 284 | } 285 | 286 | codeFile := filepath.Join(codeDir, filepath.Base(pkgPath)+".go") 287 | 288 | err = ioutil.WriteFile(codeFile, []byte(code), 0644) 289 | if err != nil { 290 | return 291 | } 292 | 293 | return 294 | } 295 | --------------------------------------------------------------------------------