├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── build.bat
├── build_linux.sh
├── build_mips.sh
├── build_sqlite3.go
├── cache.go
├── checkType.go
├── go.mod
├── go.sum
├── js
├── db
│ ├── redis.js
│ ├── sql.js
│ └── sqlite3.js
├── ejs
│ ├── ejs.js
│ ├── ejs.min.js
│ ├── functions.ejs
│ ├── functions.js
│ ├── list.ejs
│ ├── list.js
│ ├── list_redis.js
│ ├── sql.ejs
│ └── sql.js
├── file
│ └── test1.js
├── http
│ ├── body.js
│ ├── cookie.js
│ ├── download.js
│ ├── header.js
│ ├── http.js
│ ├── request.js
│ ├── session.js
│ └── upload.js
├── image
│ ├── font.js
│ ├── image.js
│ ├── test1.js
│ └── test2.js
├── index.js
├── others
│ ├── cache.js
│ ├── os.js
│ ├── require.js
│ ├── return.js
│ └── types.js
└── utils.js
├── lib
├── db
│ ├── db.go
│ ├── redis
│ │ ├── conn.go
│ │ └── redis.go
│ ├── result.go
│ ├── rows.go
│ ├── sql.go
│ ├── stmt.go
│ └── tx.go
├── error.go
├── file.go
├── fmt.go
├── image
│ ├── image.go
│ ├── lib
│ │ ├── fonts.go
│ │ └── img.go
│ ├── png
│ │ └── png.go
│ └── rgba.go
├── io.go
├── net
│ ├── http
│ │ ├── cookie.go
│ │ ├── header.go
│ │ ├── http.go
│ │ ├── multipartFile.go
│ │ ├── request.go
│ │ └── response.go
│ └── url
│ │ ├── url.go
│ │ └── values.go
├── os.go
├── path
│ └── filepath.go
├── strings.go
├── time.go
├── types.go
└── utils.go
├── main.go
├── nodejs
├── console
│ ├── module.go
│ └── module_test.go
├── eventloop
│ ├── eventloop.go
│ └── eventloop_test.go
├── require
│ ├── module.go
│ ├── module_test.go
│ └── testdata
│ │ └── m.js
└── util
│ ├── module.go
│ └── module_test.go
├── public
├── css
│ └── index.css
├── index.html
├── jquery-easyui
│ ├── jquery.easyui.min.js
│ └── themes
│ │ ├── default
│ │ ├── accordion.css
│ │ ├── calendar.css
│ │ ├── combo.css
│ │ ├── combobox.css
│ │ ├── datagrid.css
│ │ ├── datalist.css
│ │ ├── datebox.css
│ │ ├── dialog.css
│ │ ├── easyui.css
│ │ ├── filebox.css
│ │ ├── images
│ │ │ ├── accordion_arrows.png
│ │ │ ├── blank.gif
│ │ │ ├── calendar_arrows.png
│ │ │ ├── combo_arrow.png
│ │ │ ├── datagrid_icons.png
│ │ │ ├── datebox_arrow.png
│ │ │ ├── layout_arrows.png
│ │ │ ├── linkbutton_bg.png
│ │ │ ├── loading.gif
│ │ │ ├── menu_arrows.png
│ │ │ ├── messager_icons.png
│ │ │ ├── pagination_icons.png
│ │ │ ├── panel_tools.png
│ │ │ ├── passwordbox_close.png
│ │ │ ├── passwordbox_open.png
│ │ │ ├── searchbox_button.png
│ │ │ ├── slider_handle.png
│ │ │ ├── spinner_arrows.png
│ │ │ ├── tabs_icons.png
│ │ │ ├── tagbox_icons.png
│ │ │ ├── tree_icons.png
│ │ │ └── validatebox_warning.png
│ │ ├── layout.css
│ │ ├── linkbutton.css
│ │ ├── menu.css
│ │ ├── menubutton.css
│ │ ├── messager.css
│ │ ├── numberbox.css
│ │ ├── pagination.css
│ │ ├── panel.css
│ │ ├── passwordbox.css
│ │ ├── progressbar.css
│ │ ├── propertygrid.css
│ │ ├── searchbox.css
│ │ ├── slider.css
│ │ ├── spinner.css
│ │ ├── splitbutton.css
│ │ ├── switchbutton.css
│ │ ├── tabs.css
│ │ ├── tagbox.css
│ │ ├── textbox.css
│ │ ├── tooltip.css
│ │ ├── tree.css
│ │ ├── validatebox.css
│ │ └── window.css
│ │ ├── icon.css
│ │ └── icons
│ │ ├── back.png
│ │ ├── blank.gif
│ │ ├── cancel.png
│ │ ├── clear.png
│ │ ├── cut.png
│ │ ├── edit_add.png
│ │ ├── edit_remove.png
│ │ ├── filesave.png
│ │ ├── filter.png
│ │ ├── help.png
│ │ ├── large_chart.png
│ │ ├── large_clipart.png
│ │ ├── large_picture.png
│ │ ├── large_shapes.png
│ │ ├── large_smartart.png
│ │ ├── lock.png
│ │ ├── man.png
│ │ ├── mini_add.png
│ │ ├── mini_edit.png
│ │ ├── mini_refresh.png
│ │ ├── more.png
│ │ ├── no.png
│ │ ├── ok.png
│ │ ├── pencil.png
│ │ ├── print.png
│ │ ├── redo.png
│ │ ├── reload.png
│ │ ├── search.png
│ │ ├── sum.png
│ │ ├── tip.png
│ │ └── undo.png
└── js
│ └── jquery.js
├── session.go
└── test
└── sql.go
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.js linguist-language=golang
2 | *.css linguist-language=golang
3 | *.html linguist-language=golang
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.exe
2 | *.db
3 | go-server-js
4 | *.json
5 | test/
6 | debug
7 | .vscode/
8 | vendor/
9 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # a js server
4 | 一种新的javascript写服务端程序的方案,没有回调,完全不同于node.js
5 |
6 | 这可能是最简单的服务器方案了,因为它不需要任何配置,只有一个文件,运行它就有了完整的服务器、数据库和缓存系统,并且可以运行在go语言支持的所有平台上,例如:路由器上,相对于其它语言开发的服务器软件而言是非常有优势的,我曾经在路由器上配置过php服务器,花了好几个小时的时间,并且无法及时更新到新版本。这不像pc机那么容易的。
7 |
8 | 优点:
9 | 1. 免安装,无需配置任何环境,自带sqlite数据库和一个简易的缓存系统
10 | 2. go语言开发,无限扩展功能,可以自由定制
11 | 3. 跨平台,支持linux、windows、mac,支持x86/arm/mips等指令集的cpu(运行在安卓手机、树莓派、路由器、国产龙芯。。。)
12 | 4. 完全不同于node.js,没有回调,程序更易维护和编写,推荐使用typescript
13 |
14 | 缺点:
15 | 1. 由于每次js都是从磁盘读取再执行,因此性能不高,和node.js完全不是一个级别的,目前能完全满足小应用的需求,在这里能找到一份测试报告:https://github.com/zengming00/go-server-js-testShop
16 | 2. api目前不够完善,我只是需要什么就往上面加什么,你也可以
17 | 3. 目前没有文档支持,没空写,哈哈
18 | 4. 没有debug功能,调试不方便,这是个很严重的问题,目前没有办法
19 |
20 | 写node一年了,感觉node的异步优势很少用到,坑爹的回调让人非常痛苦,虽然说有async/await但仍然会时不时接触到,用async/await其实还是在写同步的代码,所谓的异步并发优势只能很少数场合能用到,有的时候甚至是得不偿失的。
21 |
22 | 在不了解node之前,在我的想象中以为node是像php那样写的,学过之后发现完全不是这样的,我曾经去找过类似这种东西,但是没找到,也许是我的方法不对,网上有个fibjs,那不是我想要的。并且,我是在发布go-server-js之后才听说的
23 |
24 | 所以我决定自己做一个,为此我曾经注册了serverjs.cn域名,我尝试过用c语言来写,C语言门槛太高了只做了一个能够连上redis的东西,还得靠cgi模式来提供服务,最终放弃了,后来接触了go语言,于是有了实现它的可能,最早是用的otto,后来才用的goja。
25 |
26 | 从开始到完成0.0.2版本应该花了一个多月吧,基本上都是在学go语言和尝试一些功能细节,最后还花时间将我一年前写的一个nodejs写的商城用我自创的go-server-js技术重写了一遍( 项目地址:https://github.com/zengming00/go-server-js-testShop ),并且和go-server-js 0.0.2捆绑发布。
27 |
28 | 再后来,为了验证go-server-js写的项目能不能够方便的移植到原生go语言项目,我又把这个商城用go语言写了一遍( 项目地址:https://github.com/zengming00/go-testShop ),得益于当时选择照抄go语言的编程风格,只需要将go-server-js封装好的一些功能实现,js代码到go语言代码的转换是很方便的
29 |
30 | # 下载试用 (download),下载后运行go-server-js,打开 http://127.0.0.1:8080/ 就是一个商城
31 | https://github.com/zengming00/go-server-js/releases
32 |
33 | ## 入门之helloworld
34 | 整个服务器就是go-server-js这个文件,不需要任何其它东西,运行它会在当前目录下生成一个config.json,这个是用来修改一些服务器配置的,比如端口号之类的。
35 |
36 | 在当前目录下创建test.js内容为
37 |
38 | ```js
39 | response.write('helloworld');
40 | ```
41 | 运行go-server-js然后在浏览器打开 http://127.0.0.1:8080/test.js 就可以看到helloworld了,修改文件后不需要重启服务器
42 | 更多的教程不如直接看附带的商城源码,一些api与go语言是完全一样的,因此为后期移植到原生go语言提供了极大便利
43 |
44 | # 用go-server-js写的项目
45 | 一个商城:https://github.com/zengming00/go-server-js-testShop
46 |
47 | wooyun本地镜像:https://github.com/zengming00/go-server-js-wooyun
48 |
49 | # 用go-server-js写的项目移植为go语言代码,两种等效代码对比
50 |
51 | https://github.com/zengming00/go-testShop
52 |
53 | 
54 |
55 |
56 | ## 获取源码
57 | ```
58 | go get -v github.com/zengming00/go-server-js
59 | ```
60 |
61 | 默认不会编译sqlite,在windows下编译sqlite需要安装 TDM-GCC 或 mingw64 并 set CGO_ENABLED = 1
62 |
63 | 如果要编译sqlite,在windows下运行build.bat,在linux下运行build_linux.sh
64 |
65 |
66 | ## 内部实现功能时需要注意的地方
67 | ```go
68 | // 在go语言中如果是返回一个error,要经过转换才能给js使用
69 | err := db.Close()
70 | if err != nil {
71 | return runtime.ToValue(lib.NewError(runtime, err))
72 | }
73 | return nil
74 |
75 | // 如果类型无法处理,应该用这种方式抛出
76 | panic(runtime.NewTypeError("p0 is not a string type:%T", args[0]))
77 |
78 | // 如果有多个返回值,应该返回一个对象供js使用
79 | tx, err := db.Begin()
80 | if err != nil {
81 | return lib.MakeErrorValue(runtime, err)
82 | }
83 | return lib.MakeReturnValue(runtime, NewTx(runtime, tx))
84 |
85 | // 动态参数
86 | args := lib.GetAllArgs(&call)
87 | err := rows.Scan(args...)
88 |
89 | // go语言原生类型的传递
90 | p0 := GetNativeType(runtime, &call, 0)
91 | if err, ok := p0.(error); ok {
92 | return runtime.ToValue(os.IsNotExist(err))
93 | }
94 | panic(runtime.NewTypeError("p0 is not error type:%T", p0))
95 |
96 | // 注意函数签名的不同
97 | func(call goja.FunctionCall) goja.Value {}
98 | func(call goja.ConstructorCall) *Object {}
99 | ```
100 |
101 | # docker
102 | ```Dockerfile
103 | FROM scratch
104 | COPY . /
105 | EXPOSE 8080
106 | CMD [ "/go-server-js" ]
107 | ```
108 | ```sh
109 | $ docker pull zengming00/go-server-js
110 | $ docker run -d --rm -p 80:8080 zengming00/go-server-js
111 | ```
112 |
113 | # docker 编译 mips 环境
114 | docker pull zengming00/golang-mips
115 |
116 |
117 |
--------------------------------------------------------------------------------
/build.bat:
--------------------------------------------------------------------------------
1 | go build -tags=sqlite3 -v
--------------------------------------------------------------------------------
/build_linux.sh:
--------------------------------------------------------------------------------
1 | go build -tags=sqlite3 -v -ldflags "-linkmode external -extldflags -static"
2 |
--------------------------------------------------------------------------------
/build_mips.sh:
--------------------------------------------------------------------------------
1 | export CGO_ENABLED=1
2 | export GOOS=linux
3 | export GOARCH=mips
4 | export CC=mips-linux-gnu-gcc
5 | export CXX=mips-linux-gnu-g++
6 |
7 | go env
8 | go build -tags=sqlite3 -v -ldflags "-linkmode external -extldflags -static"
9 |
--------------------------------------------------------------------------------
/build_sqlite3.go:
--------------------------------------------------------------------------------
1 | // +build sqlite3
2 |
3 | package main
4 |
5 | import _ "github.com/mattn/go-sqlite3"
6 |
7 | // go-sqlite3在win32下的问题
8 | // https://github.com/mattn/go-sqlite3/issues/358
9 | // 需要安装 TDM-GCC 并 set CGO_ENABLED = 1
10 |
11 | // 编译mips
12 | // apt-get install gcc-arm-linux-gnu
13 | // apt-get install g++-arm-linux-gnu
14 | // CGO_ENABLED=1 GOOS=linux GOARCH=mips CC=mips-linux-gnu-gcc CXX=mips-linux-gnu-g++ go build -v -ldflags "-linkmode external -extldflags -static"
15 |
16 | // 要将sqlite3编译进去,执行
17 | // go build -tags=sqlite3 -a -v
18 |
--------------------------------------------------------------------------------
/cache.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "sync"
5 | "time"
6 |
7 | "github.com/dop251/goja"
8 | )
9 |
10 | type CacheMgr struct {
11 | mu sync.RWMutex
12 | gcIntervalSec int64
13 | items map[string]*CacheItem
14 | }
15 |
16 | type CacheItem struct {
17 | value interface{}
18 | expireTimeSec int64
19 | }
20 |
21 | func NewCacheMgr(gcIntervalSec int64) *CacheMgr {
22 | mgr := &CacheMgr{
23 | gcIntervalSec: gcIntervalSec,
24 | items: make(map[string]*CacheItem),
25 | }
26 | go mgr.gc()
27 | return mgr
28 | }
29 |
30 | func (mgr *CacheMgr) gc() {
31 | for {
32 | <-time.After(time.Duration(mgr.gcIntervalSec) * time.Second)
33 | mgr.mu.Lock()
34 | for key := range mgr.items {
35 | mgr.isExpired(key)
36 | }
37 | mgr.mu.Unlock()
38 | }
39 | }
40 |
41 | func (mgr *CacheMgr) isExpired(key string) bool {
42 | if item, ok := mgr.items[key]; ok {
43 | if item.expireTimeSec <= 0 {
44 | return false
45 | }
46 | if item.expireTimeSec < time.Now().Unix() {
47 | delete(mgr.items, key)
48 | return true
49 | }
50 | return false
51 | }
52 | return true
53 | }
54 |
55 | func (mgr *CacheMgr) Add(key string, v int64, expireSec int64) int64 {
56 | mgr.mu.Lock()
57 | defer mgr.mu.Unlock()
58 |
59 | expireTimeSec := int64(-1)
60 | if expireSec > 0 {
61 | expireTimeSec = time.Now().Unix() + expireSec
62 | }
63 |
64 | if item, ok := mgr.items[key]; ok {
65 | if oldVal, ok := item.value.(int64); ok {
66 | item.expireTimeSec = expireTimeSec
67 | item.value = oldVal + v
68 | return oldVal
69 | }
70 | }
71 | mgr.items[key] = &CacheItem{
72 | value: v,
73 | expireTimeSec: expireTimeSec,
74 | }
75 | return 0
76 | }
77 |
78 | func (mgr *CacheMgr) Set(key string, value interface{}, expireSec int64) {
79 | mgr.mu.Lock()
80 | defer mgr.mu.Unlock()
81 |
82 | expireTimeSec := int64(-1)
83 | if expireSec > 0 {
84 | expireTimeSec = time.Now().Unix() + expireSec
85 | }
86 | mgr.items[key] = &CacheItem{
87 | value: value,
88 | expireTimeSec: expireTimeSec,
89 | }
90 | }
91 |
92 | func (mgr *CacheMgr) Get(key string) (interface{}, bool) {
93 | mgr.mu.RLock()
94 | defer mgr.mu.RUnlock()
95 | if !mgr.isExpired(key) {
96 | if v, ok := mgr.items[key]; ok {
97 | return v.value, true
98 | }
99 | }
100 | return nil, false
101 | }
102 |
103 | func (mgr *CacheMgr) Del(key string) {
104 | mgr.mu.Lock()
105 | defer mgr.mu.Unlock()
106 | delete(mgr.items, key)
107 | }
108 |
109 | func (mgr *CacheMgr) Flush() {
110 | mgr.mu.Lock()
111 | defer mgr.mu.Unlock()
112 | mgr.items = make(map[string]*CacheItem)
113 | }
114 |
115 | ///////////////////////////////////////////////////////////////////////////
116 |
117 | func NewCache(runtime *goja.Runtime, cacheMgr *CacheMgr) *goja.Object {
118 | o := runtime.NewObject()
119 | o.Set("set", func(call goja.FunctionCall) goja.Value {
120 | key := call.Argument(0).String()
121 | value := call.Argument(1).Export()
122 | expireSec := call.Argument(2).ToInteger()
123 | if IsValidType(value) {
124 | cacheMgr.Set(key, value, expireSec)
125 | return nil
126 | }
127 | panic(runtime.NewTypeError("value type %T is not permitted", value))
128 | })
129 |
130 | o.Set("get", func(call goja.FunctionCall) goja.Value {
131 | key := call.Argument(0).String()
132 | if value, ok := cacheMgr.Get(key); ok {
133 | return runtime.ToValue(value)
134 | }
135 | return goja.Null()
136 | })
137 |
138 | o.Set("del", func(call goja.FunctionCall) goja.Value {
139 | key := call.Argument(0).String()
140 | cacheMgr.Del(key)
141 | return nil
142 | })
143 |
144 | o.Set("flush", func(call goja.FunctionCall) goja.Value {
145 | cacheMgr.Flush()
146 | return nil
147 | })
148 |
149 | o.Set("add", func(call goja.FunctionCall) goja.Value {
150 | key := call.Argument(0).String()
151 | value := call.Argument(1).ToInteger()
152 | expireSec := call.Argument(2).ToInteger()
153 | oldValue := cacheMgr.Add(key, value, expireSec)
154 | return runtime.ToValue(oldValue)
155 | })
156 |
157 | o.Set("sub", func(call goja.FunctionCall) goja.Value {
158 | key := call.Argument(0).String()
159 | value := call.Argument(1).ToInteger()
160 | expireSec := call.Argument(2).ToInteger()
161 | oldValue := cacheMgr.Add(key, -value, expireSec)
162 | return runtime.ToValue(oldValue)
163 | })
164 |
165 | return o
166 | }
167 |
--------------------------------------------------------------------------------
/checkType.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "reflect"
5 | )
6 |
7 | var validType = []reflect.Kind{
8 | reflect.Bool,
9 | reflect.Int,
10 | reflect.Int8,
11 | reflect.Int16,
12 | reflect.Int32,
13 | reflect.Int64,
14 | reflect.Uint,
15 | reflect.Uint8,
16 | reflect.Uint16,
17 | reflect.Uint32,
18 | reflect.Uint64,
19 | reflect.Float32,
20 | reflect.Float64,
21 | reflect.Complex64,
22 | reflect.Complex128,
23 | reflect.String,
24 | }
25 |
26 | func IsValidType(val interface{}) bool {
27 | if val == nil {
28 | return true
29 | }
30 | k := reflect.TypeOf(val).Kind()
31 | for _, v := range validType {
32 | if v == k {
33 | return true
34 | }
35 | }
36 | return false
37 | }
38 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/zengming00/go-server-js
2 |
3 | go 1.12
4 |
5 | require (
6 | github.com/dlclark/regexp2 v1.1.6
7 | github.com/dop251/goja v0.0.0-20180113122955-eab79f83e840
8 | github.com/garyburd/redigo v1.4.0
9 | github.com/go-sql-driver/mysql v1.3.0
10 | github.com/mattn/go-sqlite3 v1.6.0
11 | golang.org/x/text v0.0.0-20171227012246-e19ae1496984
12 | )
13 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/dlclark/regexp2 v1.1.6 h1:CqB4MjHw0MFCDj+PHHjiESmHX+N7t0tJzKvC6M97BRg=
2 | github.com/dlclark/regexp2 v1.1.6/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
3 | github.com/dop251/goja v0.0.0-20180113122955-eab79f83e840 h1:c8hPp5t1uP4cfZ+HhsoVbbarv1rQrrjRTbQhf3IDFpY=
4 | github.com/dop251/goja v0.0.0-20180113122955-eab79f83e840/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA=
5 | github.com/garyburd/redigo v1.4.0 h1:PlMIyh8f7og1DRVAZiU1I6VR8R5vFbWch3ddfv1ICvY=
6 | github.com/garyburd/redigo v1.4.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
7 | github.com/go-sql-driver/mysql v1.3.0 h1:pgwjLi/dvffoP9aabwkT3AKpXQM93QARkjFhDDqC1UE=
8 | github.com/go-sql-driver/mysql v1.3.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
9 | github.com/mattn/go-sqlite3 v1.6.0 h1:TDwTWbeII+88Qy55nWlof0DclgAtI4LqGujkYMzmQII=
10 | github.com/mattn/go-sqlite3 v1.6.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
11 | golang.org/x/text v0.0.0-20171227012246-e19ae1496984 h1:ulYJn/BqO4fMRe1xAQzWjokgjsQLPpb21GltxXHI3fQ=
12 | golang.org/x/text v0.0.0-20171227012246-e19ae1496984/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
13 |
--------------------------------------------------------------------------------
/js/db/redis.js:
--------------------------------------------------------------------------------
1 | var redis = require('redis')
2 | var utils = require('utils')
3 |
4 | var r = redis.dial('tcp', ':6379')
5 | if (r.err) {
6 | throw r.err;
7 | }
8 | var conn = r.value;
9 | r = conn.do('get', 'str')
10 | if (r.err) {
11 | throw r.err;
12 | }
13 | r = redis.string(r.value)
14 | if (r.err) {
15 | conn.do('set', 'str', 'helloworld', 'ex', '3')
16 | console.log(">>>>>>> set value")
17 | throw r.err;
18 | } else {
19 | log(r.value)
20 | }
21 |
22 | r = conn.do('keys', '*')
23 | if (r.err) {
24 | throw r.err;
25 | }
26 | if (Array.isArray(r.value)) {
27 | r.value.forEach(function (item) {
28 | println(utils.toString(item))
29 | });
30 | }
31 | r = conn.close()
32 | if (r) {
33 | throw r;
34 | }
35 |
36 | log(r)
37 |
38 | function log(data) {
39 | console.log("log:", data)
40 | console.log("log:", JSON.stringify(data, null, 2))
41 | }
42 |
43 | function println(data) {
44 | utils.print(data);
45 | utils.print("\r\n");
46 | response.write(data + "\r\n");
47 | }
--------------------------------------------------------------------------------
/js/db/sql.js:
--------------------------------------------------------------------------------
1 | var sql = require('sql')
2 | var url = require('url')
3 | var utils = require('utils')
4 | var types = require('types')
5 |
6 | try {
7 | // var db = sql.new("mysql", "root:root@/test2?parseTime=true&loc=" + url.queryEscape("Asia/Shanghai"))
8 | var reUse = true;
9 | var r = sql.open("mysql", "root:root@/test2", reUse);
10 | if (r.err) {
11 | throw r.err;
12 | }
13 | var db = r.value;
14 | if (!r.isReUse) {
15 | db.setMaxOpenConns(100);
16 | }
17 | var stat = db.stats();
18 | response.write(JSON.stringify(stat, null, 2))
19 | r = db.query("select * from users")
20 | if (r.err) {
21 | throw r.err;
22 | }
23 | var rows = r.value;
24 | while (rows.next()) {
25 | var data = getData(rows)
26 | utils.print(JSON.stringify(data, null, 2))
27 | utils.print("\r\n")
28 | }
29 | var err = rows.err()
30 | if (err) {
31 | throw err;
32 | }
33 | err = rows.close();
34 | if (err) {
35 | throw err;
36 | }
37 | // err = db.close();
38 | // if (err) {
39 | // throw err;
40 | // }
41 | } catch (e) {
42 | console.log("ee: %j", e)
43 | throw e;
44 | }
45 |
46 | function getData(rows) {
47 | var arr = [
48 | types.newString(),
49 | types.newString(),
50 | types.newString(),
51 | types.newString(),
52 | types.newString(),
53 | types.newString(),
54 | types.newString(),
55 | types.newString(),
56 | ];
57 | var err = rows.scan.apply(rows, arr)
58 | if (err) {
59 | throw err;
60 | }
61 | response.write(JSON.stringify(arr, null, 2))
62 | return {
63 | // id: types.intValue(arr[0]),
64 | a: types.stringValue(arr[1]),
65 | }
66 | }
67 |
68 |
69 |
--------------------------------------------------------------------------------
/js/ejs/functions.ejs:
--------------------------------------------------------------------------------
1 |
Users
2 |
3 | <% function user(user) { %>
4 | <%= user.name %> is a <%= user.age %> year old <%= user.species %>.
5 | <% } %>
6 |
7 |
8 | <% users.map(user) %>
9 |
10 | ejs version: <%= version %>
11 |
--------------------------------------------------------------------------------
/js/ejs/functions.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Believe it or not, you can declare and use functions in EJS templates too.
3 | */
4 |
5 | var ejs = require("./js/ejs/ejs.js");
6 | var file = require("file");
7 | var utils = require("utils");
8 |
9 | function fileLoader(filePath) {
10 | var r = file.read(filePath);
11 | if(r.err){
12 | throw r.err
13 | }
14 | return utils.toString(r.data);
15 | }
16 |
17 | ejs.fileLoader = fileLoader;
18 |
19 | var data = {
20 | users: [
21 | { name: 'Tobi', age: 2, species: 'zengming' },
22 | { name: 'Loki', age: 2, species: 'ferret' },
23 | { name: 'Jane', age: 6, species: new Date().toString() },
24 | ],
25 | version: ejs.VERSION,
26 | };
27 |
28 | var path = './js/ejs/functions.ejs';
29 | var content = fileLoader(path);
30 | var func = ejs.compile(content, { filename: path });
31 | var ret = func(data);
32 | response.write(ret)
33 |
34 |
--------------------------------------------------------------------------------
/js/ejs/list.ejs:
--------------------------------------------------------------------------------
1 | <% if (names.length) { %>
2 |
3 | <% names.forEach(function (name) { %>
4 | <%# Notice how the single quotation mark is escaped in the output HTML %>
5 | - '><%= name %>
6 | <% }) %>
7 |
8 | <% } %>
9 |
--------------------------------------------------------------------------------
/js/ejs/list.js:
--------------------------------------------------------------------------------
1 | /*
2 | * This example demonstrates how to use Array.prototype.forEach() in an EJS
3 | * template.
4 | */
5 |
6 | // var ejs = require("./js/ejs/ejs.js");
7 | var ejs = require("./js/ejs/ejs.min.js");
8 | var file = require("file");
9 | var utils = require("utils");
10 | var myUtils = require('./js/utils.js');
11 |
12 |
13 | ejs.fileLoader = myUtils.fileLoader;
14 |
15 | var data = {
16 | names: ['foo', 'bar', '"baz']
17 | };
18 |
19 |
20 | ejs.renderFile('./js/ejs/list.ejs', data, function (err, html) {
21 | if (err) {
22 | console.log(err);
23 | return
24 | }
25 | response.header().set('Content-Type', 'text/html; charset=utf-8');
26 | response.write(html);
27 | });
28 |
--------------------------------------------------------------------------------
/js/ejs/list_redis.js:
--------------------------------------------------------------------------------
1 | /*
2 | * This example demonstrates how to use Array.prototype.forEach() in an EJS
3 | * template.
4 | */
5 |
6 | // var ejs = require("./js/ejs/ejs.js");
7 | var ejs = require("./js/ejs/ejs.min.js");
8 | var file = require("file");
9 | var utils = require("utils");
10 | var redis = require('redis')
11 |
12 | function fileLoader(filePath) {
13 | return utils.toString(file.read(filePath));
14 | }
15 |
16 |
17 | var data = {
18 | names: [ejs.VERSION],
19 | };
20 |
21 | var conn = redis.dial('tcp', ':6379')
22 | var v = conn.do('keys', '*')
23 | if (Array.isArray(v)) {
24 | v.forEach(function (item) {
25 | var str = utils.toString(item);
26 | data.names.push(str);
27 | });
28 | }
29 | conn.close()
30 |
31 | var path = './js/ejs/list.ejs';
32 | var content = fileLoader(path);
33 | ejs.compile(content, { filename: path })(data);
34 |
--------------------------------------------------------------------------------
/js/ejs/sql.ejs:
--------------------------------------------------------------------------------
1 | <% if (datas.length) { %>
2 |
3 | <% datas.forEach(function (item) { %>
4 |
5 | <%= item.id %> |
6 | <%= item.firstname %> |
7 | <%= item.lastname %> |
8 | <%= item.phone %> |
9 | <%= item.email %> |
10 | <%= item.created_at.Time ? item.created_at.Time : item.created_at %> |
11 |
12 | <% }) %>
13 |
14 | <% } %>
15 |
--------------------------------------------------------------------------------
/js/ejs/sql.js:
--------------------------------------------------------------------------------
1 | var sql = require('sql')
2 | var url = require('url')
3 | var file = require('file');
4 | var utils = require('utils')
5 | var ejs = require('./js/ejs/ejs.min.js');
6 | var myUtils = require('./js/utils.js');
7 |
8 |
9 |
10 | // var db = sql.new("mysql", "root:root@/test2?parseTime=true&loc=" + url.queryEscape("Asia/Shanghai"))
11 | // var db = sql.new("mysql", "root:root@/test2")
12 | var r = sql.open("sqlite3", "./js/db/test.db")
13 | if (r.err) {
14 | throw r.err;
15 | }
16 |
17 | var db = r.value;
18 | r = db.query("select * from users")
19 | if (r.err) {
20 | throw r.err;
21 | }
22 |
23 | var rows = r.value;
24 | var rowDatas = [];
25 | while (rows.next()) {
26 | var data = rows.getData();
27 | rowDatas.push(data);
28 | }
29 |
30 | var err = rows.err()
31 | if (err) {
32 | throw err;
33 | }
34 | db.close()
35 | log(rowDatas)
36 | var path = './js/ejs/sql.ejs';
37 | var content = myUtils.fileLoader(path);
38 | var func = ejs.compile(content, { filename: path });
39 | var html = func({ datas: rowDatas });
40 | response.write(html)
41 |
42 | function log(data) {
43 | console.log("log:", data)
44 | console.log("log:", JSON.stringify(data, null, 2))
45 | }
46 |
--------------------------------------------------------------------------------
/js/file/test1.js:
--------------------------------------------------------------------------------
1 | var os = require('os')
2 |
3 | var r = os.create('te.txt')
4 | if(r.err){
5 | throw r.err
6 | }
7 |
8 | var file = r.file
9 | file.writeString("helloworld go-serverjs")
10 | file.close()
11 |
--------------------------------------------------------------------------------
/js/http/body.js:
--------------------------------------------------------------------------------
1 | var utils = require('utils')
2 |
3 | function log(d) {
4 | console.log("%j", d);
5 | var r = response.write(d);
6 | if (r.err) {
7 | throw r.err;
8 | }
9 | response.write('\r\n');
10 | }
11 |
12 | var r = request.getRawBody()
13 | if (r.err) {
14 | throw r.err;
15 | }
16 |
17 | var value = utils.toString(r.value)
18 | log(value)
19 | var obj = JSON.parse(value)
20 | log(obj.a)
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/js/http/cookie.js:
--------------------------------------------------------------------------------
1 |
2 | var Name = 'test'
3 | var Value = 'testval'
4 | var Path = '/'
5 | var MaxAge = 10
6 | var HttpOnly = true
7 |
8 |
9 | // response.setCookie(Name, Value, Path, MaxAge, HttpOnly)
10 | response.setCookie(Name, Value, Path, MaxAge)
11 | // response.setCookie(Name, Value, Path)
12 |
13 |
14 | var cks = request.cookies()
15 | var str = JSON.stringify(cks, null, 2)
16 | log(str)
17 |
18 | var r = request.cookie('test')
19 | if (r.err) {
20 | throw r.err;
21 | }
22 | var cookie = r.value
23 | log(cookie.name)
24 | log(cookie.value)
25 |
26 |
27 | function log(d) {
28 | console.log("%j", d);
29 | response.write(d);
30 | response.write('\r\n');
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/js/http/download.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/js/http/download.js
--------------------------------------------------------------------------------
/js/http/header.js:
--------------------------------------------------------------------------------
1 | var utils = require('utils')
2 |
3 | function log(d) {
4 | console.log("%j", d);
5 | response.write(d);
6 | response.write('\r\n');
7 | }
8 |
9 | log("getHeader('content-type'): " + request.header.get('content-type')) // application/x-www-form-urlencoded
10 | log("headers:" + JSON.stringify(request.headers, null, 2))
11 | log("headers:" + JSON.stringify(request.headers['Haha'], null, 2))
12 | var r = request.header.getRaw()
13 | log(utils.toString(r))
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/js/http/http.js:
--------------------------------------------------------------------------------
1 | var http = require("http")
2 | var file = require("file")
3 | var utils = require("utils")
4 | var url = require('url')
5 |
6 | var obj = {
7 | ticket: '99c936b0-9c35-11e7-be48-43b6cddd43aa'
8 | };
9 |
10 | var header = {
11 | "Content-Type": "application/json",
12 | "x-api-version": "1",
13 | };
14 |
15 | var method = "POST"
16 | var url = "http://esee.rabbitpre.com/api/rabuser/login"
17 | var body = JSON.stringify(obj)
18 | var data = http.request(method, url, header, body, 3000)
19 |
20 | data.body = utils.toString(data.body);
21 | console.log("data:", JSON.stringify(data, null, 2))
22 | console.log("Set-Cookie:", data.header['Set-Cookie'][0])
23 |
24 | obj = JSON.parse(data.body)
25 | var avatar = obj.result.avatar
26 | console.log("avatar:", avatar)
27 | try {
28 | data = http.request("GET", avatar, {}, '', 3000)
29 | file.write("./a.jpg", data.body)
30 | } catch (e) {
31 | console.log("err:", e)
32 | throw e;
33 | }
34 | console.log('done.');
35 |
36 |
--------------------------------------------------------------------------------
/js/http/request.js:
--------------------------------------------------------------------------------
1 |
2 | function log(d) {
3 | console.log("%j", d);
4 | response.write(d);
5 | response.write('\r\n');
6 | }
7 |
8 | // http://localhost:8080/js/http/request.js?a=b&c=d&c=22#aa
9 |
10 | log("method: " + request.method) // POST
11 | log("uri: " + request.uri) // /js/http/request.js?a=b&c=d
12 | log("host: " + request.host) // localhost:8080
13 | log("userAgent: " + request.userAgent()) // PostmanRuntime/7.1.1
14 | log("remoteAddr: " + request.remoteAddr) // [::1]:63716
15 |
16 | // 若调用 parseForm() 则body参数必需以'application/x-www-form-urlencoded'方式传递
17 | // 不调用,则可以由'application/x-www-form-urlencoded'和'multipart/form-data'传递
18 | // request.parseForm()
19 | log("test=" + request.formValue('test')) // from body test=1111 : 1111
20 |
21 | log("a=" + request.formValue('a')) // b
22 | log("c=" + request.formValue('c')) // d
23 |
24 | var values = request.form.gets('c')
25 | log(JSON.stringify(values)) // ["d","22"]
--------------------------------------------------------------------------------
/js/http/session.js:
--------------------------------------------------------------------------------
1 | // session.start() // 可选操作,如果没有调用,在set和get时会自动调用
2 | // session.end()
3 | session.set('aa', 'helloworld')
4 | console.log(session.get('aa'))
--------------------------------------------------------------------------------
/js/http/upload.js:
--------------------------------------------------------------------------------
1 | var io = require('io')
2 | var os = require('os')
3 |
4 | if (request.method === 'POST') {
5 | var err = request.parseMultipartForm(1024 * 1024)
6 | if (err) {
7 | throw err
8 | }
9 | var haha = request.formValue('haha')
10 | console.log('haha:', haha)
11 | var o = request.formFile('file')
12 | if (o.err) {
13 | throw o.err
14 | }
15 | console.log(o.name)
16 | var r = os.openFile(o.name, os.O_CREATE|os.O_WRONLY, 0666)
17 | var file = r.value
18 | io.copy(file, o.file)
19 | o.file.close()
20 | file.close()
21 | response.write(JSON.stringify(o.header, null, 2))
22 |
23 | } else {
24 | response.write("hello /")
25 | }
--------------------------------------------------------------------------------
/js/image/image.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | var image = require('image');
4 |
5 | var Image = (function () {
6 | function Image(w, h) {
7 | this.w = w;
8 | this.h = h;
9 |
10 | var rect = image.rect(0, 0, this.w, this.h)
11 | this.img = image.newRGBA(rect)
12 | }
13 | Image.prototype.drawPoint = function (x, y, rgba) {
14 | if (x >= this.w || y >= this.h || x < 0 || y < 0) {
15 | return;
16 | }
17 | if (!(rgba instanceof Object)) {
18 | rgba = {
19 | b: rgba & 0xFF, // 蓝
20 | g: (rgba >> 8) & 0xFF, // 绿
21 | r: (rgba >> 16) & 0xFF, // 红
22 | a: 255,
23 | }
24 | }
25 | this.img.setRGBA(x, y, rgba.r, rgba.g, rgba.b, rgba.a);
26 | };
27 | Image.prototype.drawLineH = function (x1, x2, y, rgba) {
28 | if (x1 > x2) {
29 | var tmp = x2;
30 | x2 = x1;
31 | x1 = tmp;
32 | }
33 | for (; x1 <= x2; x1++) {
34 | this.drawPoint(x1, y, rgba);
35 | }
36 | };
37 | Image.prototype.drawLineV = function (y1, y2, x, rgba) {
38 | if (y1 > y2) {
39 | var tmp = y2;
40 | y2 = y1;
41 | y1 = tmp;
42 | }
43 | for (; y1 <= y2; y1++) {
44 | this.drawPoint(x, y1, rgba);
45 | }
46 | };
47 | Image.prototype.drawLine = function (x1, y1, x2, y2, rgba) {
48 | var x, y, dx, dy, s1, s2, p, temp, interchange, i;
49 | x = x1;
50 | y = y1;
51 | dx = x2 > x1 ? (x2 - x1) : (x1 - x2);
52 | dy = y2 > y1 ? (y2 - y1) : (y1 - y2);
53 | s1 = x2 > x1 ? 1 : -1;
54 | s2 = y2 > y1 ? 1 : -1;
55 | if (dy > dx) {
56 | temp = dx;
57 | dx = dy;
58 | dy = temp;
59 | interchange = true;
60 | }
61 | else {
62 | interchange = false;
63 | }
64 | p = (dy << 1) - dx;
65 | for (i = 0; i <= dx; i++) {
66 | this.drawPoint(x, y, rgba);
67 | if (p >= 0) {
68 | if (interchange) {
69 | x = x + s1;
70 | }
71 | else {
72 | y = y + s2;
73 | }
74 | p = p - (dx << 1);
75 | }
76 | if (interchange) {
77 | y = y + s2;
78 | }
79 | else {
80 | x = x + s1;
81 | }
82 | p = p + (dy << 1);
83 | }
84 | };
85 | Image.prototype.drawRect = function (x1, y1, x2, y2, rgba) {
86 | this.drawLineH(x1, x2, y1, rgba);
87 | this.drawLineH(x1, x2, y2, rgba);
88 | this.drawLineV(y1, y2, x1, rgba);
89 | this.drawLineV(y1, y2, x2, rgba);
90 | };
91 | Image.prototype.fillRect = function (x1, y1, x2, y2, rgba) {
92 | var x;
93 | if (x1 > x2) {
94 | var tmp = x2;
95 | x2 = x1;
96 | x1 = tmp;
97 | }
98 | if (y1 > y2) {
99 | var tmp = y2;
100 | y2 = y1;
101 | y1 = tmp;
102 | }
103 | for (; y1 <= y2; y1++) {
104 | for (x = x1; x <= x2; x++) {
105 | this.drawPoint(x, y1, rgba);
106 | }
107 | }
108 | };
109 | Image.prototype.drawCircle = function (x, y, r, rgba) {
110 | var a, b, c;
111 | a = 0;
112 | b = r;
113 | // c = 1.25 - r;
114 | c = 3 - 2 * r;
115 | while (a < b) {
116 | this.drawPoint(x + a, y + b, rgba);
117 | this.drawPoint(x - a, y + b, rgba);
118 | this.drawPoint(x + a, y - b, rgba);
119 | this.drawPoint(x - a, y - b, rgba);
120 | this.drawPoint(x + b, y + a, rgba);
121 | this.drawPoint(x - b, y + a, rgba);
122 | this.drawPoint(x + b, y - a, rgba);
123 | this.drawPoint(x - b, y - a, rgba);
124 | if (c < 0) {
125 | c = c + 4 * a + 6;
126 | }
127 | else {
128 | c = c + 4 * (a - b) + 10;
129 | b -= 1;
130 | }
131 | a = a + 1;
132 | }
133 | if (a === b) {
134 | this.drawPoint(x + a, y + b, rgba);
135 | this.drawPoint(x - a, y + b, rgba);
136 | this.drawPoint(x + a, y - b, rgba);
137 | this.drawPoint(x - a, y + b, rgba);
138 | this.drawPoint(x + b, y + a, rgba);
139 | this.drawPoint(x - b, y + a, rgba);
140 | this.drawPoint(x + b, y - a, rgba);
141 | this.drawPoint(x - b, y - a, rgba);
142 | }
143 | };
144 | Image.prototype.drawChar = function (ch, x, y, font, rgba) {
145 | var index = font.fonts.indexOf(ch);
146 | if (index < 0) {
147 | return;
148 | }
149 | var fontData = font.data[index];
150 | var y0 = y;
151 | var x0 = x;
152 | for (var _i = 0, fontData_1 = fontData; _i < fontData_1.length; _i++) {
153 | var data = fontData_1[_i];
154 | x0 = x;
155 | for (var b = data; b > 0; b <<= 1) {
156 | if (b & 0x80) {
157 | this.drawPoint(x0, y0, rgba);
158 | }
159 | x0++;
160 | }
161 | y0++;
162 | if ((y0 - y) >= font.h) {
163 | y0 = y;
164 | x += 8;
165 | }
166 | }
167 | };
168 | Image.prototype.drawString = function (str, x, y, font, rgba) {
169 | for (var _i = 0, str_1 = str; _i < str_1.length; _i++) {
170 | var c = str_1[_i];
171 | this.drawChar(c, x, y, font, rgba);
172 | x += font.w;
173 | }
174 | };
175 | return Image;
176 | }());
177 | exports.Image = Image;
178 |
--------------------------------------------------------------------------------
/js/image/test1.js:
--------------------------------------------------------------------------------
1 | var os = require('os')
2 | var png = require('png')
3 | var font = require('./js/image/font.js')
4 | var image = require('./js/image/image.js')
5 |
6 |
7 |
8 | function writeToFile(img) {
9 | var r = os.create('image.png')
10 | if (r.err) {
11 | console.log(r.err)
12 | return
13 | }
14 | var file = r.file
15 |
16 | var err = png.encode(file, img)
17 | if (err) {
18 | console.log(err)
19 | return
20 | }
21 | var err = file.close()
22 | if (err) {
23 | console.log(err)
24 | return
25 | }
26 | console.log("done.")
27 | }
28 |
29 | function writeToResponse(img) {
30 | var err = png.encode(response, img)
31 | if (err) {
32 | console.log(err)
33 | return
34 | }
35 | }
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | var cnfonts = {
45 | w: 16,
46 | h: 16,
47 | fonts: '中国',
48 | data: [
49 | [0x01, 0x01, 0x01, 0x01, 0x3F, 0x21, 0x21, 0x21, 0x21, 0x21, 0x3F, 0x21, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x08, 0x08, 0x08, 0x08, 0x08, 0xF8, 0x08, 0x00, 0x00, 0x00, 0x00],
50 | [0x00, 0x7F, 0x40, 0x40, 0x5F, 0x41, 0x41, 0x4F, 0x41, 0x41, 0x41, 0x5F, 0x40, 0x40, 0x7F, 0x40, 0x00, 0xFC, 0x04, 0x04, 0xF4, 0x04, 0x04, 0xE4, 0x04, 0x44, 0x24, 0xF4, 0x04, 0x04, 0xFC, 0x04],
51 | ],
52 | };
53 | // 测试字库
54 | function makeImg2() {
55 | var img = new image.Image(300, 140);
56 | img.drawString('helloworld', 20, 10, font.font8x16, { r: 255, g: 0, b: 0, a: 255 });
57 | img.drawString('helloworld', 20, 25, font.font12x24, { r: 0, g: 255, b: 0, a: 255 });
58 | img.drawString('helloworld', 20, 50, font.font16x32, { r: 0, g: 0, b: 255, a: 255 });
59 | img.drawString('中国', 20, 85, cnfonts, { r: 255, g: 255, b: 0, a: 255 });
60 | return img;
61 | }
62 | // 仿PHP的rand函数
63 | function rand(min, max) {
64 | return Math.random() * (max - min + 1) + min | 0;
65 | }
66 | // 制造验证码图片
67 | function makeCapcha() {
68 | var img = new image.Image(100, 40);
69 | img.drawCircle(rand(0, 100), rand(0, 40), rand(10, 40), rand(0, 0xffffff));
70 | // 边框
71 | img.drawRect(0, 0, img.w - 1, img.h - 1, rand(0, 0xffffff));
72 | img.fillRect(rand(0, 100), rand(0, 40), rand(10, 35), rand(10, 35), rand(0, 0xffffff));
73 | img.drawLine(rand(0, 100), rand(0, 40), rand(0, 100), rand(0, 40), rand(0, 0xffffff));
74 | // return img;
75 | // 画曲线
76 | var w = img.w / 2;
77 | var h = img.h;
78 | var color = rand(0, 0xffffff);
79 | var y1 = rand(-5, 5); // Y轴位置调整
80 | var w2 = rand(10, 15); // 数值越小频率越高
81 | var h3 = rand(4, 6); // 数值越小幅度越大
82 | var bl = rand(1, 5);
83 | for (var i_1 = -w; i_1 < w; i_1 += 0.1) {
84 | var y_1 = Math.floor(h / h3 * Math.sin(i_1 / w2) + h / 2 + y1);
85 | var x_1 = Math.floor(i_1 + w);
86 | for (var j = 0; j < bl; j++) {
87 | img.drawPoint(x_1, y_1 + j, color);
88 | }
89 | }
90 | var p = 'ABCDEFGHKMNPQRSTUVWXYZ3456789';
91 | var str = '';
92 | for (var i_2 = 0; i_2 < 5; i_2++) {
93 | str += p.charAt(Math.random() * p.length | 0);
94 | }
95 | var fonts = [font.font8x16, font.font12x24, font.font16x32];
96 | var x = 15, y = 8; // tslint:disable-line
97 | for (var _i = 0, str_1 = str; _i < str_1.length; _i++) {
98 | var ch = str_1[_i];
99 | var f = fonts[Math.random() * fonts.length | 0];
100 | y = 8 + rand(-10, 10);
101 | img.drawChar(ch, x, y, f, rand(0, 0xffffff));
102 | x += f.w + rand(2, 8);
103 | }
104 | return img;
105 | }
106 |
107 | // 测试生成验证码的效率
108 | // var start = Date.now();
109 | // var i = 0;
110 | // while ((Date.now() - start) < 1000) {
111 | // makeCapcha();
112 | // // makeImg2();
113 | // i++;
114 | // }
115 | // console.log('1秒钟生成:' + i);
116 |
117 |
118 | // writeToResponse(makeImg2().img)
119 | writeToResponse(makeCapcha().img)
--------------------------------------------------------------------------------
/js/image/test2.js:
--------------------------------------------------------------------------------
1 | var os = require('os')
2 | var png = require('png')
3 | var image = require('image')
4 |
5 |
6 | function writeToFile(img) {
7 | var r = os.create('image.png')
8 | if (r.err) {
9 | console.log(r.err)
10 | return
11 | }
12 | var file = r.file
13 |
14 | var err = png.encode(file, img)
15 | if (err) {
16 | console.log(err)
17 | return
18 | }
19 | var err = file.close()
20 | if (err) {
21 | console.log(err)
22 | return
23 | }
24 | console.log("done.")
25 | }
26 |
27 | function writeToResponse(img) {
28 | var err = png.encode(response, img)
29 | if (err) {
30 | console.log(err)
31 | return
32 | }
33 | }
34 |
35 | // var start = Date.now();
36 | // var i = 0;
37 | // while ((Date.now() - start) < 1000) {
38 | // image.makeCapcha()
39 | // i++;
40 | // }
41 | // console.log('1秒钟生成:' + i);
42 |
43 | writeToResponse(image.makeCapcha())
44 |
--------------------------------------------------------------------------------
/js/index.js:
--------------------------------------------------------------------------------
1 |
2 | var header = response.header()
3 | header.set('location', '/public')
4 |
5 | response.writeHeader(302)
6 |
7 |
--------------------------------------------------------------------------------
/js/others/cache.js:
--------------------------------------------------------------------------------
1 | cache.set("a", 1234)
2 | cache.set("b", "bbbb")
3 |
4 | get("a")
5 | get("b")
6 | cache.del("b")
7 | get("b")
8 |
9 | var r = cache.get("c")
10 | if (!r.ok) {
11 | console.log("set c")
12 | cache.set("c", Date.now(), 10)
13 | } else {
14 | console.log("get c:", r.value)
15 | }
16 |
17 | function get(key) {
18 | var r = cache.get(key)
19 | if (r.ok) {
20 | console.log(key + ":" + r.value)
21 | } else {
22 | console.log(key + " not exists")
23 | }
24 | }
25 |
26 | get('i')
27 | console.log('oldv:', cache.add("i", 3, 10))
28 | get('i')
29 | console.log('oldv:', cache.sub("i", 2, 10))
30 | get('i')
31 |
32 | console.log("--------------------------------------")
--------------------------------------------------------------------------------
/js/others/os.js:
--------------------------------------------------------------------------------
1 | var os = require('os')
2 |
3 | console.log('args', os.args)
4 |
5 | function getwd() {
6 | var wd = os.getwd()
7 | if (wd.err) {
8 | throw err;
9 | }
10 | console.log('wd:', wd.value)
11 | }
12 |
13 | getwd()
14 | os.chdir("d:/")
15 | getwd()
16 |
17 | console.log('tmpdir:', os.tempDir())
18 | console.log('path:', os.getEnv('path'))
19 |
20 | var r = os.hostname()
21 | if (r.err) {
22 | throw err;
23 | }
24 | console.log('hostname:', r.value)
25 |
26 | var r = os.mkdir("est", 0666)
27 | if (r) {
28 | throw r;
29 | }
30 | r = os.remove('est')
31 | if (r) {
32 | throw r;
33 | }
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/js/others/require.js:
--------------------------------------------------------------------------------
1 | var fmt = require('fmt')
2 | var os = require('os')
3 | var utils = require('utils')
4 | var file = require('file')
5 |
6 | var r = cache.get("a")
7 |
8 | if (!r.ok) {
9 | console.log('set a')
10 | cache.set("a", 11.9, 10)
11 | }
12 |
13 | fmt.printf("%s %d %T \n", 'hello', 123, { a: true })
14 |
15 | var list = require_list()
16 | var str = JSON.stringify(list, null, 2)
17 |
18 | console.log('require_list:', str)
19 |
20 |
21 |
22 | var fs = require_get('fs')
23 | if (!fs) {
24 | var myExports = {
25 | foo: function () {
26 | console.log('foooooo');
27 | },
28 | readFileSync: function (name) {
29 | var r = file.read(name);
30 | if (r.err) {
31 | throw r.err
32 | }
33 | return utils.toString(r.value);
34 | },
35 | existsSync: function (name) {
36 | var r = os.stat(name)
37 | return !r.err;
38 | }
39 | }
40 | var myModule = {
41 | exports: myExports,
42 | a: true,
43 | b: 1234,
44 | c: 'asdf',
45 | d: [1, 4, 6]
46 | };
47 | require_set('fs', myModule);
48 | }
49 | var fs = require('fs');
50 | fs.foo();
51 | var name = './test/a.js';
52 | var r = fs.existsSync('asdf')
53 | console.log('existsSync:', r)
54 | var r = fs.readFileSync(name);
55 | console.log(r.toString())
56 |
57 |
--------------------------------------------------------------------------------
/js/others/return.js:
--------------------------------------------------------------------------------
1 | var types = require('types');
2 |
3 | var a = types.retNil();
4 | // console.log('a:', a === null) // false
5 | console.log('a:', a === undefined) // ture
6 |
7 | var b = types.retNull();
8 | // console.log(b === null) // true
9 | console.log(b === undefined) // false
10 |
11 | var c = types.retUndefined()
12 | // console.log(c === null) // false
13 | console.log(c === undefined) // true
14 | console.log('=a:', c === a) // true
15 | console.log('=b:', c === b) // true
--------------------------------------------------------------------------------
/js/others/types.js:
--------------------------------------------------------------------------------
1 | var types = require('types')
2 | console.log(types.err())
3 | console.log("%j", types.err())
4 | console.log(JSON.stringify(types.err()))
5 | console.log(types.err2())
--------------------------------------------------------------------------------
/js/utils.js:
--------------------------------------------------------------------------------
1 | var file = require('file');
2 |
3 | exports.log = function (data) {
4 | console.log("log: %j", data);
5 | console.log("log json: ", JSON.stringify(data, null, 2));
6 | }
7 |
8 | exports.fileLoader = function (filePath) {
9 | var r = file.read(filePath);
10 | if (r.err) {
11 | throw err;
12 | }
13 | return utils.toString(r.value);
14 | }
15 |
16 | exports.toInt = function (v, def) {
17 | def = def || 0;
18 | v = parseInt(v);
19 | return isNaN(v) ? def : v;
20 | }
--------------------------------------------------------------------------------
/lib/db/db.go:
--------------------------------------------------------------------------------
1 | package db
2 |
3 | import (
4 | "database/sql"
5 |
6 | "github.com/dop251/goja"
7 | "github.com/zengming00/go-server-js/lib"
8 | )
9 |
10 | func NewDB(runtime *goja.Runtime, db *sql.DB) *goja.Object {
11 | o := runtime.NewObject()
12 | o.Set("query", func(call goja.FunctionCall) goja.Value {
13 | args := lib.GetAllArgs(&call)
14 | if query, ok := args[0].(string); ok {
15 | var rows *sql.Rows
16 | var err error
17 | if len(args) == 1 {
18 | rows, err = db.Query(query)
19 | } else {
20 | rows, err = db.Query(query, args[1:]...)
21 | }
22 | if err != nil {
23 | return lib.MakeErrorValue(runtime, err)
24 | }
25 | return lib.MakeReturnValue(runtime, NewRows(runtime, rows))
26 | }
27 | panic(runtime.NewTypeError("p0 is not a string type:%T", args[0]))
28 | })
29 |
30 | o.Set("close", func(call goja.FunctionCall) goja.Value {
31 | err := db.Close()
32 | if err != nil {
33 | return runtime.ToValue(lib.NewError(runtime, err))
34 | }
35 | return nil
36 | })
37 |
38 | o.Set("exec", func(call goja.FunctionCall) goja.Value {
39 | args := lib.GetAllArgs(&call)
40 |
41 | if query, ok := args[0].(string); ok {
42 | var result sql.Result
43 | var err error
44 | if len(args) == 1 {
45 | result, err = db.Exec(query)
46 | } else {
47 | result, err = db.Exec(query, args[1:]...)
48 | }
49 | if err != nil {
50 | return lib.MakeErrorValue(runtime, err)
51 | }
52 | return lib.MakeReturnValue(runtime, NewResult(runtime, result))
53 | }
54 | panic(runtime.NewTypeError("p0 is not a string type:%T", args[0]))
55 | })
56 |
57 | o.Set("prepare", func(call goja.FunctionCall) goja.Value {
58 | query := call.Argument(0).String()
59 | stmt, err := db.Prepare(query)
60 | if err != nil {
61 | return lib.MakeErrorValue(runtime, err)
62 | }
63 | return lib.MakeReturnValue(runtime, NewStmt(runtime, stmt))
64 | })
65 |
66 | o.Set("stats", func(call goja.FunctionCall) goja.Value {
67 | st := db.Stats()
68 | o := runtime.NewObject()
69 | o.Set("openConnections", st.OpenConnections)
70 | return o
71 | })
72 |
73 | o.Set("begin", func(call goja.FunctionCall) goja.Value {
74 | tx, err := db.Begin()
75 | if err != nil {
76 | return lib.MakeErrorValue(runtime, err)
77 | }
78 | return lib.MakeReturnValue(runtime, NewTx(runtime, tx))
79 | })
80 |
81 | o.Set("setMaxOpenConns", func(call goja.FunctionCall) goja.Value {
82 | n := call.Argument(0).ToInteger()
83 | db.SetMaxOpenConns(int(n))
84 | return nil
85 | })
86 |
87 | o.Set("setMaxIdleConns", func(call goja.FunctionCall) goja.Value {
88 | n := call.Argument(0).ToInteger()
89 | db.SetMaxIdleConns(int(n))
90 | return nil
91 | })
92 | return o
93 | }
94 |
--------------------------------------------------------------------------------
/lib/db/redis/conn.go:
--------------------------------------------------------------------------------
1 | package redis
2 |
3 | import (
4 | "github.com/dop251/goja"
5 | "github.com/garyburd/redigo/redis"
6 | "github.com/zengming00/go-server-js/lib"
7 | )
8 |
9 | func NewConn(runtime *goja.Runtime, conn redis.Conn) *goja.Object {
10 | o := runtime.NewObject()
11 | o.Set("do", func(call goja.FunctionCall) goja.Value {
12 | commandName := call.Argument(0).String()
13 | args := lib.GetAllArgs(&call)
14 | reply, err := conn.Do(commandName, args[1:]...)
15 | if err != nil {
16 | return lib.MakeErrorValue(runtime, err)
17 | }
18 | return lib.MakeReturnValue(runtime, reply)
19 | })
20 |
21 | o.Set("close", func(call goja.FunctionCall) goja.Value {
22 | err := conn.Close()
23 | if err != nil {
24 | return lib.MakeErrorValue(runtime, err)
25 | }
26 | return nil
27 | })
28 | return o
29 | }
30 |
--------------------------------------------------------------------------------
/lib/db/redis/redis.go:
--------------------------------------------------------------------------------
1 | package redis
2 |
3 | import (
4 | "github.com/dop251/goja"
5 | "github.com/garyburd/redigo/redis"
6 | "github.com/zengming00/go-server-js/lib"
7 | "github.com/zengming00/go-server-js/nodejs/require"
8 | )
9 |
10 | func init() {
11 | require.RegisterNativeModule("redis", func(runtime *goja.Runtime, module *goja.Object) {
12 | o := module.Get("exports").(*goja.Object)
13 | o.Set("dial", func(call goja.FunctionCall) goja.Value {
14 | network := call.Argument(0).String()
15 | address := call.Argument(1).String()
16 | conn, err := redis.Dial(network, address)
17 | if err != nil {
18 | return lib.MakeErrorValue(runtime, err)
19 | }
20 | return lib.MakeReturnValue(runtime, NewConn(runtime, conn))
21 | })
22 |
23 | o.Set("string", func(call goja.FunctionCall) goja.Value {
24 | repl := call.Argument(0).Export()
25 | str, err := redis.String(repl, nil)
26 | if err != nil {
27 | return lib.MakeErrorValue(runtime, err)
28 | }
29 | return lib.MakeReturnValue(runtime, str)
30 | })
31 | })
32 | }
33 |
--------------------------------------------------------------------------------
/lib/db/result.go:
--------------------------------------------------------------------------------
1 | package db
2 |
3 | import (
4 | "database/sql"
5 |
6 | "github.com/dop251/goja"
7 | "github.com/zengming00/go-server-js/lib"
8 | )
9 |
10 | func NewResult(runtime *goja.Runtime, result sql.Result) *goja.Object {
11 | o := runtime.NewObject()
12 | o.Set("lastInsertId", func(call goja.FunctionCall) goja.Value {
13 | id, err := result.LastInsertId()
14 | if err != nil {
15 | return lib.MakeErrorValue(runtime, err)
16 | }
17 | return lib.MakeReturnValue(runtime, id)
18 | })
19 |
20 | o.Set("rowsAffected", func(call goja.FunctionCall) goja.Value {
21 | rows, err := result.RowsAffected()
22 | if err != nil {
23 | return lib.MakeErrorValue(runtime, err)
24 | }
25 | return lib.MakeReturnValue(runtime, rows)
26 | })
27 | return o
28 | }
29 |
--------------------------------------------------------------------------------
/lib/db/rows.go:
--------------------------------------------------------------------------------
1 | package db
2 |
3 | import (
4 | "database/sql"
5 | "reflect"
6 |
7 | "github.com/dop251/goja"
8 | "github.com/go-sql-driver/mysql"
9 | "github.com/zengming00/go-server-js/lib"
10 | )
11 |
12 | func NewRows(runtime *goja.Runtime, rows *sql.Rows) *goja.Object {
13 | o := runtime.NewObject()
14 | o.Set("err", func(call goja.FunctionCall) goja.Value {
15 | err := rows.Err()
16 | if err != nil {
17 | return runtime.ToValue(lib.NewError(runtime, err))
18 | }
19 | return nil
20 | })
21 |
22 | o.Set("getData", func(call goja.FunctionCall) goja.Value {
23 | rows := rows
24 | cols, err := rows.Columns()
25 | if err != nil {
26 | panic(runtime.NewGoError(err))
27 | }
28 | ct, err := rows.ColumnTypes()
29 | if err != nil {
30 | panic(runtime.NewGoError(err))
31 | }
32 |
33 | arr := make([]interface{}, len(ct))
34 | for i, v := range ct {
35 | t := v.ScanType()
36 | arr[i] = reflect.New(t).Interface()
37 | }
38 |
39 | err = rows.Scan(arr...)
40 | if err != nil {
41 | panic(runtime.NewGoError(err))
42 | }
43 |
44 | m := make(map[string]interface{})
45 | for i, col := range cols {
46 | switch vv := arr[i].(type) {
47 | case *int64:
48 | m[col] = *vv
49 | case *int32:
50 | m[col] = *vv
51 | case *sql.NullString:
52 | m[col] = *vv
53 | case *sql.NullBool:
54 | m[col] = *vv
55 | case *sql.NullFloat64:
56 | m[col] = *vv
57 | case *sql.NullInt64:
58 | m[col] = *vv
59 | case *sql.RawBytes:
60 | m[col] = string(*vv)
61 | case *mysql.NullTime:
62 | m[col] = *vv
63 | case *string:
64 | m[col] = *vv
65 | default:
66 | panic(runtime.NewTypeError("unknown type %T", vv))
67 | }
68 | }
69 | return runtime.ToValue(m)
70 | })
71 |
72 | o.Set("scan", func(call goja.FunctionCall) goja.Value {
73 | args := lib.GetAllArgs(&call)
74 | err := rows.Scan(args...)
75 | if err != nil {
76 | return runtime.ToValue(lib.NewError(runtime, err))
77 | }
78 | return nil
79 | })
80 |
81 | o.Set("next", func(call goja.FunctionCall) goja.Value {
82 | r := rows.Next()
83 | return runtime.ToValue(r)
84 | })
85 |
86 | o.Set("close", func(call goja.FunctionCall) goja.Value {
87 | err := rows.Close()
88 | if err != nil {
89 | return runtime.ToValue(lib.NewError(runtime, err))
90 | }
91 | return nil
92 | })
93 | return o
94 | }
95 |
--------------------------------------------------------------------------------
/lib/db/sql.go:
--------------------------------------------------------------------------------
1 | package db
2 |
3 | import (
4 | "database/sql"
5 |
6 | "github.com/dop251/goja"
7 | "github.com/zengming00/go-server-js/lib"
8 | "github.com/zengming00/go-server-js/nodejs/require"
9 | )
10 |
11 | var reUseDb *sql.DB
12 |
13 | func init() {
14 | require.RegisterNativeModule("sql", func(runtime *goja.Runtime, module *goja.Object) {
15 | o := module.Get("exports").(*goja.Object)
16 | o.Set("open", func(call goja.FunctionCall) goja.Value {
17 | driverName := call.Argument(0).String()
18 | dataSourceName := call.Argument(1).String()
19 | reUse := call.Argument(2).ToBoolean()
20 |
21 | if reUse && reUseDb != nil {
22 | return runtime.ToValue(map[string]interface{}{
23 | "value": NewDB(runtime, reUseDb),
24 | "isReUse": true,
25 | })
26 | }
27 | db, err := sql.Open(driverName, dataSourceName)
28 | if err != nil {
29 | return lib.MakeErrorValue(runtime, err)
30 | }
31 | if reUse && reUseDb == nil {
32 | reUseDb = db
33 | }
34 | return lib.MakeReturnValue(runtime, NewDB(runtime, db))
35 | })
36 |
37 | o.Set("drivers", func(call goja.FunctionCall) goja.Value {
38 | arr := sql.Drivers()
39 | return runtime.ToValue(arr)
40 | })
41 |
42 | o.Set("newNullString", func(call goja.FunctionCall) goja.Value {
43 | return runtime.ToValue(new(sql.NullString))
44 | })
45 |
46 | o.Set("nullStringValue", func(call goja.FunctionCall) goja.Value {
47 | v := call.Argument(0).Export()
48 | if vv, ok := v.(*sql.NullString); ok {
49 | return runtime.ToValue(map[string]interface{}{
50 | "value": vv.String,
51 | "valid": vv.Valid,
52 | })
53 | }
54 | panic(runtime.NewTypeError("p0 is not sql.NullString type:%T", v))
55 | })
56 |
57 | o.Set("newNullBool", func(call goja.FunctionCall) goja.Value {
58 | return runtime.ToValue(new(sql.NullBool))
59 | })
60 |
61 | o.Set("nullBoolValue", func(call goja.FunctionCall) goja.Value {
62 | v := call.Argument(0).Export()
63 | if vv, ok := v.(*sql.NullBool); ok {
64 | return runtime.ToValue(map[string]interface{}{
65 | "value": vv.Bool,
66 | "valid": vv.Valid,
67 | })
68 | }
69 | panic(runtime.NewTypeError("p0 is not sql.NullBool type:%T", v))
70 | })
71 |
72 | o.Set("newNullFloat64", func(call goja.FunctionCall) goja.Value {
73 | return runtime.ToValue(new(sql.NullFloat64))
74 | })
75 |
76 | o.Set("nullFloat64Value", func(call goja.FunctionCall) goja.Value {
77 | v := call.Argument(0).Export()
78 | if vv, ok := v.(*sql.NullFloat64); ok {
79 | return runtime.ToValue(map[string]interface{}{
80 | "value": vv.Float64,
81 | "valid": vv.Valid,
82 | })
83 | }
84 | panic(runtime.NewTypeError("p0 is not sql.NullFloat64 type:%T", v))
85 | })
86 |
87 | o.Set("newNullInt64", func(call goja.FunctionCall) goja.Value {
88 | return runtime.ToValue(new(sql.NullInt64))
89 | })
90 |
91 | o.Set("nullInt64Value", func(call goja.FunctionCall) goja.Value {
92 | v := call.Argument(0).Export()
93 | if vv, ok := v.(*sql.NullInt64); ok {
94 | return runtime.ToValue(map[string]interface{}{
95 | "value": vv.Int64,
96 | "valid": vv.Valid,
97 | })
98 | }
99 | panic(runtime.NewTypeError("p0 is not sql.NullInt64 type:%T", v))
100 | })
101 |
102 | })
103 | }
104 |
--------------------------------------------------------------------------------
/lib/db/stmt.go:
--------------------------------------------------------------------------------
1 | package db
2 |
3 | import (
4 | "database/sql"
5 |
6 | "github.com/dop251/goja"
7 | "github.com/zengming00/go-server-js/lib"
8 | )
9 |
10 | func NewStmt(runtime *goja.Runtime, stmt *sql.Stmt) *goja.Object {
11 | o := runtime.NewObject()
12 | o.Set("exec", func(call goja.FunctionCall) goja.Value {
13 | args := lib.GetAllArgs(&call)
14 | result, err := stmt.Exec(args...)
15 | if err != nil {
16 | return lib.MakeErrorValue(runtime, err)
17 | }
18 | return lib.MakeReturnValue(runtime, NewResult(runtime, result))
19 | })
20 | return o
21 | }
22 |
--------------------------------------------------------------------------------
/lib/db/tx.go:
--------------------------------------------------------------------------------
1 | package db
2 |
3 | import (
4 | "database/sql"
5 |
6 | "github.com/dop251/goja"
7 | "github.com/zengming00/go-server-js/lib"
8 | )
9 |
10 | func NewTx(runtime *goja.Runtime, tx *sql.Tx) *goja.Object {
11 | // todo
12 | o := runtime.NewObject()
13 | o.Set("commit", func(call goja.FunctionCall) goja.Value {
14 | err := tx.Commit()
15 | if err != nil {
16 | return lib.MakeErrorValue(runtime, err)
17 | }
18 | return nil
19 | })
20 | return o
21 | }
22 |
--------------------------------------------------------------------------------
/lib/error.go:
--------------------------------------------------------------------------------
1 | package lib
2 |
3 | import (
4 | "errors"
5 |
6 | "github.com/dop251/goja"
7 | "github.com/zengming00/go-server-js/nodejs/require"
8 | )
9 |
10 | func NewError(runtime *goja.Runtime, err error) *goja.Object {
11 | o := runtime.NewObject()
12 | o.Set("error", func(call goja.FunctionCall) goja.Value {
13 | return runtime.ToValue(err.Error())
14 | })
15 |
16 | o.Set("nativeType", err)
17 |
18 | return o
19 | }
20 |
21 | func init() {
22 | require.RegisterNativeModule("error", func(runtime *goja.Runtime, module *goja.Object) {
23 | o := module.Get("exports").(*goja.Object)
24 | o.Set("new", func(call goja.FunctionCall) goja.Value {
25 | text := call.Argument(0).String()
26 | err := errors.New(text)
27 | return NewError(runtime, err)
28 | })
29 | })
30 | }
31 |
--------------------------------------------------------------------------------
/lib/file.go:
--------------------------------------------------------------------------------
1 | package lib
2 |
3 | import (
4 | "io/ioutil"
5 | "os"
6 |
7 | "github.com/dop251/goja"
8 | "github.com/zengming00/go-server-js/nodejs/require"
9 | )
10 |
11 | func NewFile(runtime *goja.Runtime, file *os.File) *goja.Object {
12 | o := runtime.NewObject()
13 | o.Set("writeString", func(call goja.FunctionCall) goja.Value {
14 | s := call.Argument(0).String()
15 | n, err := file.WriteString(s)
16 | if err != nil {
17 | return MakeErrorValue(runtime, err)
18 | }
19 | return MakeReturnValue(runtime, n)
20 | })
21 |
22 | o.Set("close", func(call goja.FunctionCall) goja.Value {
23 | err := file.Close()
24 | if err != nil {
25 | return MakeErrorValue(runtime, err)
26 | }
27 | return nil
28 | })
29 |
30 | o.Set("nativeType", file)
31 |
32 | return o
33 | }
34 |
35 | func init() {
36 | require.RegisterNativeModule("file", func(runtime *goja.Runtime, module *goja.Object) {
37 | o := module.Get("exports").(*goja.Object)
38 | o.Set("write", func(call goja.FunctionCall) goja.Value {
39 | filename := call.Argument(0).String()
40 | data := call.Argument(1).Export()
41 | if bts, ok := data.([]byte); ok {
42 | err := ioutil.WriteFile(filename, bts, 0666)
43 | if err != nil {
44 | return MakeErrorValue(runtime, err)
45 | }
46 | return nil
47 | }
48 | panic(runtime.NewTypeError("p1 is not []byte type:%T", data))
49 | })
50 |
51 | o.Set("read", func(call goja.FunctionCall) goja.Value {
52 | filename := call.Argument(0).String()
53 | data, err := ioutil.ReadFile(filename)
54 | if err != nil {
55 | return MakeErrorValue(runtime, err)
56 | }
57 | return MakeReturnValue(runtime, data)
58 | })
59 | })
60 | }
61 |
--------------------------------------------------------------------------------
/lib/fmt.go:
--------------------------------------------------------------------------------
1 | package lib
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/dop251/goja"
7 | "github.com/zengming00/go-server-js/nodejs/require"
8 | )
9 |
10 | func init() {
11 | require.RegisterNativeModule("fmt", func(runtime *goja.Runtime, module *goja.Object) {
12 | o := module.Get("exports").(*goja.Object)
13 | o.Set("sprintf", func(call goja.FunctionCall) goja.Value {
14 | format := call.Argument(0).String()
15 | args := GetAllArgs(&call)
16 | str := fmt.Sprintf(format, args[1:]...)
17 | return runtime.ToValue(str)
18 | })
19 |
20 | o.Set("printf", func(call goja.FunctionCall) goja.Value {
21 | format := call.Argument(0).String()
22 | args := GetAllArgs(&call)
23 | n, err := fmt.Printf(format, args[1:]...)
24 | if err != nil {
25 | return MakeErrorValue(runtime, err)
26 | }
27 | return MakeReturnValue(runtime, n)
28 | })
29 |
30 | o.Set("println", func(call goja.FunctionCall) goja.Value {
31 | args := GetAllArgs(&call)
32 | n, err := fmt.Println(args...)
33 | if err != nil {
34 | return MakeErrorValue(runtime, err)
35 | }
36 | return MakeReturnValue(runtime, n)
37 | })
38 |
39 | o.Set("print", func(call goja.FunctionCall) goja.Value {
40 | args := GetAllArgs(&call)
41 | n, err := fmt.Print(args...)
42 | if err != nil {
43 | return MakeErrorValue(runtime, err)
44 | }
45 | return MakeReturnValue(runtime, n)
46 | })
47 | })
48 | }
49 |
--------------------------------------------------------------------------------
/lib/image/image.go:
--------------------------------------------------------------------------------
1 | package image
2 |
3 | import (
4 | "image"
5 |
6 | "github.com/dop251/goja"
7 | "github.com/zengming00/go-server-js/lib/image/lib"
8 | "github.com/zengming00/go-server-js/nodejs/require"
9 | )
10 |
11 | func init() {
12 | require.RegisterNativeModule("image", func(runtime *goja.Runtime, module *goja.Object) {
13 | o := module.Get("exports").(*goja.Object)
14 | o.Set("rect", func(call goja.FunctionCall) goja.Value {
15 | x0 := int(call.Argument(0).ToInteger())
16 | y0 := int(call.Argument(1).ToInteger())
17 | x1 := int(call.Argument(2).ToInteger())
18 | y1 := int(call.Argument(3).ToInteger())
19 | // TODO
20 | rect := image.Rect(x0, y0, x1, y1)
21 | return runtime.ToValue(rect)
22 | })
23 |
24 | o.Set("newRGBA", func(call goja.FunctionCall) goja.Value {
25 | r := call.Argument(0).Export()
26 | if rect, ok := r.(image.Rectangle); ok {
27 | rgba := image.NewRGBA(rect)
28 | return runtime.ToValue(NewRGBA(runtime, rgba))
29 | }
30 | panic(runtime.NewTypeError("p0 is not a image.Rectangle type:%T", r))
31 | })
32 |
33 | o.Set("makeCapcha", func(call goja.FunctionCall) goja.Value {
34 | rgba := lib.MakeCapcha()
35 | return runtime.ToValue(NewRGBA(runtime, rgba))
36 | })
37 |
38 | })
39 | }
40 |
--------------------------------------------------------------------------------
/lib/image/lib/img.go:
--------------------------------------------------------------------------------
1 | package lib
2 |
3 | import (
4 | "image"
5 | "time"
6 |
7 | "image/color"
8 | "math"
9 | mrand "math/rand"
10 | "unicode/utf8"
11 | )
12 |
13 | func rand(min, max int) int {
14 | return mrand.Intn(max + 1)
15 | }
16 |
17 | func randColor() color.Color {
18 | return &color.RGBA{
19 | R: uint8(rand(0, 255)),
20 | G: uint8(rand(0, 255)),
21 | B: uint8(rand(0, 255)),
22 | A: 255,
23 | }
24 | }
25 |
26 | func MakeCapcha() *image.RGBA {
27 | mrand.Seed(time.Now().UnixNano())
28 | const imgw = 100
29 | const imgh = 40
30 | img := image.NewRGBA(image.Rect(0, 0, imgw, imgh))
31 | DrawCircle(img, rand(0, 100), rand(0, 40), rand(10, 40), randColor())
32 | // 边框
33 | DrawRect(img, 0, 0, imgw-1, imgh-1, randColor())
34 | FillRect(img, rand(0, 100), rand(0, 40), rand(10, 35), rand(10, 35), randColor())
35 | DrawLine(img, rand(0, 100), rand(0, 40), rand(0, 100), rand(0, 40), randColor())
36 | // return img;
37 | // 画曲线
38 | var w = float64(imgw / 2)
39 | var h = float64(imgh)
40 | var color = randColor()
41 | var y1 = float64(rand(-5, 5))
42 | var w2 = float64(rand(10, 15))
43 | var h3 = float64(rand(4, 6))
44 | var bl = rand(1, 5)
45 | for i1 := -w; i1 < w; i1 += 0.1 {
46 | var y1 = math.Floor(h/h3*math.Sin(i1/w2) + h/2 + y1)
47 | var x1 = math.Floor(i1 + w)
48 | for j := 0; j < bl; j++ {
49 | img.Set(int(x1), int(y1+float64(j)), color)
50 | }
51 | }
52 | var p = "ABCDEFGHKMNPQRSTUVWXYZ3456789"
53 | var plegn = utf8.RuneCountInString(p)
54 | var str = ""
55 | for i2 := 0; i2 < 5; i2++ {
56 | str += string(charAt(p, mrand.Intn(plegn)))
57 | }
58 | fonts := []*Font{Font8x16, Font12x24, Font16x32}
59 | x := 15
60 | y := 8
61 | arr := []rune(str)
62 | for i := 0; i < len(arr); i++ {
63 | var ch = arr[i]
64 | var f = fonts[mrand.Intn(len(fonts))]
65 | y = 8 + rand(-10, 10)
66 | DrawChar(img, ch, x, y, f, randColor())
67 | x += f.w + rand(2, 8)
68 | }
69 | return img
70 | }
71 |
72 | type DrawPoint interface {
73 | Set(x, y int, c color.Color)
74 | }
75 |
76 | func charAt(str string, i int) rune {
77 | arr := []rune(str)
78 | return arr[i]
79 | }
80 |
81 | func indexRune(str string, r rune) int {
82 | finded := false
83 | n := -1
84 | for _, v := range str {
85 | n++
86 | if v == r {
87 | finded = true
88 | break
89 | }
90 | }
91 | if finded {
92 | return n
93 | }
94 | return -1
95 | }
96 |
97 | func DrawLineH(img DrawPoint, x1, x2, y int, color color.Color) {
98 | if x1 > x2 {
99 | var tmp = x2
100 | x2 = x1
101 | x1 = tmp
102 | }
103 | for ; x1 <= x2; x1++ {
104 | img.Set(x1, y, color)
105 | }
106 | }
107 |
108 | func DrawLineV(img DrawPoint, y1, y2, x int, color color.Color) {
109 | if y1 > y2 {
110 | var tmp = y2
111 | y2 = y1
112 | y1 = tmp
113 | }
114 | for ; y1 <= y2; y1++ {
115 | img.Set(x, y1, color)
116 | }
117 | }
118 |
119 | func DrawLine(img DrawPoint, x1, y1, x2, y2 int, color color.Color) {
120 | var x, y, dx, dy, s1, s2, p, temp, i int
121 | var interchange bool
122 | x = x1
123 | y = y1
124 |
125 | if x2 > x1 {
126 | dx = x2 - x1
127 | } else {
128 | dx = x1 - x2
129 | }
130 | if y2 > y1 {
131 | dy = y2 - y1
132 | } else {
133 | dy = y1 - y2
134 | }
135 | if x2 > x1 {
136 | s1 = 1
137 | } else {
138 | s1 = -1
139 | }
140 | if y2 > y1 {
141 | s2 = 1
142 | } else {
143 | s2 = -1
144 | }
145 | if dy > dx {
146 | temp = dx
147 | dx = dy
148 | dy = temp
149 | interchange = true
150 | } else {
151 | interchange = false
152 | }
153 | p = (dy << 1) - dx
154 | for i = 0; i <= dx; i++ {
155 | img.Set(x, y, color)
156 | if p >= 0 {
157 | if interchange {
158 | x = x + s1
159 | } else {
160 | y = y + s2
161 | }
162 | p = p - (dx << 1)
163 | }
164 | if interchange {
165 | y = y + s2
166 | } else {
167 | x = x + s1
168 | }
169 | p = p + (dy << 1)
170 | }
171 | }
172 |
173 | func DrawRect(img DrawPoint, x1, y1, x2, y2 int, color color.Color) {
174 | DrawLineH(img, x1, x2, y1, color)
175 | DrawLineH(img, x1, x2, y2, color)
176 | DrawLineV(img, y1, y2, x1, color)
177 | DrawLineV(img, y1, y2, x2, color)
178 | }
179 |
180 | func FillRect(img DrawPoint, x1, y1, x2, y2 int, color color.Color) {
181 | var x int
182 | if x1 > x2 {
183 | var tmp = x2
184 | x2 = x1
185 | x1 = tmp
186 | }
187 | if y1 > y2 {
188 | var tmp = y2
189 | y2 = y1
190 | y1 = tmp
191 | }
192 | for ; y1 <= y2; y1++ {
193 | for x = x1; x <= x2; x++ {
194 | img.Set(x, y1, color)
195 | }
196 | }
197 | }
198 |
199 | func DrawCircle(img DrawPoint, x, y, r int, color color.Color) {
200 | var a, b, c int
201 | a = 0
202 | b = r
203 | // c = 1.25 - r;
204 | c = 3 - 2*r
205 | for a < b {
206 | img.Set(x+a, y+b, color)
207 | img.Set(x-a, y+b, color)
208 | img.Set(x+a, y-b, color)
209 | img.Set(x-a, y-b, color)
210 | img.Set(x+b, y+a, color)
211 | img.Set(x-b, y+a, color)
212 | img.Set(x+b, y-a, color)
213 | img.Set(x-b, y-a, color)
214 | if c < 0 {
215 | c = c + 4*a + 6
216 | } else {
217 | c = c + 4*(a-b) + 10
218 | b--
219 | }
220 | a = a + 1
221 | }
222 | if a == b {
223 | img.Set(x+a, y+b, color)
224 | img.Set(x-a, y+b, color)
225 | img.Set(x+a, y-b, color)
226 | img.Set(x-a, y+b, color)
227 | img.Set(x+b, y+a, color)
228 | img.Set(x-b, y+a, color)
229 | img.Set(x+b, y-a, color)
230 | img.Set(x-b, y-a, color)
231 | }
232 | }
233 |
234 | func DrawChar(img DrawPoint, ch rune, x int, y int, font *Font, color color.Color) {
235 | var index = indexRune(font.fonts, ch)
236 | if index < 0 {
237 | return
238 | }
239 | var fontData = font.data[index]
240 | var y0 = y
241 | var x0 = x
242 | for i := 0; i < len(fontData); i++ {
243 | var data = fontData[i]
244 | x0 = x
245 | for b := data; b > 0; b <<= 1 {
246 | if b&0x80 != 0 {
247 | img.Set(x0, y0, color)
248 | }
249 | x0++
250 | }
251 | y0++
252 | if (y0 - y) >= font.h {
253 | y0 = y
254 | x += 8
255 | }
256 | }
257 | }
258 |
259 | func DrawString(img DrawPoint, str string, x int, y int, font *Font, color color.Color) {
260 | for _, v := range str {
261 | DrawChar(img, rune(v), x, y, font, color)
262 | x += font.w
263 | }
264 | }
265 |
--------------------------------------------------------------------------------
/lib/image/png/png.go:
--------------------------------------------------------------------------------
1 | package png
2 |
3 | import (
4 | "image"
5 | "image/png"
6 | "io"
7 |
8 | "github.com/dop251/goja"
9 | "github.com/zengming00/go-server-js/lib"
10 | "github.com/zengming00/go-server-js/nodejs/require"
11 | )
12 |
13 | func init() {
14 | require.RegisterNativeModule("image/png", func(runtime *goja.Runtime, module *goja.Object) {
15 | o := module.Get("exports").(*goja.Object)
16 | o.Set("encode", func(call goja.FunctionCall) goja.Value {
17 | p0 := lib.GetNativeType(runtime, &call, 0)
18 | p1 := lib.GetNativeType(runtime, &call, 1)
19 |
20 | w, ok := p0.(io.Writer)
21 | if !ok {
22 | panic(runtime.NewTypeError("p0 is not io.Writer type:%T", p0))
23 | }
24 |
25 | m, ok := p1.(image.Image)
26 | if !ok {
27 | panic(runtime.NewTypeError("p1 is not image.Image type:%T", p1))
28 | }
29 | err := png.Encode(w, m)
30 | if err != nil {
31 | return lib.MakeErrorValue(runtime, err)
32 | }
33 | return nil
34 | })
35 | })
36 | }
37 |
--------------------------------------------------------------------------------
/lib/image/rgba.go:
--------------------------------------------------------------------------------
1 | package image
2 |
3 | import (
4 | "image"
5 | "image/color"
6 |
7 | "github.com/dop251/goja"
8 | )
9 |
10 | type _rgba struct {
11 | runtime *goja.Runtime
12 | rgba *image.RGBA
13 | }
14 |
15 | func (This *_rgba) drawLineH(call goja.FunctionCall) goja.Value {
16 | return nil
17 | }
18 |
19 | func (This *_rgba) drawLineV(call goja.FunctionCall) goja.Value {
20 | return nil
21 | }
22 |
23 | func (This *_rgba) drawLine(call goja.FunctionCall) goja.Value {
24 | return nil
25 | }
26 |
27 | func (This *_rgba) drawRect(call goja.FunctionCall) goja.Value {
28 | return nil
29 | }
30 |
31 | func (This *_rgba) fillRect(call goja.FunctionCall) goja.Value {
32 | return nil
33 | }
34 |
35 | func (This *_rgba) drawCircle(call goja.FunctionCall) goja.Value {
36 | return nil
37 | }
38 |
39 | func (This *_rgba) drawChar(call goja.FunctionCall) goja.Value {
40 | return nil
41 | }
42 |
43 | func (This *_rgba) drawString(call goja.FunctionCall) goja.Value {
44 | return nil
45 | }
46 |
47 | func NewRGBA(runtime *goja.Runtime, rgba *image.RGBA) *goja.Object {
48 | o := runtime.NewObject()
49 | o.Set("nativeType", rgba)
50 |
51 | o.Set("setRGBA", func(call goja.FunctionCall) goja.Value {
52 | x := int(call.Argument(0).ToInteger())
53 | y := int(call.Argument(1).ToInteger())
54 | rgba.SetRGBA(x, y, color.RGBA{
55 | R: uint8(call.Argument(2).ToInteger()),
56 | G: uint8(call.Argument(3).ToInteger()),
57 | B: uint8(call.Argument(4).ToInteger()),
58 | A: uint8(call.Argument(5).ToInteger()),
59 | })
60 | return nil
61 | })
62 | return o
63 | }
64 |
--------------------------------------------------------------------------------
/lib/io.go:
--------------------------------------------------------------------------------
1 | package lib
2 |
3 | import (
4 | "io"
5 |
6 | "github.com/dop251/goja"
7 | "github.com/zengming00/go-server-js/nodejs/require"
8 | )
9 |
10 | func init() {
11 | require.RegisterNativeModule("io", func(runtime *goja.Runtime, module *goja.Object) {
12 | o := module.Get("exports").(*goja.Object)
13 | o.Set("copy", func(call goja.FunctionCall) goja.Value {
14 | p0 := GetNativeType(runtime, &call, 0)
15 | dst, ok := p0.(io.Writer)
16 | if !ok {
17 | panic(runtime.NewTypeError("p0 is not io.Writer type:%T", p0))
18 | }
19 |
20 | p1 := GetNativeType(runtime, &call, 1)
21 | src, ok := p1.(io.Reader)
22 | if !ok {
23 | panic(runtime.NewTypeError("p1 is not io.Reader type:%T", p1))
24 | }
25 |
26 | written, err := io.Copy(dst, src)
27 | if err != nil {
28 | return MakeErrorValue(runtime, err)
29 | }
30 | return MakeReturnValue(runtime, written)
31 | })
32 | })
33 | }
34 |
--------------------------------------------------------------------------------
/lib/net/http/cookie.go:
--------------------------------------------------------------------------------
1 | package http
2 |
3 | import (
4 | "net/http"
5 |
6 | "github.com/dop251/goja"
7 | "github.com/zengming00/go-server-js/lib"
8 | )
9 |
10 | func NewCookie(runtime *goja.Runtime, cookie *http.Cookie) *goja.Object {
11 | o := runtime.NewObject()
12 | o.Set("string", func(call goja.FunctionCall) goja.Value {
13 | return runtime.ToValue(cookie.String())
14 | })
15 | o.Set("getDomain", func(call goja.FunctionCall) goja.Value {
16 | return runtime.ToValue(cookie.Domain)
17 | })
18 | o.Set("getExpires", func(call goja.FunctionCall) goja.Value {
19 | return lib.NewTime(runtime, &cookie.Expires)
20 | })
21 | o.Set("getHttpOnly", func(call goja.FunctionCall) goja.Value {
22 | return runtime.ToValue(cookie.HttpOnly)
23 | })
24 | o.Set("getMaxAge", func(call goja.FunctionCall) goja.Value {
25 | return runtime.ToValue(cookie.MaxAge)
26 | })
27 | o.Set("getName", func(call goja.FunctionCall) goja.Value {
28 | return runtime.ToValue(cookie.Name)
29 | })
30 | o.Set("getPath", func(call goja.FunctionCall) goja.Value {
31 | return runtime.ToValue(cookie.Path)
32 | })
33 | o.Set("getRaw", func(call goja.FunctionCall) goja.Value {
34 | return runtime.ToValue(cookie.Raw)
35 | })
36 | o.Set("getRawExpires", func(call goja.FunctionCall) goja.Value {
37 | return runtime.ToValue(cookie.RawExpires)
38 | })
39 | o.Set("getSecure", func(call goja.FunctionCall) goja.Value {
40 | return runtime.ToValue(cookie.Secure)
41 | })
42 | o.Set("getUnparsed", func(call goja.FunctionCall) goja.Value {
43 | return runtime.ToValue(cookie.Unparsed)
44 | })
45 | o.Set("getValue", func(call goja.FunctionCall) goja.Value {
46 | return runtime.ToValue(cookie.Value)
47 | })
48 | return o
49 | }
50 |
--------------------------------------------------------------------------------
/lib/net/http/header.go:
--------------------------------------------------------------------------------
1 | package http
2 |
3 | import (
4 | "bytes"
5 | "net/http"
6 |
7 | "github.com/dop251/goja"
8 | )
9 |
10 | func NewHeader(runtime *goja.Runtime, header http.Header) *goja.Object {
11 | o := runtime.NewObject()
12 | o.Set("add", func(call goja.FunctionCall) goja.Value {
13 | key := call.Argument(0).String()
14 | value := call.Argument(1).String()
15 | header.Add(key, value)
16 | return nil
17 | })
18 |
19 | o.Set("del", func(call goja.FunctionCall) goja.Value {
20 | key := call.Argument(0).String()
21 | header.Del(key)
22 | return nil
23 | })
24 |
25 | o.Set("get", func(call goja.FunctionCall) goja.Value {
26 | key := call.Argument(0).String()
27 | value := header.Get(key)
28 | return runtime.ToValue(value)
29 | })
30 |
31 | o.Set("gets", func(call goja.FunctionCall) goja.Value {
32 | key := call.Argument(0).String()
33 | value := header[key]
34 | return runtime.ToValue(value)
35 | })
36 |
37 | o.Set("set", func(call goja.FunctionCall) goja.Value {
38 | key := call.Argument(0).String()
39 | value := call.Argument(1).String()
40 | header.Set(key, value)
41 | return nil
42 | })
43 |
44 | o.Set("getRaw", func(call goja.FunctionCall) goja.Value {
45 | byteBuf := &bytes.Buffer{}
46 | header.Write(byteBuf)
47 | return runtime.ToValue(byteBuf.Bytes())
48 | })
49 | return o
50 | }
51 |
--------------------------------------------------------------------------------
/lib/net/http/http.go:
--------------------------------------------------------------------------------
1 | package http
2 |
3 | import (
4 | "io/ioutil"
5 | "net/http"
6 | "strings"
7 | "time"
8 |
9 | "github.com/dop251/goja"
10 | "github.com/zengming00/go-server-js/nodejs/require"
11 | )
12 |
13 | func init() {
14 | require.RegisterNativeModule("http", func(runtime *goja.Runtime, module *goja.Object) {
15 | o := module.Get("exports").(*goja.Object)
16 | o.Set("request", func(call goja.FunctionCall) goja.Value {
17 | method := call.Argument(0).String()
18 | url := call.Argument(1).String()
19 | headers := call.Argument(2).Export().(map[string]interface{})
20 | body := call.Argument(3).String()
21 | timeout := call.Argument(4).ToInteger()
22 |
23 | req, err := http.NewRequest(method, url, strings.NewReader(body))
24 | if err != nil {
25 | panic(runtime.NewGoError(err))
26 | }
27 |
28 | for k, v := range headers {
29 | if str, ok := v.(string); ok {
30 | req.Header.Set(k, str)
31 | } else {
32 | panic(runtime.NewTypeError("header[" + k + "] is not string"))
33 | }
34 | }
35 |
36 | client := &http.Client{}
37 | client.Timeout = time.Duration(timeout) * time.Millisecond
38 | res, err := client.Do(req)
39 | if err != nil {
40 | panic(runtime.NewGoError(err))
41 | }
42 | defer res.Body.Close()
43 | datas, err := ioutil.ReadAll(res.Body)
44 | if err != nil {
45 | panic(runtime.NewGoError(err))
46 | }
47 |
48 | headerObj := runtime.NewObject()
49 | for k, v := range res.Header {
50 | headerObj.Set(k, v)
51 | }
52 | return runtime.ToValue(map[string]interface{}{
53 | "body": datas,
54 | "header": headerObj,
55 | })
56 | })
57 | })
58 | }
59 |
--------------------------------------------------------------------------------
/lib/net/http/multipartFile.go:
--------------------------------------------------------------------------------
1 | package http
2 |
3 | import (
4 | "mime/multipart"
5 |
6 | "github.com/dop251/goja"
7 | "github.com/zengming00/go-server-js/lib"
8 | )
9 |
10 | func NewMultipartFile(runtime *goja.Runtime, file multipart.File) *goja.Object {
11 | o := runtime.NewObject()
12 | o.Set("nativeType", file)
13 |
14 | o.Set("read", func(call goja.FunctionCall) goja.Value {
15 | p0 := call.Argument(0).Export()
16 | if buf, ok := p0.([]byte); ok {
17 | n, err := file.Read(buf)
18 | if err != nil {
19 | return lib.MakeErrorValue(runtime, err)
20 | }
21 | return lib.MakeReturnValue(runtime, n)
22 | }
23 | panic(runtime.NewTypeError("p0 is not []byte type:%T", p0))
24 | })
25 |
26 | o.Set("readAt", func(call goja.FunctionCall) goja.Value {
27 | p0 := call.Argument(0).Export()
28 | off := call.Argument(1).ToInteger()
29 | if buf, ok := p0.([]byte); ok {
30 | n, err := file.ReadAt(buf, off)
31 | if err != nil {
32 | return lib.MakeErrorValue(runtime, err)
33 | }
34 | return lib.MakeReturnValue(runtime, n)
35 | }
36 | panic(runtime.NewTypeError("p0 is not []byte type:%T", p0))
37 | })
38 |
39 | o.Set("seek", func(call goja.FunctionCall) goja.Value {
40 | offset := call.Argument(0).ToInteger()
41 | whence := call.Argument(1).ToInteger()
42 | v, err := file.Seek(offset, int(whence))
43 | if err != nil {
44 | return lib.MakeErrorValue(runtime, err)
45 | }
46 | return lib.MakeReturnValue(runtime, v)
47 | })
48 |
49 | o.Set("close", func(call goja.FunctionCall) goja.Value {
50 | err := file.Close()
51 | if err != nil {
52 | return runtime.ToValue(lib.NewError(runtime, err))
53 | }
54 | return nil
55 | })
56 |
57 | return o
58 | }
59 |
--------------------------------------------------------------------------------
/lib/net/http/request.go:
--------------------------------------------------------------------------------
1 | package http
2 |
3 | import (
4 | "io/ioutil"
5 | "net/http"
6 |
7 | "github.com/dop251/goja"
8 | "github.com/zengming00/go-server-js/lib"
9 | "github.com/zengming00/go-server-js/lib/net/url"
10 | )
11 |
12 | func NewRequest(runtime *goja.Runtime, r *http.Request) *goja.Object {
13 | o := runtime.NewObject()
14 |
15 | o.Set("isMissingFile", func(call goja.FunctionCall) goja.Value {
16 | p0 := lib.GetNativeType(runtime, &call, 0)
17 | if err, ok := p0.(error); ok {
18 | return runtime.ToValue(err == http.ErrMissingFile)
19 | }
20 | panic(runtime.NewTypeError("p0 is not error type:%T", p0))
21 | })
22 |
23 | o.Set("getContentLength", func(call goja.FunctionCall) goja.Value {
24 | return runtime.ToValue(r.ContentLength)
25 | })
26 |
27 | o.Set("getMethod", func(call goja.FunctionCall) goja.Value {
28 | return runtime.ToValue(r.Method)
29 | })
30 |
31 | o.Set("getHost", func(call goja.FunctionCall) goja.Value {
32 | return runtime.ToValue(r.Host)
33 | })
34 |
35 | o.Set("getBody", func(call goja.FunctionCall) goja.Value {
36 | //todo
37 | return runtime.ToValue(r.Body)
38 | })
39 |
40 | o.Set("getHeader", func(call goja.FunctionCall) goja.Value {
41 | return NewHeader(runtime, r.Header)
42 | })
43 |
44 | o.Set("getHeaders", func(call goja.FunctionCall) goja.Value {
45 | return runtime.ToValue(map[string][]string(r.Header))
46 | })
47 |
48 | o.Set("getUri", func(call goja.FunctionCall) goja.Value {
49 | return runtime.ToValue(r.RequestURI)
50 | })
51 |
52 | o.Set("getUrl", func(call goja.FunctionCall) goja.Value {
53 | return url.NewURL(runtime, r.URL)
54 | })
55 |
56 | o.Set("getRemoteAddr", func(call goja.FunctionCall) goja.Value {
57 | return runtime.ToValue(r.RemoteAddr)
58 | })
59 |
60 | o.Set("getForm", func(call goja.FunctionCall) goja.Value {
61 | return url.NewValues(runtime, r.Form)
62 | })
63 |
64 | o.Set("formValue", func(call goja.FunctionCall) goja.Value {
65 | key := call.Argument(0).String()
66 | value := r.FormValue(key)
67 | return runtime.ToValue(value)
68 | })
69 |
70 | o.Set("formFile", func(call goja.FunctionCall) goja.Value {
71 | key := call.Argument(0).String()
72 | file, fileHeader, err := r.FormFile(key)
73 | if err != nil {
74 | return lib.MakeErrorValue(runtime, err)
75 | }
76 | return runtime.ToValue(map[string]interface{}{
77 | "file": NewMultipartFile(runtime, file),
78 | "name": fileHeader.Filename,
79 | "header": map[string][]string(fileHeader.Header),
80 | })
81 | })
82 |
83 | o.Set("userAgent", func(call goja.FunctionCall) goja.Value {
84 | value := r.UserAgent()
85 | return runtime.ToValue(value)
86 | })
87 |
88 | o.Set("parseForm", func(call goja.FunctionCall) goja.Value {
89 | err := r.ParseForm()
90 | if err != nil {
91 | return lib.MakeErrorValue(runtime, err)
92 | }
93 | return nil
94 | })
95 |
96 | o.Set("parseMultipartForm", func(call goja.FunctionCall) goja.Value {
97 | maxMemory := call.Argument(0).ToInteger()
98 | err := r.ParseMultipartForm(maxMemory)
99 | if err != nil {
100 | return lib.MakeErrorValue(runtime, err)
101 | }
102 | return nil
103 | })
104 |
105 | o.Set("cookie", func(call goja.FunctionCall) goja.Value {
106 | name := call.Argument(0).String()
107 | c, err := r.Cookie(name)
108 | if err != nil {
109 | return lib.MakeErrorValue(runtime, err)
110 | }
111 | return lib.MakeReturnValue(runtime, NewCookie(runtime, c))
112 | })
113 |
114 | o.Set("cookies", func(call goja.FunctionCall) goja.Value {
115 | cks := r.Cookies()
116 | arr := make([]*goja.Object, len(cks))
117 | for i, v := range cks {
118 | arr[i] = NewCookie(runtime, v)
119 | }
120 | return runtime.ToValue(arr)
121 | })
122 |
123 | o.Set("getRawBody", func(call goja.FunctionCall) goja.Value {
124 | bts, err := ioutil.ReadAll(r.Body)
125 | if err != nil {
126 | return lib.MakeErrorValue(runtime, err)
127 | }
128 | return lib.MakeReturnValue(runtime, bts)
129 | })
130 |
131 | return o
132 | }
133 |
--------------------------------------------------------------------------------
/lib/net/http/response.go:
--------------------------------------------------------------------------------
1 | package http
2 |
3 | import (
4 | "net/http"
5 |
6 | "github.com/dop251/goja"
7 | "github.com/zengming00/go-server-js/lib"
8 | )
9 |
10 | func NewResponse(runtime *goja.Runtime, w http.ResponseWriter) *goja.Object {
11 | o := runtime.NewObject()
12 | o.Set("header", func(call goja.FunctionCall) goja.Value {
13 | return NewHeader(runtime, w.Header())
14 | })
15 |
16 | o.Set("write", func(call goja.FunctionCall) goja.Value {
17 | p0 := call.Argument(0).Export()
18 |
19 | var data []byte
20 | switch t := p0.(type) {
21 | case []interface{}:
22 | data = make([]byte, len(t))
23 | for i, v := range t {
24 | if val, ok := v.(int64); ok {
25 | if val >= 0 && val <= 255 {
26 | data[i] = byte(val)
27 | continue
28 | }
29 | }
30 | panic(runtime.NewTypeError("can not convert to byte `data[%d]:%T`", i, v))
31 | }
32 | case []byte:
33 | data = t
34 | case string:
35 | data = []byte(t)
36 | default:
37 | panic(runtime.NewTypeError("data is not a []byte or string type:%T", t))
38 | }
39 |
40 | n, err := w.Write(data)
41 | if err != nil {
42 | return lib.MakeErrorValue(runtime, err)
43 | }
44 | return lib.MakeReturnValue(runtime, n)
45 | })
46 |
47 | o.Set("writeHeader", func(call goja.FunctionCall) goja.Value {
48 | n := call.Argument(0).ToInteger()
49 | w.WriteHeader(int(n))
50 | return nil
51 | })
52 |
53 | o.Set("setCookie", func(call goja.FunctionCall) goja.Value {
54 | cookie := &http.Cookie{}
55 | cookie.Name = call.Argument(0).String()
56 | cookie.Value = call.Argument(1).String()
57 | cookie.Path = call.Argument(2).String()
58 | cookie.MaxAge = int(call.Argument(3).ToInteger())
59 | cookie.HttpOnly = call.Argument(4).ToBoolean()
60 | http.SetCookie(w, cookie)
61 | return nil
62 | })
63 |
64 | o.Set("nativeType", w)
65 |
66 | return o
67 | }
68 |
--------------------------------------------------------------------------------
/lib/net/url/url.go:
--------------------------------------------------------------------------------
1 | package url
2 |
3 | import (
4 | "net/url"
5 |
6 | "github.com/dop251/goja"
7 | "github.com/zengming00/go-server-js/lib"
8 | "github.com/zengming00/go-server-js/nodejs/require"
9 | )
10 |
11 | func NewURL(runtime *goja.Runtime, u *url.URL) *goja.Object {
12 | // TODO
13 | o := runtime.NewObject()
14 | o.Set("getForceQuery", func(call goja.FunctionCall) goja.Value {
15 | return runtime.ToValue(u.ForceQuery)
16 | })
17 |
18 | o.Set("getFragment", func(call goja.FunctionCall) goja.Value {
19 | return runtime.ToValue(u.Fragment)
20 | })
21 |
22 | o.Set("getHost", func(call goja.FunctionCall) goja.Value {
23 | return runtime.ToValue(u.Host)
24 | })
25 |
26 | o.Set("getOpaque", func(call goja.FunctionCall) goja.Value {
27 | return runtime.ToValue(u.Opaque)
28 | })
29 |
30 | o.Set("getPath", func(call goja.FunctionCall) goja.Value {
31 | return runtime.ToValue(u.Path)
32 | })
33 |
34 | o.Set("getRawPath", func(call goja.FunctionCall) goja.Value {
35 | return runtime.ToValue(u.RawPath)
36 | })
37 |
38 | o.Set("getRawQuery", func(call goja.FunctionCall) goja.Value {
39 | return runtime.ToValue(u.RawQuery)
40 | })
41 |
42 | o.Set("getScheme", func(call goja.FunctionCall) goja.Value {
43 | return runtime.ToValue(u.Scheme)
44 | })
45 |
46 | o.Set("getPort", func(call goja.FunctionCall) goja.Value {
47 | return runtime.ToValue(u.Port())
48 | })
49 |
50 | return o
51 | }
52 |
53 | func init() {
54 | require.RegisterNativeModule("url", func(runtime *goja.Runtime, module *goja.Object) {
55 | o := module.Get("exports").(*goja.Object)
56 | o.Set("parse", func(call goja.FunctionCall) goja.Value {
57 | rawurl := call.Argument(0).String()
58 | u, err := url.Parse(rawurl)
59 | if err != nil {
60 | return lib.MakeErrorValue(runtime, err)
61 | }
62 | return lib.MakeReturnValue(runtime, NewURL(runtime, u))
63 | })
64 |
65 | o.Set("queryEscape", func(call goja.FunctionCall) goja.Value {
66 | str := url.QueryEscape(call.Argument(0).String())
67 | return runtime.ToValue(str)
68 | })
69 |
70 | o.Set("queryUnescape", func(call goja.FunctionCall) goja.Value {
71 | str, err := url.QueryUnescape(call.Argument(0).String())
72 | if err != nil {
73 | return lib.MakeErrorValue(runtime, err)
74 | }
75 | return lib.MakeReturnValue(runtime, str)
76 | })
77 |
78 | o.Set("parseRequestURI", func(call goja.FunctionCall) goja.Value {
79 | rawurl := call.Argument(0).String()
80 | mUrl, err := url.ParseRequestURI(rawurl)
81 | if err != nil {
82 | return lib.MakeErrorValue(runtime, err)
83 | }
84 | return lib.MakeReturnValue(runtime, NewURL(runtime, mUrl))
85 | })
86 |
87 | o.Set("parseQuery", func(call goja.FunctionCall) goja.Value {
88 | query := call.Argument(0).String()
89 | values, err := url.ParseQuery(query)
90 | if err != nil {
91 | return lib.MakeErrorValue(runtime, err)
92 | }
93 | return lib.MakeReturnValue(runtime, NewValues(runtime, values))
94 | })
95 |
96 | o.Set("newValues", func(call goja.FunctionCall) goja.Value {
97 | return NewValues(runtime, make(url.Values))
98 | })
99 | })
100 | }
101 |
--------------------------------------------------------------------------------
/lib/net/url/values.go:
--------------------------------------------------------------------------------
1 | package url
2 |
3 | import (
4 | "net/url"
5 |
6 | "github.com/dop251/goja"
7 | )
8 |
9 | func NewValues(runtime *goja.Runtime, values url.Values) *goja.Object {
10 | o := runtime.NewObject()
11 | o.Set("del", func(call goja.FunctionCall) goja.Value {
12 | key := call.Argument(0).String()
13 | values.Del(key)
14 | return nil
15 | })
16 |
17 | o.Set("add", func(call goja.FunctionCall) goja.Value {
18 | key := call.Argument(0).String()
19 | value := call.Argument(1).String()
20 | values.Add(key, value)
21 | return nil
22 | })
23 |
24 | o.Set("encode", func(call goja.FunctionCall) goja.Value {
25 | str := values.Encode()
26 | return runtime.ToValue(str)
27 | })
28 |
29 | o.Set("get", func(call goja.FunctionCall) goja.Value {
30 | key := call.Argument(0).String()
31 | str := values.Get(key)
32 | return runtime.ToValue(str)
33 | })
34 |
35 | o.Set("gets", func(call goja.FunctionCall) goja.Value {
36 | key := call.Argument(0).String()
37 | values := values[key]
38 | return runtime.ToValue(values)
39 | })
40 |
41 | o.Set("getAll", func(call goja.FunctionCall) goja.Value {
42 | return runtime.ToValue(map[string][]string(values))
43 | })
44 |
45 | o.Set("set", func(call goja.FunctionCall) goja.Value {
46 | key := call.Argument(0).String()
47 | value := call.Argument(1).String()
48 | values.Set(key, value)
49 | return nil
50 | })
51 | return o
52 | }
53 |
--------------------------------------------------------------------------------
/lib/os.go:
--------------------------------------------------------------------------------
1 | package lib
2 |
3 | import (
4 | "os"
5 |
6 | "github.com/dop251/goja"
7 | "github.com/zengming00/go-server-js/nodejs/require"
8 | )
9 |
10 | func init() {
11 | require.RegisterNativeModule("os", func(runtime *goja.Runtime, module *goja.Object) {
12 | o := module.Get("exports").(*goja.Object)
13 | o.Set("O_CREATE", os.O_CREATE)
14 | o.Set("O_WRONLY", os.O_WRONLY)
15 | o.Set("O_RDONLY", os.O_RDONLY)
16 | o.Set("O_RDWR", os.O_RDWR)
17 | o.Set("O_APPEND", os.O_APPEND)
18 | o.Set("O_EXCL", os.O_EXCL)
19 | o.Set("O_SYNC", os.O_SYNC)
20 | o.Set("O_TRUNC", os.O_TRUNC)
21 |
22 | o.Set("args", os.Args)
23 |
24 | o.Set("tempDir", func(call goja.FunctionCall) goja.Value {
25 | value := os.TempDir()
26 | return runtime.ToValue(value)
27 | })
28 |
29 | o.Set("hostname", func(call goja.FunctionCall) goja.Value {
30 | name, err := os.Hostname()
31 | if err != nil {
32 | return MakeErrorValue(runtime, err)
33 | }
34 | return MakeReturnValue(runtime, name)
35 | })
36 |
37 | o.Set("getEnv", func(call goja.FunctionCall) goja.Value {
38 | key := call.Argument(0).String()
39 | value := os.Getenv(key)
40 | return runtime.ToValue(value)
41 | })
42 |
43 | o.Set("remove", func(call goja.FunctionCall) goja.Value {
44 | name := call.Argument(0).String()
45 | err := os.Remove(name)
46 | if err != nil {
47 | return runtime.ToValue(NewError(runtime, err))
48 | }
49 | return nil
50 | })
51 |
52 | o.Set("removeAll", func(call goja.FunctionCall) goja.Value {
53 | path := call.Argument(0).String()
54 | err := os.RemoveAll(path)
55 | if err != nil {
56 | return runtime.ToValue(NewError(runtime, err))
57 | }
58 | return nil
59 | })
60 |
61 | o.Set("mkdir", func(call goja.FunctionCall) goja.Value {
62 | name := call.Argument(0).String()
63 | perm := call.Argument(1).ToInteger()
64 | err := os.Mkdir(name, os.FileMode(perm))
65 | if err != nil {
66 | return runtime.ToValue(NewError(runtime, err))
67 | }
68 | return nil
69 | })
70 |
71 | o.Set("mkdirAll", func(call goja.FunctionCall) goja.Value {
72 | path := call.Argument(0).String()
73 | perm := call.Argument(1).ToInteger()
74 | err := os.MkdirAll(path, os.FileMode(perm))
75 | if err != nil {
76 | return runtime.ToValue(NewError(runtime, err))
77 | }
78 | return nil
79 | })
80 |
81 | o.Set("getwd", func(call goja.FunctionCall) goja.Value {
82 | dir, err := os.Getwd()
83 | if err != nil {
84 | return MakeErrorValue(runtime, err)
85 | }
86 | return MakeReturnValue(runtime, dir)
87 | })
88 |
89 | o.Set("chdir", func(call goja.FunctionCall) goja.Value {
90 | dir := call.Argument(0).String()
91 | err := os.Chdir(dir)
92 | if err != nil {
93 | return runtime.ToValue(NewError(runtime, err))
94 | }
95 | return nil
96 | })
97 |
98 | o.Set("openFile", func(call goja.FunctionCall) goja.Value {
99 | name := call.Argument(0).String()
100 | flag := call.Argument(1).ToInteger()
101 | perm := call.Argument(2).ToInteger()
102 |
103 | file, err := os.OpenFile(name, int(flag), os.FileMode(perm))
104 | if err != nil {
105 | return MakeErrorValue(runtime, err)
106 | }
107 | return MakeReturnValue(runtime, NewFile(runtime, file))
108 | })
109 |
110 | o.Set("create", func(call goja.FunctionCall) goja.Value {
111 | name := call.Argument(0).String()
112 | file, err := os.Create(name)
113 | if err != nil {
114 | return MakeErrorValue(runtime, err)
115 | }
116 | return MakeReturnValue(runtime, NewFile(runtime, file))
117 | })
118 |
119 | o.Set("open", func(call goja.FunctionCall) goja.Value {
120 | name := call.Argument(0).String()
121 | file, err := os.Open(name)
122 | if err != nil {
123 | return MakeErrorValue(runtime, err)
124 | }
125 | return MakeReturnValue(runtime, NewFile(runtime, file))
126 | })
127 |
128 | o.Set("stat", func(call goja.FunctionCall) goja.Value {
129 | name := call.Argument(0).String()
130 | fileInfo, err := os.Stat(name)
131 | if err != nil {
132 | return MakeErrorValue(runtime, err)
133 | }
134 | // todo
135 | return MakeReturnValue(runtime, fileInfo)
136 | })
137 |
138 | o.Set("isExist", func(call goja.FunctionCall) goja.Value {
139 | p0 := GetNativeType(runtime, &call, 0)
140 | if err, ok := p0.(error); ok {
141 | return runtime.ToValue(os.IsExist(err))
142 | }
143 | panic(runtime.NewTypeError("p0 is not error type:%T", p0))
144 | })
145 |
146 | o.Set("isNotExist", func(call goja.FunctionCall) goja.Value {
147 | p0 := GetNativeType(runtime, &call, 0)
148 | if err, ok := p0.(error); ok {
149 | return runtime.ToValue(os.IsNotExist(err))
150 | }
151 | panic(runtime.NewTypeError("p0 is not error type:%T", p0))
152 | })
153 | })
154 | }
155 |
--------------------------------------------------------------------------------
/lib/path/filepath.go:
--------------------------------------------------------------------------------
1 | package path
2 |
3 | import (
4 | "path/filepath"
5 |
6 | "github.com/dop251/goja"
7 | "github.com/zengming00/go-server-js/lib"
8 | "github.com/zengming00/go-server-js/nodejs/require"
9 | )
10 |
11 | func init() {
12 | require.RegisterNativeModule("path/filepath", func(runtime *goja.Runtime, module *goja.Object) {
13 | o := module.Get("exports").(*goja.Object)
14 | o.Set("abs", func(call goja.FunctionCall) goja.Value {
15 | path := call.Argument(0).String()
16 | str, err := filepath.Abs(path)
17 | if err != nil {
18 | return lib.MakeErrorValue(runtime, err)
19 | }
20 | return lib.MakeReturnValue(runtime, str)
21 | })
22 |
23 | o.Set("join", func(call goja.FunctionCall) goja.Value {
24 | arr := lib.GetAllArgs_string(runtime, &call)
25 | str := filepath.Join(arr...)
26 | return runtime.ToValue(str)
27 | })
28 |
29 | o.Set("ext", func(call goja.FunctionCall) goja.Value {
30 | path := call.Argument(0).String()
31 | str := filepath.Ext(path)
32 | return runtime.ToValue(str)
33 | })
34 |
35 | })
36 | }
37 |
--------------------------------------------------------------------------------
/lib/strings.go:
--------------------------------------------------------------------------------
1 | package lib
2 |
3 | import (
4 | "strings"
5 |
6 | "github.com/dop251/goja"
7 | "github.com/zengming00/go-server-js/nodejs/require"
8 | )
9 |
10 | func init() {
11 | require.RegisterNativeModule("strings", func(runtime *goja.Runtime, module *goja.Object) {
12 | o := module.Get("exports").(*goja.Object)
13 | o.Set("hasPrefix", func(call goja.FunctionCall) goja.Value {
14 | s := call.Argument(0).String()
15 | prefix := call.Argument(1).String()
16 | return runtime.ToValue(strings.HasPrefix(s, prefix))
17 | })
18 |
19 | o.Set("hasSuffix", func(call goja.FunctionCall) goja.Value {
20 | s := call.Argument(0).String()
21 | suffix := call.Argument(1).String()
22 | return runtime.ToValue(strings.HasSuffix(s, suffix))
23 | })
24 |
25 | })
26 | }
27 |
--------------------------------------------------------------------------------
/lib/time.go:
--------------------------------------------------------------------------------
1 | package lib
2 |
3 | import (
4 | "time"
5 |
6 | "github.com/dop251/goja"
7 | "github.com/zengming00/go-server-js/nodejs/require"
8 | )
9 |
10 | func NewTime(runtime *goja.Runtime, t *time.Time) *goja.Object {
11 | o := runtime.NewObject()
12 | o.Set("string", func(call goja.FunctionCall) goja.Value {
13 | str := t.String()
14 | return runtime.ToValue(str)
15 | })
16 |
17 | return o
18 | }
19 |
20 | func init() {
21 | require.RegisterNativeModule("time", func(runtime *goja.Runtime, module *goja.Object) {
22 | o := module.Get("exports").(*goja.Object)
23 | o.Set("sleep", func(call goja.FunctionCall) goja.Value {
24 | d := call.Argument(0).ToInteger()
25 | <-time.After(time.Duration(d) * time.Millisecond)
26 | return nil
27 | })
28 |
29 | o.Set("nowString", func(call goja.FunctionCall) goja.Value {
30 | const DATE_TIME_FORMAT = "2006-01-02 15:04:05"
31 | cst := time.FixedZone("CST", 28800)
32 | str := time.Now().In(cst).Format(DATE_TIME_FORMAT)
33 | return runtime.ToValue(str)
34 | })
35 | })
36 | }
37 |
--------------------------------------------------------------------------------
/lib/types.go:
--------------------------------------------------------------------------------
1 | package lib
2 |
3 | import (
4 | "errors"
5 | "fmt"
6 |
7 | "github.com/dop251/goja"
8 | "github.com/zengming00/go-server-js/nodejs/require"
9 | )
10 |
11 | func init() {
12 | require.RegisterNativeModule("types", func(runtime *goja.Runtime, module *goja.Object) {
13 | o := module.Get("exports").(*goja.Object)
14 |
15 | o.Set("newInt", func(call goja.FunctionCall) goja.Value {
16 | return runtime.ToValue(new(int))
17 | })
18 |
19 | o.Set("intValue", func(call goja.FunctionCall) goja.Value {
20 | v := call.Argument(0).Export()
21 | if vv, ok := v.(*int); ok {
22 | return runtime.ToValue(*vv)
23 | }
24 | panic(runtime.NewTypeError("p0 is not int type:%T", v))
25 | })
26 |
27 | o.Set("newBool", func(call goja.FunctionCall) goja.Value {
28 | return runtime.ToValue(new(bool))
29 | })
30 |
31 | o.Set("boolValue", func(call goja.FunctionCall) goja.Value {
32 | v := call.Argument(0).Export()
33 | if vv, ok := v.(*bool); ok {
34 | return runtime.ToValue(*vv)
35 | }
36 | panic(runtime.NewTypeError("p0 is not bool type:%T", v))
37 | })
38 |
39 | o.Set("newString", func(call goja.FunctionCall) goja.Value {
40 | return runtime.ToValue(new(string))
41 | })
42 |
43 | o.Set("stringValue", func(call goja.FunctionCall) goja.Value {
44 | v := call.Argument(0).Export()
45 | if vv, ok := v.(*string); ok {
46 | return runtime.ToValue(*vv)
47 | }
48 | panic(runtime.NewTypeError("p0 is not string type:%T", v))
49 | })
50 |
51 | o.Set("makeByteSlice", func(call goja.FunctionCall) goja.Value {
52 | mLen := call.Argument(0).ToInteger()
53 | mCap := mLen
54 | if len(call.Arguments) != 1 {
55 | mCap = call.Argument(1).ToInteger()
56 | }
57 | v := make([]byte, mLen, mCap)
58 | return runtime.ToValue(v)
59 | })
60 |
61 | o.Set("test", func(call goja.FunctionCall) goja.Value {
62 | v := call.Argument(0).Export()
63 | fmt.Printf("%T %[1]v\n", v)
64 | return nil
65 | })
66 |
67 | o.Set("err", func(call goja.FunctionCall) goja.Value {
68 | return MakeErrorValue(runtime, errors.New("terr"))
69 | })
70 |
71 | o.Set("retNil", func(call goja.FunctionCall) goja.Value {
72 | // nil 和 goja.Undefined() 效果相同,在js中都是undefined
73 | return nil
74 | })
75 |
76 | o.Set("retUndefined", func(call goja.FunctionCall) goja.Value {
77 | return goja.Undefined()
78 | })
79 |
80 | o.Set("retNull", func(call goja.FunctionCall) goja.Value {
81 | // 在js中是null
82 | return goja.Null()
83 | })
84 |
85 | })
86 | }
87 |
--------------------------------------------------------------------------------
/lib/utils.go:
--------------------------------------------------------------------------------
1 | package lib
2 |
3 | import (
4 | "crypto/md5"
5 | "crypto/sha1"
6 | "encoding/base64"
7 | "encoding/hex"
8 | "fmt"
9 |
10 | "github.com/dop251/goja"
11 | "github.com/zengming00/go-server-js/nodejs/require"
12 | )
13 |
14 | func GetNativeType(runtime *goja.Runtime, call *goja.FunctionCall, idx int) interface{} {
15 | return call.Argument(idx).ToObject(runtime).Get("nativeType").Export()
16 | }
17 |
18 | func GetGoType(runtime *goja.Runtime, call *goja.FunctionCall, idx int) goja.Value {
19 | p := call.Argument(idx).ToObject(runtime)
20 | protoFunc, ok := goja.AssertFunction(p.Get("getGoType"))
21 | if !ok {
22 | panic(runtime.NewTypeError("p%d not have getGoType() function", idx))
23 | }
24 | obj, err := protoFunc(p)
25 | if err != nil {
26 | panic(runtime.NewGoError(err))
27 | }
28 | return obj
29 | }
30 |
31 | func GetAllArgs(call *goja.FunctionCall) []interface{} {
32 | args := make([]interface{}, len(call.Arguments))
33 | for i, v := range call.Arguments {
34 | args[i] = v.Export()
35 | }
36 | return args
37 | }
38 |
39 | func GetAllArgs_string(runtime *goja.Runtime, call *goja.FunctionCall) []string {
40 | args := make([]string, len(call.Arguments))
41 | for i, v := range call.Arguments {
42 | vv := v.Export()
43 | if s, ok := vv.(string); ok {
44 | args[i] = s
45 | } else {
46 | panic(runtime.NewTypeError("arg[%d] is not a string type:%T", i, v))
47 | }
48 | }
49 | return args
50 | }
51 |
52 | func MakeReturnValue(runtime *goja.Runtime, value interface{}) goja.Value {
53 | return runtime.ToValue(map[string]interface{}{
54 | "value": value,
55 | })
56 | }
57 |
58 | func MakeErrorValue(runtime *goja.Runtime, err error) goja.Value {
59 | return runtime.ToValue(map[string]interface{}{
60 | "err": NewError(runtime, err),
61 | })
62 | }
63 |
64 | func init() {
65 | require.RegisterNativeModule("utils", func(runtime *goja.Runtime, module *goja.Object) {
66 | o := module.Get("exports").(*goja.Object)
67 | o.Set("print", func(call goja.FunctionCall) goja.Value {
68 | fmt.Print(call.Argument(0).String())
69 | return nil
70 | })
71 |
72 | o.Set("panic", func(call goja.FunctionCall) goja.Value {
73 | panic(call.Argument(0).String())
74 | })
75 |
76 | o.Set("toString", func(call goja.FunctionCall) goja.Value {
77 | data := call.Argument(0).Export()
78 | if bts, ok := data.([]byte); ok {
79 | return runtime.ToValue(string(bts))
80 | }
81 | panic(runtime.NewTypeError("p0 is not []byte type:%T", data))
82 | })
83 |
84 | o.Set("toBase64", func(call goja.FunctionCall) goja.Value {
85 | p0 := call.Argument(0).Export()
86 | var str string
87 | switch data := p0.(type) {
88 | case []byte:
89 | str = base64.StdEncoding.EncodeToString(data)
90 | case string:
91 | str = base64.StdEncoding.EncodeToString([]byte(data))
92 | default:
93 | panic(runtime.NewTypeError("p0 is not []byte or string type:%T", p0))
94 | }
95 | return runtime.ToValue(str)
96 | })
97 |
98 | o.Set("md5", func(call goja.FunctionCall) goja.Value {
99 | p0 := call.Argument(0).Export()
100 | var r []byte
101 | switch data := p0.(type) {
102 | case []byte:
103 | tmp := md5.Sum(data)
104 | r = tmp[:]
105 | case string:
106 | tmp := md5.Sum([]byte(data))
107 | r = tmp[:]
108 | default:
109 | panic(runtime.NewTypeError("p0 is not []byte or string type:%T", p0))
110 | }
111 | return runtime.ToValue(hex.EncodeToString(r))
112 | })
113 |
114 | o.Set("sha1", func(call goja.FunctionCall) goja.Value {
115 | p0 := call.Argument(0).Export()
116 | var r []byte
117 | switch data := p0.(type) {
118 | case []byte:
119 | tmp := sha1.Sum(data)
120 | r = tmp[:]
121 | case string:
122 | tmp := sha1.Sum([]byte(data))
123 | r = tmp[:]
124 | default:
125 | panic(runtime.NewTypeError("p0 is not []byte or string type:%T", p0))
126 | }
127 | return runtime.ToValue(hex.EncodeToString(r))
128 | })
129 | })
130 | }
131 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "encoding/json"
5 | "flag"
6 | "fmt"
7 | "io/ioutil"
8 | "log"
9 | "math/rand"
10 | "net/http"
11 | "os"
12 | "path/filepath"
13 | "strings"
14 | "time"
15 |
16 | _ "github.com/zengming00/go-server-js/lib"
17 | _ "github.com/zengming00/go-server-js/lib/db"
18 | _ "github.com/zengming00/go-server-js/lib/db/redis"
19 | _ "github.com/zengming00/go-server-js/lib/image"
20 | _ "github.com/zengming00/go-server-js/lib/image/png"
21 | mhttp "github.com/zengming00/go-server-js/lib/net/http"
22 | _ "github.com/zengming00/go-server-js/lib/net/url"
23 | _ "github.com/zengming00/go-server-js/lib/path"
24 |
25 | _ "net/http/pprof"
26 |
27 | "github.com/dop251/goja"
28 | _ "github.com/go-sql-driver/mysql"
29 | "github.com/zengming00/go-server-js/nodejs/console"
30 | "github.com/zengming00/go-server-js/nodejs/require"
31 | )
32 |
33 | var configFile = flag.String("config", "config.json", "set the config.json")
34 |
35 | var _cwd string
36 | var _sessionMgr *SessionMgr
37 | var _cacheMgr *CacheMgr
38 |
39 | type _server struct {
40 | config *config
41 | writeResultValue bool
42 | }
43 |
44 | type config struct {
45 | IndexFile string
46 | Port string
47 | WorkDir *string
48 | SessionMaxLifeTimeSec int64
49 | CacheGcIntervalSec int64
50 | ScriptTimeoutSec int
51 | }
52 |
53 | func (This *_server) handler(w http.ResponseWriter, r *http.Request) {
54 | u := r.URL
55 | file := u.Path
56 | if file == "/" {
57 | file = This.config.IndexFile
58 | }
59 | file = filepath.Join(_cwd, file)
60 |
61 | if strings.HasPrefix(file, _cwd) {
62 | ext := filepath.Ext(file)
63 | if ext == ".js" {
64 | runtime := goja.New()
65 | registry := new(require.Registry)
66 | runtime.Set("response", mhttp.NewResponse(runtime, w))
67 | runtime.Set("request", mhttp.NewRequest(runtime, r))
68 | runtime.Set("cache", NewCache(runtime, _cacheMgr))
69 | runtime.Set("session", NewSession(runtime, _sessionMgr, w, r))
70 |
71 | normalEndCh := make(chan bool)
72 |
73 | go func() {
74 | ret, err := runFile(file, runtime, registry)
75 | if err != nil {
76 | switch err := err.(type) {
77 | case *goja.Exception:
78 | w.WriteHeader(http.StatusInternalServerError)
79 | fmt.Println("*goja.Exception:", err.String())
80 | if v := err.Value().ToObject(runtime).Get("nativeType"); v != nil {
81 | fmt.Printf("%T:%[1]v\n", v.Export())
82 | }
83 | case *goja.InterruptedError:
84 | fmt.Println("*goja.InterruptedError:", err.String())
85 | default:
86 | fmt.Println("default err:", err)
87 | }
88 | normalEndCh <- false
89 | return
90 | }
91 |
92 | // if goja.IsNull(*ret) || goja.IsUndefined(*ret) {
93 | // w.WriteHeader(http.StatusOK)
94 | // return
95 | // }
96 | if This.writeResultValue {
97 | // w.Header().Set("Content-Type", "text/html; charset=utf-8")
98 | w.Write([]byte((ret).String()))
99 | }
100 | normalEndCh <- true
101 | }()
102 |
103 | if This.config.ScriptTimeoutSec > 0 {
104 | timeoutCh := time.After(time.Duration(This.config.ScriptTimeoutSec) * time.Second)
105 | select {
106 | case <-timeoutCh:
107 | runtime.Interrupt("run code timeout, halt")
108 | w.WriteHeader(http.StatusInternalServerError)
109 | case <-normalEndCh:
110 | }
111 | } else {
112 | <-normalEndCh
113 | }
114 | return
115 | }
116 | }
117 | w.WriteHeader(http.StatusNotFound)
118 | }
119 |
120 | func server() {
121 | var err error
122 | s := &_server{
123 | config: &config{
124 | IndexFile: "/index.js",
125 | Port: "8080",
126 | SessionMaxLifeTimeSec: 60 * 15,
127 | CacheGcIntervalSec: 60,
128 | ScriptTimeoutSec: -1,
129 | },
130 | }
131 |
132 | initConfig(*configFile, s.config)
133 |
134 | if s.config.WorkDir != nil {
135 | err := os.Chdir(*s.config.WorkDir)
136 | if err != nil {
137 | panic(err)
138 | }
139 | }
140 |
141 | _cwd, err = os.Getwd()
142 | if err != nil {
143 | panic(err)
144 | }
145 |
146 | _sessionMgr = NewSessionMgr("sid", s.config.SessionMaxLifeTimeSec)
147 | log.Printf("SessionMaxLifeTimeSec: %d\r\n", s.config.SessionMaxLifeTimeSec)
148 |
149 | _cacheMgr = NewCacheMgr(s.config.CacheGcIntervalSec)
150 | log.Printf("CacheGcIntervalSec: %d\r\n", s.config.CacheGcIntervalSec)
151 | log.Printf("ScriptTimeoutSec: %d\r\n", s.config.ScriptTimeoutSec)
152 |
153 | http.Handle("/public/", http.StripPrefix("/public/", http.FileServer(http.Dir("./public"))))
154 | // http.Handle("/public", s.fileServer)
155 | http.HandleFunc("/", s.handler)
156 |
157 | log.Println("server running on " + s.config.Port)
158 | err = http.ListenAndServe(":"+s.config.Port, nil)
159 | if err != nil {
160 | panic(err)
161 | }
162 | }
163 |
164 | func main() {
165 | flag.Parse()
166 | // debug.SetGCPercent(1)
167 | rand.Seed(time.Now().UnixNano())
168 |
169 | if len(os.Args) == 2 {
170 | filename := os.Args[1]
171 | start := time.Now()
172 |
173 | registry := new(require.Registry)
174 | runtime := goja.New()
175 | r, err := runFile(filename, runtime, registry)
176 | if err != nil {
177 | switch err := err.(type) {
178 | case *goja.Exception:
179 | fmt.Println("*goja.Exception:", err.String())
180 | case *goja.InterruptedError:
181 | fmt.Println("*goja.InterruptedError:", err.String())
182 | default:
183 | fmt.Println("default:", err)
184 | }
185 | os.Exit(64)
186 | }
187 | fmt.Println("result:", r)
188 | fmt.Printf("done (%s)", time.Since(start))
189 | return
190 | }
191 | server()
192 | }
193 |
194 | func runFile(filename string, runtime *goja.Runtime, registry *require.Registry) (goja.Value, error) {
195 | src, err := ioutil.ReadFile(filename)
196 | if err != nil {
197 | return nil, err
198 | }
199 | registry.Enable(runtime)
200 | console.Enable(runtime)
201 |
202 | // (function(){ ... })() 用来允许直接在文件顶层return
203 | prg, err := goja.Compile(filename, "(function(){"+string(src)+"\n})()", false)
204 | if err != nil {
205 | return nil, err
206 | }
207 |
208 | result, err := runtime.RunProgram(prg)
209 | if err != nil {
210 | return nil, err
211 | }
212 | return result, nil
213 | }
214 |
215 | func initConfig(path string, v interface{}) {
216 | _, err := os.Stat(path)
217 | if err != nil {
218 | if os.IsNotExist(err) {
219 | bts, err := json.MarshalIndent(v, "", " ")
220 | if err != nil {
221 | panic(err)
222 | }
223 | err = ioutil.WriteFile(path, bts, 0666)
224 | if err != nil {
225 | panic(err)
226 | }
227 | return
228 | }
229 | panic(err)
230 | }
231 | file, err := os.Open(path)
232 | if err != nil {
233 | panic(err)
234 | }
235 | defer file.Close()
236 | dec := json.NewDecoder(file)
237 | err = dec.Decode(v)
238 | if err != nil {
239 | panic(err)
240 | }
241 | }
242 |
--------------------------------------------------------------------------------
/nodejs/console/module.go:
--------------------------------------------------------------------------------
1 | package console
2 |
3 | import (
4 | "log"
5 |
6 | "github.com/dop251/goja"
7 | "github.com/zengming00/go-server-js/nodejs/require"
8 | _ "github.com/zengming00/go-server-js/nodejs/util"
9 | )
10 |
11 | type Console struct {
12 | runtime *goja.Runtime
13 | util *goja.Object
14 | }
15 |
16 | func (c *Console) log(call goja.FunctionCall) goja.Value {
17 | if format, ok := goja.AssertFunction(c.util.Get("format")); ok {
18 | ret, err := format(c.util, call.Arguments...)
19 | if err != nil {
20 | panic(err)
21 | }
22 |
23 | log.Print(ret.String())
24 | } else {
25 | panic(c.runtime.NewTypeError("util.format is not a function"))
26 | }
27 |
28 | return nil
29 | }
30 |
31 | func Require(runtime *goja.Runtime, module *goja.Object) {
32 | c := &Console{
33 | runtime: runtime,
34 | }
35 |
36 | c.util = require.Require(runtime, "util").(*goja.Object)
37 |
38 | o := module.Get("exports").(*goja.Object)
39 | o.Set("log", c.log)
40 | o.Set("error", c.log)
41 | o.Set("warn", c.log)
42 |
43 | }
44 |
45 | func Enable(runtime *goja.Runtime) {
46 | runtime.Set("console", require.Require(runtime, "console"))
47 | }
48 |
49 | func init() {
50 | require.RegisterNativeModule("console", Require)
51 | }
52 |
--------------------------------------------------------------------------------
/nodejs/console/module_test.go:
--------------------------------------------------------------------------------
1 | package console
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/dop251/goja"
7 | "github.com/zengming00/go-server-js/nodejs/require"
8 | )
9 |
10 | func TestConsole(t *testing.T) {
11 | vm := goja.New()
12 |
13 | new(require.Registry).Enable(vm)
14 | Enable(vm)
15 |
16 | if c := vm.Get("console"); c == nil {
17 | t.Fatal("console not found")
18 | }
19 |
20 | if _, err := vm.RunString("console.log('')"); err != nil {
21 | t.Fatal("console.log() error", err)
22 | }
23 |
24 | if _, err := vm.RunString("console.error('')"); err != nil {
25 | t.Fatal("console.error() error", err)
26 | }
27 |
28 | if _, err := vm.RunString("console.warn('')"); err != nil {
29 | t.Fatal("console.warn() error", err)
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/nodejs/eventloop/eventloop.go:
--------------------------------------------------------------------------------
1 | package eventloop
2 |
3 | import (
4 | "github.com/dop251/goja"
5 | "github.com/zengming00/go-server-js/nodejs/console"
6 | "github.com/zengming00/go-server-js/nodejs/require"
7 | "time"
8 | )
9 |
10 | type job struct {
11 | goja.Callable
12 | args []goja.Value
13 | cancelled bool
14 | }
15 |
16 | type timer struct {
17 | job
18 | timer *time.Timer
19 | }
20 |
21 | type interval struct {
22 | job
23 | ticker *time.Ticker
24 | stopChan chan int
25 | }
26 |
27 | type EventLoop struct {
28 | vm *goja.Runtime
29 | jobChan chan func()
30 | jobCount int32
31 | running bool
32 | }
33 |
34 | func NewEventLoop() *EventLoop {
35 | vm := goja.New()
36 |
37 | loop := &EventLoop{
38 | vm: vm,
39 | jobChan: make(chan func()),
40 | }
41 |
42 | new(require.Registry).Enable(vm)
43 | console.Enable(vm)
44 | vm.Set("setTimeout", loop.setTimeout)
45 | vm.Set("setInterval", loop.setInterval)
46 | vm.Set("clearTimeout", loop.clearTimeout)
47 | vm.Set("clearInterval", loop.clearInterval)
48 |
49 | return loop
50 | }
51 |
52 | func (loop *EventLoop) schedule(call goja.FunctionCall, repeating bool) goja.Value {
53 | if fn, ok := goja.AssertFunction(call.Argument(0)); ok {
54 | delay := call.Argument(1).ToInteger()
55 | var args []goja.Value
56 | if len(call.Arguments) > 2 {
57 | args = call.Arguments[2:]
58 | }
59 | if repeating {
60 | return loop.vm.ToValue(loop.addInterval(fn, time.Duration(delay)*time.Millisecond, args))
61 | } else {
62 | return loop.vm.ToValue(loop.addTimeout(fn, time.Duration(delay)*time.Millisecond, args))
63 | }
64 | }
65 | return nil
66 | }
67 |
68 | func (loop *EventLoop) setTimeout(call goja.FunctionCall) goja.Value {
69 | return loop.schedule(call, false)
70 | }
71 |
72 | func (loop *EventLoop) setInterval(call goja.FunctionCall) goja.Value {
73 | return loop.schedule(call, true)
74 | }
75 |
76 | // Run calls the specified function, starts the event loop and waits until there are no more delayed jobs to run
77 | // after which it stops the loop and returns.
78 | // The instance of goja.Runtime that is passed to the function and any Values derived from it must not be used outside
79 | // of the function.
80 | func (loop *EventLoop) Run(fn func(*goja.Runtime)) {
81 | fn(loop.vm)
82 | loop.run(false)
83 | }
84 |
85 | // Start the event loop in the background. The loop continues to run until Stop() is called.
86 | func (loop *EventLoop) Start() {
87 | go loop.run(true)
88 | }
89 |
90 | // Stop the loop that was started with Start(). After this function returns there will be no more jobs executed
91 | // by the loop. It is possible to call Start() or Run() again after this to resume the execution.
92 | func (loop *EventLoop) Stop() {
93 | ch := make(chan int)
94 |
95 | loop.jobChan <- func() {
96 | loop.running = false
97 | ch <- 1
98 | }
99 |
100 | <-ch
101 | }
102 |
103 | // RunOnLoop schedules to run the specified function in the context of the loop as soon as possible.
104 | // The order of the runs is preserved (i.e. the functions will be called in the same order as calls to RunOnLoop())
105 | // The instance of goja.Runtime that is passed to the function and any Values derived from it must not be used outside
106 | // of the function.
107 | func (loop *EventLoop) RunOnLoop(fn func(*goja.Runtime)) {
108 | loop.jobChan <- func() {
109 | fn(loop.vm)
110 | }
111 | }
112 |
113 | func (loop *EventLoop) run(inBackground bool) {
114 | loop.running = true
115 | for job := range loop.jobChan {
116 | job()
117 | if !loop.running || !inBackground && loop.jobCount <= 0 {
118 | break
119 | }
120 | }
121 | }
122 |
123 | func (loop *EventLoop) addTimeout(f goja.Callable, timeout time.Duration, args []goja.Value) *timer {
124 | t := &timer{
125 | job: job{Callable: f, args: args},
126 | }
127 |
128 | t.timer = time.AfterFunc(timeout, func() {
129 | loop.jobChan <- func() {
130 | loop.doTimeout(t)
131 | }
132 | })
133 |
134 | loop.jobCount++
135 | return t
136 | }
137 |
138 | func (loop *EventLoop) addInterval(f goja.Callable, timeout time.Duration, args []goja.Value) *interval {
139 | i := &interval{
140 | job: job{Callable: f, args: args},
141 | ticker: time.NewTicker(timeout),
142 | stopChan: make(chan int),
143 | }
144 |
145 | go i.run(loop)
146 | loop.jobCount++
147 | return i
148 | }
149 |
150 | func (loop *EventLoop) doTimeout(t *timer) {
151 | if !t.cancelled {
152 | t.Callable(nil, t.args...)
153 | t.cancelled = true
154 | loop.jobCount--
155 | }
156 | }
157 |
158 | func (loop *EventLoop) doInterval(i *interval) {
159 | if !i.cancelled {
160 | i.Callable(nil, i.args...)
161 | }
162 | }
163 |
164 | func (loop *EventLoop) clearTimeout(t *timer) {
165 | if !t.cancelled {
166 | t.timer.Stop()
167 | t.cancelled = true
168 | loop.jobCount--
169 | }
170 | }
171 |
172 | func (loop *EventLoop) clearInterval(i *interval) {
173 | if !i.cancelled {
174 | i.cancelled = true
175 | i.stopChan <- 1
176 | loop.jobCount--
177 | }
178 | }
179 |
180 | func (i *interval) run(loop *EventLoop) {
181 | for {
182 | select {
183 | case <-i.stopChan:
184 | i.ticker.Stop()
185 | break
186 | case <-i.ticker.C:
187 | loop.jobChan <- func() {
188 | loop.doInterval(i)
189 | }
190 | }
191 | }
192 | }
193 |
--------------------------------------------------------------------------------
/nodejs/eventloop/eventloop_test.go:
--------------------------------------------------------------------------------
1 | package eventloop
2 |
3 | import (
4 | "github.com/dop251/goja"
5 | "testing"
6 | "time"
7 | )
8 |
9 | func TestRun(t *testing.T) {
10 | const SCRIPT = `
11 | setTimeout(function() {
12 | console.log("ok");
13 | }, 1000);
14 | console.log("Started");
15 | `
16 |
17 | loop := NewEventLoop()
18 | prg, err := goja.Compile("main.js", SCRIPT, false)
19 | if err != nil {
20 | t.Fatal(err)
21 | }
22 | loop.Run(func(vm *goja.Runtime) {
23 | vm.RunProgram(prg)
24 | })
25 | }
26 |
27 | func TestStart(t *testing.T) {
28 | const SCRIPT = `
29 | setTimeout(function() {
30 | console.log("ok");
31 | }, 1000);
32 | console.log("Started");
33 | `
34 |
35 | prg, err := goja.Compile("main.js", SCRIPT, false)
36 | if err != nil {
37 | t.Fatal(err)
38 | }
39 |
40 | loop := NewEventLoop()
41 | loop.Start()
42 |
43 | loop.RunOnLoop(func(vm *goja.Runtime) {
44 | vm.RunProgram(prg)
45 | })
46 |
47 | time.Sleep(2 * time.Second)
48 | loop.Stop()
49 | }
50 |
51 | func TestInterval(t *testing.T) {
52 | const SCRIPT = `
53 | var count = 0;
54 | var t = setInterval(function() {
55 | console.log("tick");
56 | if (++count > 2) {
57 | clearInterval(t);
58 | }
59 | }, 1000);
60 | console.log("Started");
61 | `
62 |
63 | loop := NewEventLoop()
64 | prg, err := goja.Compile("main.js", SCRIPT, false)
65 | if err != nil {
66 | t.Fatal(err)
67 | }
68 | loop.Run(func(vm *goja.Runtime) {
69 | vm.RunProgram(prg)
70 | })
71 | }
72 |
--------------------------------------------------------------------------------
/nodejs/require/module.go:
--------------------------------------------------------------------------------
1 | package require
2 |
3 | import (
4 | js "github.com/dop251/goja"
5 |
6 | "errors"
7 | "fmt"
8 | "io/ioutil"
9 | "path/filepath"
10 | "sync"
11 | )
12 |
13 | type ModuleLoader func(*js.Runtime, *js.Object)
14 | type SourceLoader func(path string) ([]byte, error)
15 |
16 | var (
17 | InvalidModuleError = errors.New("Invalid module")
18 | IllegalModuleNameError = errors.New("Illegal module name")
19 | )
20 |
21 | var native map[string]ModuleLoader
22 |
23 | // Registry contains a cache of compiled modules which can be used by multiple Runtimes
24 | type Registry struct {
25 | sync.Mutex
26 | compiled map[string]*js.Program
27 |
28 | srcLoader SourceLoader
29 | }
30 |
31 | type RequireModule struct {
32 | r *Registry
33 | runtime *js.Runtime
34 | modules map[string]*js.Object
35 | }
36 |
37 | func NewRegistryWithLoader(srcLoader SourceLoader) *Registry {
38 | return &Registry{
39 | srcLoader: srcLoader,
40 | }
41 | }
42 |
43 | // Enable adds the require() function to the specified runtime.
44 | func (r *Registry) Enable(runtime *js.Runtime) *RequireModule {
45 | rrt := &RequireModule{
46 | r: r,
47 | runtime: runtime,
48 | modules: make(map[string]*js.Object),
49 | }
50 |
51 | runtime.Set("require", rrt.require)
52 | runtime.Set("require_list", rrt.list)
53 | runtime.Set("require_set", rrt.set)
54 | runtime.Set("require_get", rrt.get)
55 | return rrt
56 | }
57 |
58 | func (r *Registry) getCompiledSource(p string) (prg *js.Program, err error) {
59 | r.Lock()
60 | defer r.Unlock()
61 |
62 | prg = r.compiled[p]
63 | if prg == nil {
64 | srcLoader := r.srcLoader
65 | if srcLoader == nil {
66 | srcLoader = ioutil.ReadFile
67 | }
68 | if s, err1 := srcLoader(p); err1 == nil {
69 | source := "(function(module, exports) {" + string(s) + "\n})"
70 | prg, err = js.Compile(p, source, false)
71 | if err == nil {
72 | if r.compiled == nil {
73 | r.compiled = make(map[string]*js.Program)
74 | }
75 | r.compiled[p] = prg
76 | }
77 | } else {
78 | err = err1
79 | }
80 | }
81 | return
82 | }
83 |
84 | func (r *RequireModule) loadModule(path string, jsModule *js.Object) error {
85 |
86 | if ldr, exists := native[path]; exists {
87 | ldr(r.runtime, jsModule)
88 | return nil
89 | }
90 |
91 | prg, err := r.r.getCompiledSource(path)
92 |
93 | if err != nil {
94 | return err
95 | }
96 |
97 | f, err := r.runtime.RunProgram(prg)
98 | if err != nil {
99 | return err
100 | }
101 |
102 | if call, ok := js.AssertFunction(f); ok {
103 | jsExports := jsModule.Get("exports")
104 |
105 | // Run the module source, with "jsModule" as the "module" variable, "jsExports" as "this"(Nodejs capable).
106 | _, err = call(jsExports, jsModule, jsExports)
107 | if err != nil {
108 | return err
109 | }
110 | } else {
111 | return InvalidModuleError
112 | }
113 |
114 | return nil
115 | }
116 |
117 | func (r *RequireModule) list(call js.FunctionCall) js.Value {
118 | return r.runtime.ToValue(r.modules)
119 | }
120 |
121 | func (r *RequireModule) set(call js.FunctionCall) js.Value {
122 | key := call.Argument(0).String()
123 | value := call.Argument(1).ToObject(r.runtime)
124 | r.modules[key] = value
125 | return nil
126 | }
127 |
128 | func (r *RequireModule) get(call js.FunctionCall) js.Value {
129 | key := call.Argument(0).String()
130 | if v, ok := r.modules[key]; ok {
131 | return r.runtime.ToValue(v)
132 | }
133 | return nil
134 | }
135 |
136 | func (r *RequireModule) require(call js.FunctionCall) js.Value {
137 | ret, err := r.Require(call.Argument(0).String())
138 | if err != nil {
139 | panic(r.runtime.NewGoError(err))
140 | }
141 | return ret
142 | }
143 |
144 | func filepathClean(p string) string {
145 | return filepath.Clean(p)
146 | }
147 |
148 | // Require can be used to import modules from Go source (similar to JS require() function).
149 | func (r *RequireModule) Require(p string) (ret js.Value, err error) {
150 | p = filepathClean(p)
151 | if p == "" {
152 | err = IllegalModuleNameError
153 | return
154 | }
155 | module := r.modules[p]
156 | if module == nil {
157 | module = r.runtime.NewObject()
158 | module.Set("exports", r.runtime.NewObject())
159 | r.modules[p] = module
160 | err = r.loadModule(p, module)
161 | if err != nil {
162 | delete(r.modules, p)
163 | err = fmt.Errorf("Could not load module '%s': %v", p, err)
164 | return
165 | }
166 | }
167 | ret = module.Get("exports")
168 | return
169 | }
170 |
171 | func Require(runtime *js.Runtime, name string) js.Value {
172 | if r, ok := js.AssertFunction(runtime.Get("require")); ok {
173 | mod, err := r(js.Undefined(), runtime.ToValue(name))
174 | if err != nil {
175 | panic(err)
176 | }
177 | return mod
178 | }
179 | panic(runtime.NewTypeError("Please enable require for this runtime using new(require.Require).Enable(runtime)"))
180 | }
181 |
182 | func RegisterNativeModule(name string, loader ModuleLoader) {
183 | if native == nil {
184 | native = make(map[string]ModuleLoader)
185 | }
186 | name = filepathClean(name)
187 | native[name] = loader
188 | }
189 |
--------------------------------------------------------------------------------
/nodejs/require/module_test.go:
--------------------------------------------------------------------------------
1 | package require
2 |
3 | import (
4 | "errors"
5 | "testing"
6 |
7 | js "github.com/dop251/goja"
8 | )
9 |
10 | func TestRequireNativeModule(t *testing.T) {
11 | const SCRIPT = `
12 | var m = require("test/m");
13 | m.test();
14 | `
15 |
16 | vm := js.New()
17 |
18 | registry := new(Registry)
19 | registry.Enable(vm)
20 |
21 | RegisterNativeModule("test/m", func(runtime *js.Runtime, module *js.Object) {
22 | o := module.Get("exports").(*js.Object)
23 | o.Set("test", func(call js.FunctionCall) js.Value {
24 | return runtime.ToValue("passed")
25 | })
26 | })
27 |
28 | v, err := vm.RunString(SCRIPT)
29 | if err != nil {
30 | t.Fatal(err)
31 | }
32 |
33 | if !v.StrictEquals(vm.ToValue("passed")) {
34 | t.Fatalf("Unexpected result: %v", v)
35 | }
36 | }
37 |
38 | func TestRequire(t *testing.T) {
39 | const SCRIPT = `
40 | var m = require("./testdata/m.js");
41 | m.test();
42 | `
43 |
44 | vm := js.New()
45 |
46 | registry := new(Registry)
47 | registry.Enable(vm)
48 |
49 | v, err := vm.RunString(SCRIPT)
50 | if err != nil {
51 | t.Fatal(err)
52 | }
53 |
54 | if !v.StrictEquals(vm.ToValue("passed")) {
55 | t.Fatalf("Unexpected result: %v", v)
56 | }
57 | }
58 |
59 | func TestSourceLoader(t *testing.T) {
60 | const SCRIPT = `
61 | var m = require("m.js");
62 | m.test();
63 | `
64 |
65 | const MODULE = `
66 | function test() {
67 | return "passed1";
68 | }
69 |
70 | exports.test = test;
71 | `
72 |
73 | vm := js.New()
74 |
75 | registry := NewRegistryWithLoader(func(name string) ([]byte, error) {
76 | if name == "m.js" {
77 | return []byte(MODULE), nil
78 | }
79 | return nil, errors.New("Module does not exist")
80 | })
81 | registry.Enable(vm)
82 |
83 | v, err := vm.RunString(SCRIPT)
84 | if err != nil {
85 | t.Fatal(err)
86 | }
87 |
88 | if !v.StrictEquals(vm.ToValue("passed1")) {
89 | t.Fatalf("Unexpected result: %v", v)
90 | }
91 | }
92 |
93 | func TestStrictModule(t *testing.T) {
94 | const SCRIPT = `
95 | var m = require("m.js");
96 | m.test();
97 | `
98 |
99 | const MODULE = `
100 | "use strict";
101 |
102 | function test() {
103 | var a = "passed1";
104 | eval("var a = 'not passed'");
105 | return a;
106 | }
107 |
108 | exports.test = test;
109 | `
110 |
111 | vm := js.New()
112 |
113 | registry := NewRegistryWithLoader(func(name string) ([]byte, error) {
114 | if name == "m.js" {
115 | return []byte(MODULE), nil
116 | }
117 | return nil, errors.New("Module does not exist")
118 | })
119 | registry.Enable(vm)
120 |
121 | v, err := vm.RunString(SCRIPT)
122 | if err != nil {
123 | t.Fatal(err)
124 | }
125 |
126 | if !v.StrictEquals(vm.ToValue("passed1")) {
127 | t.Fatalf("Unexpected result: %v", v)
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/nodejs/require/testdata/m.js:
--------------------------------------------------------------------------------
1 | function test() {
2 | return "passed";
3 | }
4 |
5 | module.exports = {
6 | test: test
7 | }
8 |
--------------------------------------------------------------------------------
/nodejs/util/module.go:
--------------------------------------------------------------------------------
1 | package util
2 |
3 | import (
4 | "bytes"
5 | "github.com/dop251/goja"
6 | "github.com/zengming00/go-server-js/nodejs/require"
7 | )
8 |
9 | type Util struct {
10 | runtime *goja.Runtime
11 | }
12 |
13 | func (u *Util) format(f rune, val goja.Value, w *bytes.Buffer) bool {
14 | switch f {
15 | case 's':
16 | w.WriteString(val.String())
17 | case 'd':
18 | w.WriteString(val.ToNumber().String())
19 | case 'j':
20 | if json, ok := u.runtime.Get("JSON").(*goja.Object); ok {
21 | if stringify, ok := goja.AssertFunction(json.Get("stringify")); ok {
22 | res, err := stringify(json, val)
23 | if err != nil {
24 | panic(err)
25 | }
26 | w.WriteString(res.String())
27 | }
28 | }
29 | case '%':
30 | w.WriteByte('%')
31 | return false
32 | default:
33 | w.WriteByte('%')
34 | w.WriteRune(f)
35 | return false
36 | }
37 | return true
38 | }
39 |
40 | func (u *Util) Format(b *bytes.Buffer, f string, args ...goja.Value) {
41 | pct := false
42 | argNum := 0
43 | for _, chr := range f {
44 | if pct {
45 | if argNum < len(args) {
46 | if u.format(chr, args[argNum], b) {
47 | argNum++
48 | }
49 | } else {
50 | b.WriteByte('%')
51 | b.WriteRune(chr)
52 | }
53 | pct = false
54 | } else {
55 | if chr == '%' {
56 | pct = true
57 | } else {
58 | b.WriteRune(chr)
59 | }
60 | }
61 | }
62 |
63 | for _, arg := range args[argNum:] {
64 | b.WriteByte(' ')
65 | b.WriteString(arg.String())
66 | }
67 | }
68 |
69 | func (u *Util) js_format(call goja.FunctionCall) goja.Value {
70 | var b bytes.Buffer
71 | var fmt string
72 |
73 | if arg := call.Argument(0); !goja.IsUndefined(arg) {
74 | fmt = arg.String()
75 | }
76 |
77 | var args []goja.Value
78 | if len(call.Arguments) > 0 {
79 | args = call.Arguments[1:]
80 | }
81 | u.Format(&b, fmt, args...)
82 |
83 | return u.runtime.ToValue(b.String())
84 | }
85 |
86 | func Require(runtime *goja.Runtime, module *goja.Object) {
87 | u := &Util{
88 | runtime: runtime,
89 | }
90 | obj := module.Get("exports").(*goja.Object)
91 | obj.Set("format", u.js_format)
92 | }
93 |
94 | func New(runtime *goja.Runtime) *Util {
95 | return &Util{
96 | runtime: runtime,
97 | }
98 | }
99 |
100 | func init() {
101 | require.RegisterNativeModule("util", Require)
102 | }
103 |
--------------------------------------------------------------------------------
/nodejs/util/module_test.go:
--------------------------------------------------------------------------------
1 | package util
2 |
3 | import (
4 | "bytes"
5 | "testing"
6 |
7 | "github.com/dop251/goja"
8 | "github.com/zengming00/go-server-js/nodejs/require"
9 | )
10 |
11 | func TestUtil_Format(t *testing.T) {
12 | vm := goja.New()
13 | util := New(vm)
14 |
15 | var b bytes.Buffer
16 | util.Format(&b, "Test: %% %д %s %d, %j", vm.ToValue("string"), vm.ToValue(42), vm.NewObject())
17 |
18 | if res := b.String(); res != "Test: % %д string 42, {}" {
19 | t.Fatalf("Unexpected result: '%s'", res)
20 | }
21 | }
22 |
23 | func TestUtil_Format_NoArgs(t *testing.T) {
24 | vm := goja.New()
25 | util := New(vm)
26 |
27 | var b bytes.Buffer
28 | util.Format(&b, "Test: %s %d, %j")
29 |
30 | if res := b.String(); res != "Test: %s %d, %j" {
31 | t.Fatalf("Unexpected result: '%s'", res)
32 | }
33 | }
34 |
35 | func TestUtil_Format_LessArgs(t *testing.T) {
36 | vm := goja.New()
37 | util := New(vm)
38 |
39 | var b bytes.Buffer
40 | util.Format(&b, "Test: %s %d, %j", vm.ToValue("string"), vm.ToValue(42))
41 |
42 | if res := b.String(); res != "Test: string 42, %j" {
43 | t.Fatalf("Unexpected result: '%s'", res)
44 | }
45 | }
46 |
47 | func TestUtil_Format_MoreArgs(t *testing.T) {
48 | vm := goja.New()
49 | util := New(vm)
50 |
51 | var b bytes.Buffer
52 | util.Format(&b, "Test: %s %d, %j", vm.ToValue("string"), vm.ToValue(42), vm.NewObject(), vm.ToValue(42.42))
53 |
54 | if res := b.String(); res != "Test: string 42, {} 42.42" {
55 | t.Fatalf("Unexpected result: '%s'", res)
56 | }
57 | }
58 |
59 | func TestJSNoArgs(t *testing.T) {
60 | vm := goja.New()
61 | new(require.Registry).Enable(vm)
62 |
63 | if util, ok := require.Require(vm, "util").(*goja.Object); ok {
64 | if format, ok := goja.AssertFunction(util.Get("format")); ok {
65 | res, err := format(util)
66 | if err != nil {
67 | t.Fatal(err)
68 | }
69 | if v := res.Export(); v != "" {
70 | t.Fatalf("Unexpected result: %v", v)
71 | }
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/public/css/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: verdana, helvetica, arial, sans-serif;
3 | padding: 20px;
4 | font-size: 12px;
5 | margin: 0;
6 | }
7 |
8 | h2 {
9 | font-size: 18px;
10 | font-weight: bold;
11 | margin: 0;
12 | margin-bottom: 15px;
13 | }
14 |
15 | .demo-info {
16 | padding: 0 0 12px 0;
17 | }
18 |
19 | .demo-tip {
20 | display: none;
21 | }
22 |
23 | #fm {
24 | margin: 0;
25 | padding: 10px 30px;
26 | }
27 |
28 | .ftitle {
29 | font-size: 14px;
30 | font-weight: bold;
31 | color: #666;
32 | padding: 5px 0;
33 | margin-bottom: 10px;
34 | border-bottom: 1px solid #ccc;
35 | }
36 |
37 | .fitem {
38 | margin-bottom: 5px;
39 | }
40 |
41 | .fitem label {
42 | display: inline-block;
43 | width: 80px;
44 | }
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | jQuery EasyUI CRUD Demo
9 |
10 |
11 |
12 |
13 |
14 |
95 |
96 |
97 |
98 | go-server-js Basic CRUD Application
99 |
109 |
110 |
112 |
113 |
114 | First Name |
115 | Last Name |
116 | Phone |
117 | Email |
118 |
119 |
120 |
121 |
126 |
127 |
128 |
User Information
129 |
147 |
148 |
152 |
153 |
154 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/accordion.css:
--------------------------------------------------------------------------------
1 | .accordion {
2 | overflow: hidden;
3 | border-width: 1px;
4 | border-style: solid;
5 | }
6 | .accordion .accordion-header {
7 | border-width: 0 0 1px;
8 | cursor: pointer;
9 | }
10 | .accordion .accordion-body {
11 | border-width: 0 0 1px;
12 | }
13 | .accordion-noborder {
14 | border-width: 0;
15 | }
16 | .accordion-noborder .accordion-header {
17 | border-width: 0 0 1px;
18 | }
19 | .accordion-noborder .accordion-body {
20 | border-width: 0 0 1px;
21 | }
22 | .accordion-collapse {
23 | background: url('images/accordion_arrows.png') no-repeat 0 0;
24 | }
25 | .accordion-expand {
26 | background: url('images/accordion_arrows.png') no-repeat -16px 0;
27 | }
28 | .accordion {
29 | background: #ffffff;
30 | border-color: #95B8E7;
31 | }
32 | .accordion .accordion-header {
33 | background: #E0ECFF;
34 | filter: none;
35 | }
36 | .accordion .accordion-header-selected {
37 | background: #ffe48d;
38 | }
39 | .accordion .accordion-header-selected .panel-title {
40 | color: #000000;
41 | }
42 | .accordion .panel-last > .accordion-header {
43 | border-bottom-color: #E0ECFF;
44 | }
45 | .accordion .panel-last > .accordion-body {
46 | border-bottom-color: #ffffff;
47 | }
48 | .accordion .panel-last > .accordion-header-selected,
49 | .accordion .panel-last > .accordion-header-border {
50 | border-bottom-color: #95B8E7;
51 | }
52 | .accordion> .panel-hleft {
53 | float: left;
54 | }
55 | .accordion> .panel-hleft>.panel-header {
56 | border-width: 0 1px 0 0;
57 | }
58 | .accordion> .panel-hleft> .panel-body {
59 | border-width: 0 1px 0 0;
60 | }
61 | .accordion> .panel-hleft.panel-last > .accordion-header {
62 | border-right-color: #E0ECFF;
63 | }
64 | .accordion> .panel-hleft.panel-last > .accordion-body {
65 | border-right-color: #ffffff;
66 | }
67 | .accordion> .panel-hleft.panel-last > .accordion-header-selected,
68 | .accordion> .panel-hleft.panel-last > .accordion-header-border {
69 | border-right-color: #95B8E7;
70 | }
71 | .accordion> .panel-hright {
72 | float: right;
73 | }
74 | .accordion> .panel-hright>.panel-header {
75 | border-width: 0 0 0 1px;
76 | }
77 | .accordion> .panel-hright> .panel-body {
78 | border-width: 0 0 0 1px;
79 | }
80 | .accordion> .panel-hright.panel-last > .accordion-header {
81 | border-left-color: #E0ECFF;
82 | }
83 | .accordion> .panel-hright.panel-last > .accordion-body {
84 | border-left-color: #ffffff;
85 | }
86 | .accordion> .panel-hright.panel-last > .accordion-header-selected,
87 | .accordion> .panel-hright.panel-last > .accordion-header-border {
88 | border-left-color: #95B8E7;
89 | }
90 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/calendar.css:
--------------------------------------------------------------------------------
1 | .calendar {
2 | border-width: 1px;
3 | border-style: solid;
4 | padding: 1px;
5 | overflow: hidden;
6 | }
7 | .calendar table {
8 | table-layout: fixed;
9 | border-collapse: separate;
10 | font-size: 12px;
11 | width: 100%;
12 | height: 100%;
13 | }
14 | .calendar table td,
15 | .calendar table th {
16 | font-size: 12px;
17 | }
18 | .calendar-noborder {
19 | border: 0;
20 | }
21 | .calendar-header {
22 | position: relative;
23 | height: 22px;
24 | }
25 | .calendar-title {
26 | text-align: center;
27 | height: 22px;
28 | }
29 | .calendar-title span {
30 | position: relative;
31 | display: inline-block;
32 | top: 2px;
33 | padding: 0 3px;
34 | height: 18px;
35 | line-height: 18px;
36 | font-size: 12px;
37 | cursor: pointer;
38 | -moz-border-radius: 5px 5px 5px 5px;
39 | -webkit-border-radius: 5px 5px 5px 5px;
40 | border-radius: 5px 5px 5px 5px;
41 | }
42 | .calendar-prevmonth,
43 | .calendar-nextmonth,
44 | .calendar-prevyear,
45 | .calendar-nextyear {
46 | position: absolute;
47 | top: 50%;
48 | margin-top: -7px;
49 | width: 14px;
50 | height: 14px;
51 | cursor: pointer;
52 | font-size: 1px;
53 | -moz-border-radius: 5px 5px 5px 5px;
54 | -webkit-border-radius: 5px 5px 5px 5px;
55 | border-radius: 5px 5px 5px 5px;
56 | }
57 | .calendar-prevmonth {
58 | left: 20px;
59 | background: url('images/calendar_arrows.png') no-repeat -18px -2px;
60 | }
61 | .calendar-nextmonth {
62 | right: 20px;
63 | background: url('images/calendar_arrows.png') no-repeat -34px -2px;
64 | }
65 | .calendar-prevyear {
66 | left: 3px;
67 | background: url('images/calendar_arrows.png') no-repeat -1px -2px;
68 | }
69 | .calendar-nextyear {
70 | right: 3px;
71 | background: url('images/calendar_arrows.png') no-repeat -49px -2px;
72 | }
73 | .calendar-body {
74 | position: relative;
75 | }
76 | .calendar-body th,
77 | .calendar-body td {
78 | text-align: center;
79 | }
80 | .calendar-day {
81 | border: 0;
82 | padding: 1px;
83 | cursor: pointer;
84 | -moz-border-radius: 5px 5px 5px 5px;
85 | -webkit-border-radius: 5px 5px 5px 5px;
86 | border-radius: 5px 5px 5px 5px;
87 | }
88 | .calendar-other-month {
89 | opacity: 0.3;
90 | filter: alpha(opacity=30);
91 | }
92 | .calendar-disabled {
93 | opacity: 0.6;
94 | filter: alpha(opacity=60);
95 | cursor: default;
96 | }
97 | .calendar-menu {
98 | position: absolute;
99 | top: 0;
100 | left: 0;
101 | width: 180px;
102 | height: 150px;
103 | padding: 5px;
104 | font-size: 12px;
105 | display: none;
106 | overflow: hidden;
107 | }
108 | .calendar-menu-year-inner {
109 | text-align: center;
110 | padding-bottom: 5px;
111 | }
112 | .calendar-menu-year {
113 | width: 50px;
114 | text-align: center;
115 | border-width: 1px;
116 | border-style: solid;
117 | outline-style: none;
118 | resize: none;
119 | margin: 0;
120 | padding: 2px;
121 | font-weight: bold;
122 | font-size: 12px;
123 | -moz-border-radius: 5px 5px 5px 5px;
124 | -webkit-border-radius: 5px 5px 5px 5px;
125 | border-radius: 5px 5px 5px 5px;
126 | }
127 | .calendar-menu-prev,
128 | .calendar-menu-next {
129 | display: inline-block;
130 | width: 21px;
131 | height: 21px;
132 | vertical-align: top;
133 | cursor: pointer;
134 | -moz-border-radius: 5px 5px 5px 5px;
135 | -webkit-border-radius: 5px 5px 5px 5px;
136 | border-radius: 5px 5px 5px 5px;
137 | }
138 | .calendar-menu-prev {
139 | margin-right: 10px;
140 | background: url('images/calendar_arrows.png') no-repeat 2px 2px;
141 | }
142 | .calendar-menu-next {
143 | margin-left: 10px;
144 | background: url('images/calendar_arrows.png') no-repeat -45px 2px;
145 | }
146 | .calendar-menu-month {
147 | text-align: center;
148 | cursor: pointer;
149 | font-weight: bold;
150 | -moz-border-radius: 5px 5px 5px 5px;
151 | -webkit-border-radius: 5px 5px 5px 5px;
152 | border-radius: 5px 5px 5px 5px;
153 | }
154 | .calendar-body th,
155 | .calendar-menu-month {
156 | color: #4d4d4d;
157 | }
158 | .calendar-day {
159 | color: #000000;
160 | }
161 | .calendar-sunday {
162 | color: #CC2222;
163 | }
164 | .calendar-saturday {
165 | color: #00ee00;
166 | }
167 | .calendar-today {
168 | color: #0000ff;
169 | }
170 | .calendar-menu-year {
171 | border-color: #95B8E7;
172 | }
173 | .calendar {
174 | border-color: #95B8E7;
175 | }
176 | .calendar-header {
177 | background: #E0ECFF;
178 | }
179 | .calendar-body,
180 | .calendar-menu {
181 | background: #ffffff;
182 | }
183 | .calendar-body th {
184 | background: #F4F4F4;
185 | padding: 2px 0;
186 | }
187 | .calendar-hover,
188 | .calendar-nav-hover,
189 | .calendar-menu-hover {
190 | background-color: #eaf2ff;
191 | color: #000000;
192 | }
193 | .calendar-hover {
194 | border: 1px solid #b7d2ff;
195 | padding: 0;
196 | }
197 | .calendar-selected {
198 | background-color: #ffe48d;
199 | color: #000000;
200 | border: 1px solid #ffab3f;
201 | padding: 0;
202 | }
203 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/combo.css:
--------------------------------------------------------------------------------
1 | .combo-arrow {
2 | width: 18px;
3 | height: 20px;
4 | overflow: hidden;
5 | display: inline-block;
6 | vertical-align: top;
7 | cursor: pointer;
8 | opacity: 0.6;
9 | filter: alpha(opacity=60);
10 | }
11 | .combo-arrow-hover {
12 | opacity: 1.0;
13 | filter: alpha(opacity=100);
14 | }
15 | .combo-panel {
16 | overflow: auto;
17 | }
18 | .combo-arrow {
19 | background: url('images/combo_arrow.png') no-repeat center center;
20 | }
21 | .combo-panel {
22 | background-color: #ffffff;
23 | }
24 | .combo-arrow {
25 | background-color: #E0ECFF;
26 | }
27 | .combo-arrow-hover {
28 | background-color: #eaf2ff;
29 | }
30 | .combo-arrow:hover {
31 | background-color: #eaf2ff;
32 | }
33 | .combo .textbox-icon-disabled:hover {
34 | cursor: default;
35 | }
36 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/combobox.css:
--------------------------------------------------------------------------------
1 | .combobox-item,
2 | .combobox-group,
3 | .combobox-stick {
4 | font-size: 12px;
5 | padding: 3px;
6 | }
7 | .combobox-item-disabled {
8 | opacity: 0.5;
9 | filter: alpha(opacity=50);
10 | }
11 | .combobox-gitem {
12 | padding-left: 10px;
13 | }
14 | .combobox-group,
15 | .combobox-stick {
16 | font-weight: bold;
17 | }
18 | .combobox-stick {
19 | position: absolute;
20 | top: 1px;
21 | left: 1px;
22 | right: 1px;
23 | background: inherit;
24 | }
25 | .combobox-item-hover {
26 | background-color: #eaf2ff;
27 | color: #000000;
28 | }
29 | .combobox-item-selected {
30 | background-color: #ffe48d;
31 | color: #000000;
32 | }
33 | .combobox-icon {
34 | display: inline-block;
35 | width: 16px;
36 | height: 16px;
37 | vertical-align: middle;
38 | margin-right: 2px;
39 | }
40 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/datalist.css:
--------------------------------------------------------------------------------
1 | .datalist .datagrid-header {
2 | border-width: 0;
3 | }
4 | .datalist .datagrid-group,
5 | .m-list .m-list-group {
6 | height: 25px;
7 | line-height: 25px;
8 | font-weight: bold;
9 | overflow: hidden;
10 | background-color: #efefef;
11 | border-style: solid;
12 | border-width: 0 0 1px 0;
13 | border-color: #ccc;
14 | }
15 | .datalist .datagrid-group-expander {
16 | display: none;
17 | }
18 | .datalist .datagrid-group-title {
19 | padding: 0 4px;
20 | }
21 | .datalist .datagrid-btable {
22 | width: 100%;
23 | table-layout: fixed;
24 | }
25 | .datalist .datagrid-row td {
26 | border-style: solid;
27 | border-left-color: transparent;
28 | border-right-color: transparent;
29 | border-bottom-width: 0;
30 | }
31 | .datalist-lines .datagrid-row td {
32 | border-bottom-width: 1px;
33 | }
34 | .datalist .datagrid-cell,
35 | .m-list li {
36 | width: auto;
37 | height: auto;
38 | padding: 2px 4px;
39 | line-height: 18px;
40 | position: relative;
41 | white-space: nowrap;
42 | text-overflow: ellipsis;
43 | overflow: hidden;
44 | }
45 | .datalist-link,
46 | .m-list li>a {
47 | display: block;
48 | position: relative;
49 | cursor: pointer;
50 | color: #000000;
51 | text-decoration: none;
52 | overflow: hidden;
53 | margin: -2px -4px;
54 | padding: 2px 4px;
55 | padding-right: 16px;
56 | line-height: 18px;
57 | white-space: nowrap;
58 | text-overflow: ellipsis;
59 | overflow: hidden;
60 | }
61 | .datalist-link::after,
62 | .m-list li>a::after {
63 | position: absolute;
64 | display: block;
65 | width: 8px;
66 | height: 8px;
67 | content: '';
68 | right: 6px;
69 | top: 50%;
70 | margin-top: -4px;
71 | border-style: solid;
72 | border-width: 1px 1px 0 0;
73 | -ms-transform: rotate(45deg);
74 | -moz-transform: rotate(45deg);
75 | -webkit-transform: rotate(45deg);
76 | -o-transform: rotate(45deg);
77 | transform: rotate(45deg);
78 | }
79 | .m-list {
80 | margin: 0;
81 | padding: 0;
82 | list-style: none;
83 | }
84 | .m-list li {
85 | border-style: solid;
86 | border-width: 0 0 1px 0;
87 | border-color: #ccc;
88 | }
89 | .m-list li>a:hover {
90 | background: #eaf2ff;
91 | color: #000000;
92 | }
93 | .m-list .m-list-group {
94 | padding: 0 4px;
95 | }
96 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/datebox.css:
--------------------------------------------------------------------------------
1 | .datebox-calendar-inner {
2 | height: 180px;
3 | }
4 | .datebox-button {
5 | padding: 0 5px;
6 | text-align: center;
7 | }
8 | .datebox-button a {
9 | line-height: 22px;
10 | font-size: 12px;
11 | font-weight: bold;
12 | text-decoration: none;
13 | opacity: 0.6;
14 | filter: alpha(opacity=60);
15 | }
16 | .datebox-button a:hover {
17 | opacity: 1.0;
18 | filter: alpha(opacity=100);
19 | }
20 | .datebox-current,
21 | .datebox-close {
22 | float: left;
23 | }
24 | .datebox-close {
25 | float: right;
26 | }
27 | .datebox .combo-arrow {
28 | background-image: url('images/datebox_arrow.png');
29 | background-position: center center;
30 | }
31 | .datebox-button {
32 | background-color: #F4F4F4;
33 | }
34 | .datebox-button a {
35 | color: #444;
36 | }
37 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/dialog.css:
--------------------------------------------------------------------------------
1 | .dialog-content {
2 | overflow: auto;
3 | }
4 | .dialog-toolbar {
5 | position: relative;
6 | padding: 2px 5px;
7 | }
8 | .dialog-tool-separator {
9 | float: left;
10 | height: 24px;
11 | border-left: 1px solid #ccc;
12 | border-right: 1px solid #fff;
13 | margin: 2px 1px;
14 | }
15 | .dialog-button {
16 | position: relative;
17 | top: -1px;
18 | padding: 5px;
19 | text-align: right;
20 | }
21 | .dialog-button .l-btn {
22 | margin-left: 5px;
23 | }
24 | .dialog-toolbar,
25 | .dialog-button {
26 | background: #F4F4F4;
27 | border-width: 1px;
28 | border-style: solid;
29 | }
30 | .dialog-toolbar {
31 | border-color: #95B8E7 #95B8E7 #dddddd #95B8E7;
32 | }
33 | .dialog-button {
34 | border-color: #dddddd #95B8E7 #95B8E7 #95B8E7;
35 | }
36 | .window-thinborder .dialog-toolbar {
37 | border-left: transparent;
38 | border-right: transparent;
39 | border-top-color: #F4F4F4;
40 | }
41 | .window-thinborder .dialog-button {
42 | top: 0px;
43 | padding: 5px 8px 8px 8px;
44 | border-left: transparent;
45 | border-right: transparent;
46 | border-bottom: transparent;
47 | }
48 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/filebox.css:
--------------------------------------------------------------------------------
1 | .filebox .textbox-value {
2 | vertical-align: top;
3 | position: absolute;
4 | top: 0;
5 | left: -5000px;
6 | }
7 | .filebox-label {
8 | display: inline-block;
9 | position: absolute;
10 | width: 100%;
11 | height: 100%;
12 | cursor: pointer;
13 | left: 0;
14 | top: 0;
15 | z-index: 10;
16 | background: url('images/blank.gif') no-repeat;
17 | }
18 | .l-btn-disabled .filebox-label {
19 | cursor: default;
20 | }
21 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/images/accordion_arrows.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/default/images/accordion_arrows.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/images/blank.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/default/images/blank.gif
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/images/calendar_arrows.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/default/images/calendar_arrows.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/images/combo_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/default/images/combo_arrow.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/images/datagrid_icons.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/default/images/datagrid_icons.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/images/datebox_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/default/images/datebox_arrow.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/images/layout_arrows.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/default/images/layout_arrows.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/images/linkbutton_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/default/images/linkbutton_bg.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/images/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/default/images/loading.gif
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/images/menu_arrows.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/default/images/menu_arrows.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/images/messager_icons.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/default/images/messager_icons.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/images/pagination_icons.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/default/images/pagination_icons.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/images/panel_tools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/default/images/panel_tools.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/images/passwordbox_close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/default/images/passwordbox_close.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/images/passwordbox_open.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/default/images/passwordbox_open.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/images/searchbox_button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/default/images/searchbox_button.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/images/slider_handle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/default/images/slider_handle.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/images/spinner_arrows.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/default/images/spinner_arrows.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/images/tabs_icons.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/default/images/tabs_icons.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/images/tagbox_icons.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/default/images/tagbox_icons.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/images/tree_icons.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/default/images/tree_icons.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/images/validatebox_warning.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/default/images/validatebox_warning.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/layout.css:
--------------------------------------------------------------------------------
1 | .layout {
2 | position: relative;
3 | overflow: hidden;
4 | margin: 0;
5 | padding: 0;
6 | z-index: 0;
7 | }
8 | .layout-panel {
9 | position: absolute;
10 | overflow: hidden;
11 | }
12 | .layout-body {
13 | min-width: 1px;
14 | min-height: 1px;
15 | }
16 | .layout-panel-east,
17 | .layout-panel-west {
18 | z-index: 2;
19 | }
20 | .layout-panel-north,
21 | .layout-panel-south {
22 | z-index: 3;
23 | }
24 | .layout-expand {
25 | position: absolute;
26 | padding: 0px;
27 | font-size: 1px;
28 | cursor: pointer;
29 | z-index: 1;
30 | }
31 | .layout-expand .panel-header,
32 | .layout-expand .panel-body {
33 | background: transparent;
34 | filter: none;
35 | overflow: hidden;
36 | }
37 | .layout-expand .panel-header {
38 | border-bottom-width: 0px;
39 | }
40 | .layout-expand .panel-body {
41 | position: relative;
42 | }
43 | .layout-expand .panel-body .panel-icon {
44 | margin-top: 0;
45 | top: 0;
46 | left: 50%;
47 | margin-left: -8px;
48 | }
49 | .layout-expand-west .panel-header .panel-icon,
50 | .layout-expand-east .panel-header .panel-icon {
51 | display: none;
52 | }
53 | .layout-expand-title {
54 | position: absolute;
55 | top: 0;
56 | left: 21px;
57 | white-space: nowrap;
58 | word-wrap: normal;
59 | -webkit-transform: rotate(90deg);
60 | -webkit-transform-origin: 0 0;
61 | -moz-transform: rotate(90deg);
62 | -moz-transform-origin: 0 0;
63 | -o-transform: rotate(90deg);
64 | -o-transform-origin: 0 0;
65 | transform: rotate(90deg);
66 | transform-origin: 0 0;
67 | }
68 | .layout-expand-title-up {
69 | position: absolute;
70 | top: 0;
71 | left: 0;
72 | text-align: right;
73 | padding-left: 5px;
74 | white-space: nowrap;
75 | word-wrap: normal;
76 | -webkit-transform: rotate(-90deg);
77 | -webkit-transform-origin: 0 0;
78 | -moz-transform: rotate(-90deg);
79 | -moz-transform-origin: 0 0;
80 | -o-transform: rotate(-90deg);
81 | -o-transform-origin: 0 0;
82 | transform: rotate(-90deg);
83 | transform-origin: 0 0;
84 | }
85 | .layout-expand-with-icon {
86 | top: 18px;
87 | }
88 | .layout-expand .panel-body-noheader .layout-expand-title,
89 | .layout-expand .panel-body-noheader .panel-icon {
90 | top: 5px;
91 | }
92 | .layout-expand .panel-body-noheader .layout-expand-with-icon {
93 | top: 23px;
94 | }
95 | .layout-split-proxy-h,
96 | .layout-split-proxy-v {
97 | position: absolute;
98 | font-size: 1px;
99 | display: none;
100 | z-index: 5;
101 | }
102 | .layout-split-proxy-h {
103 | width: 5px;
104 | cursor: e-resize;
105 | }
106 | .layout-split-proxy-v {
107 | height: 5px;
108 | cursor: n-resize;
109 | }
110 | .layout-mask {
111 | position: absolute;
112 | background: #fafafa;
113 | filter: alpha(opacity=10);
114 | opacity: 0.10;
115 | z-index: 4;
116 | }
117 | .layout-button-up {
118 | background: url('images/layout_arrows.png') no-repeat -16px -16px;
119 | }
120 | .layout-button-down {
121 | background: url('images/layout_arrows.png') no-repeat -16px 0;
122 | }
123 | .layout-button-left {
124 | background: url('images/layout_arrows.png') no-repeat 0 0;
125 | }
126 | .layout-button-right {
127 | background: url('images/layout_arrows.png') no-repeat 0 -16px;
128 | }
129 | .layout-split-proxy-h,
130 | .layout-split-proxy-v {
131 | background-color: #aac5e7;
132 | }
133 | .layout-split-north {
134 | border-bottom: 5px solid #E6EEF8;
135 | }
136 | .layout-split-south {
137 | border-top: 5px solid #E6EEF8;
138 | }
139 | .layout-split-east {
140 | border-left: 5px solid #E6EEF8;
141 | }
142 | .layout-split-west {
143 | border-right: 5px solid #E6EEF8;
144 | }
145 | .layout-expand {
146 | background-color: #E0ECFF;
147 | }
148 | .layout-expand-over {
149 | background-color: #E0ECFF;
150 | }
151 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/linkbutton.css:
--------------------------------------------------------------------------------
1 | .l-btn {
2 | text-decoration: none;
3 | display: inline-block;
4 | overflow: hidden;
5 | margin: 0;
6 | padding: 0;
7 | cursor: pointer;
8 | outline: none;
9 | text-align: center;
10 | vertical-align: middle;
11 | line-height: normal;
12 | }
13 | .l-btn-plain {
14 | border-width: 0;
15 | padding: 1px;
16 | }
17 | .l-btn-left {
18 | display: inline-block;
19 | position: relative;
20 | overflow: hidden;
21 | margin: 0;
22 | padding: 0;
23 | vertical-align: top;
24 | }
25 | .l-btn-text {
26 | display: inline-block;
27 | vertical-align: top;
28 | width: auto;
29 | line-height: 24px;
30 | font-size: 12px;
31 | padding: 0;
32 | margin: 0 4px;
33 | }
34 | .l-btn-icon {
35 | display: inline-block;
36 | width: 16px;
37 | height: 16px;
38 | line-height: 16px;
39 | position: absolute;
40 | top: 50%;
41 | margin-top: -8px;
42 | font-size: 1px;
43 | }
44 | .l-btn span span .l-btn-empty {
45 | display: inline-block;
46 | margin: 0;
47 | width: 16px;
48 | height: 24px;
49 | font-size: 1px;
50 | vertical-align: top;
51 | }
52 | .l-btn span .l-btn-icon-left {
53 | padding: 0 0 0 20px;
54 | background-position: left center;
55 | }
56 | .l-btn span .l-btn-icon-right {
57 | padding: 0 20px 0 0;
58 | background-position: right center;
59 | }
60 | .l-btn-icon-left .l-btn-text {
61 | margin: 0 4px 0 24px;
62 | }
63 | .l-btn-icon-left .l-btn-icon {
64 | left: 4px;
65 | }
66 | .l-btn-icon-right .l-btn-text {
67 | margin: 0 24px 0 4px;
68 | }
69 | .l-btn-icon-right .l-btn-icon {
70 | right: 4px;
71 | }
72 | .l-btn-icon-top .l-btn-text {
73 | margin: 20px 4px 0 4px;
74 | }
75 | .l-btn-icon-top .l-btn-icon {
76 | top: 4px;
77 | left: 50%;
78 | margin: 0 0 0 -8px;
79 | }
80 | .l-btn-icon-bottom .l-btn-text {
81 | margin: 0 4px 20px 4px;
82 | }
83 | .l-btn-icon-bottom .l-btn-icon {
84 | top: auto;
85 | bottom: 4px;
86 | left: 50%;
87 | margin: 0 0 0 -8px;
88 | }
89 | .l-btn-left .l-btn-empty {
90 | margin: 0 4px;
91 | width: 16px;
92 | }
93 | .l-btn-plain:hover {
94 | padding: 0;
95 | }
96 | .l-btn-focus {
97 | outline: #0000FF dotted thin;
98 | }
99 | .l-btn-large .l-btn-text {
100 | line-height: 40px;
101 | }
102 | .l-btn-large .l-btn-icon {
103 | width: 32px;
104 | height: 32px;
105 | line-height: 32px;
106 | margin-top: -16px;
107 | }
108 | .l-btn-large .l-btn-icon-left .l-btn-text {
109 | margin-left: 40px;
110 | }
111 | .l-btn-large .l-btn-icon-right .l-btn-text {
112 | margin-right: 40px;
113 | }
114 | .l-btn-large .l-btn-icon-top .l-btn-text {
115 | margin-top: 36px;
116 | line-height: 24px;
117 | min-width: 32px;
118 | }
119 | .l-btn-large .l-btn-icon-top .l-btn-icon {
120 | margin: 0 0 0 -16px;
121 | }
122 | .l-btn-large .l-btn-icon-bottom .l-btn-text {
123 | margin-bottom: 36px;
124 | line-height: 24px;
125 | min-width: 32px;
126 | }
127 | .l-btn-large .l-btn-icon-bottom .l-btn-icon {
128 | margin: 0 0 0 -16px;
129 | }
130 | .l-btn-large .l-btn-left .l-btn-empty {
131 | margin: 0 4px;
132 | width: 32px;
133 | }
134 | .l-btn {
135 | color: #444;
136 | background: #fafafa;
137 | background-repeat: repeat-x;
138 | border: 1px solid #bbb;
139 | background: -webkit-linear-gradient(top,#ffffff 0,#eeeeee 100%);
140 | background: -moz-linear-gradient(top,#ffffff 0,#eeeeee 100%);
141 | background: -o-linear-gradient(top,#ffffff 0,#eeeeee 100%);
142 | background: linear-gradient(to bottom,#ffffff 0,#eeeeee 100%);
143 | background-repeat: repeat-x;
144 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#ffffff,endColorstr=#eeeeee,GradientType=0);
145 | -moz-border-radius: 5px 5px 5px 5px;
146 | -webkit-border-radius: 5px 5px 5px 5px;
147 | border-radius: 5px 5px 5px 5px;
148 | }
149 | .l-btn:hover {
150 | background: #eaf2ff;
151 | color: #000000;
152 | border: 1px solid #b7d2ff;
153 | filter: none;
154 | }
155 | .l-btn-plain {
156 | background: transparent;
157 | border-width: 0;
158 | filter: none;
159 | }
160 | .l-btn-outline {
161 | border-width: 1px;
162 | border-color: #b7d2ff;
163 | padding: 0;
164 | }
165 | .l-btn-plain:hover {
166 | background: #eaf2ff;
167 | color: #000000;
168 | border: 1px solid #b7d2ff;
169 | -moz-border-radius: 5px 5px 5px 5px;
170 | -webkit-border-radius: 5px 5px 5px 5px;
171 | border-radius: 5px 5px 5px 5px;
172 | }
173 | .l-btn-disabled,
174 | .l-btn-disabled:hover {
175 | opacity: 0.5;
176 | cursor: default;
177 | background: #fafafa;
178 | color: #444;
179 | background: -webkit-linear-gradient(top,#ffffff 0,#eeeeee 100%);
180 | background: -moz-linear-gradient(top,#ffffff 0,#eeeeee 100%);
181 | background: -o-linear-gradient(top,#ffffff 0,#eeeeee 100%);
182 | background: linear-gradient(to bottom,#ffffff 0,#eeeeee 100%);
183 | background-repeat: repeat-x;
184 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#ffffff,endColorstr=#eeeeee,GradientType=0);
185 | }
186 | .l-btn-disabled .l-btn-text,
187 | .l-btn-disabled .l-btn-icon {
188 | filter: alpha(opacity=50);
189 | }
190 | .l-btn-plain-disabled,
191 | .l-btn-plain-disabled:hover {
192 | background: transparent;
193 | filter: alpha(opacity=50);
194 | }
195 | .l-btn-selected,
196 | .l-btn-selected:hover {
197 | background: #ddd;
198 | filter: none;
199 | }
200 | .l-btn-plain-selected,
201 | .l-btn-plain-selected:hover {
202 | background: #ddd;
203 | }
204 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/menu.css:
--------------------------------------------------------------------------------
1 | .menu {
2 | position: absolute;
3 | margin: 0;
4 | padding: 2px;
5 | border-width: 1px;
6 | border-style: solid;
7 | overflow: hidden;
8 | }
9 | .menu-inline {
10 | position: relative;
11 | }
12 | .menu-item {
13 | position: relative;
14 | margin: 0;
15 | padding: 0;
16 | overflow: hidden;
17 | white-space: nowrap;
18 | cursor: pointer;
19 | border-width: 1px;
20 | border-style: solid;
21 | }
22 | .menu-text {
23 | height: 20px;
24 | line-height: 20px;
25 | float: left;
26 | padding-left: 28px;
27 | }
28 | .menu-icon {
29 | position: absolute;
30 | width: 16px;
31 | height: 16px;
32 | left: 2px;
33 | top: 50%;
34 | margin-top: -8px;
35 | }
36 | .menu-rightarrow {
37 | position: absolute;
38 | width: 16px;
39 | height: 16px;
40 | right: 0;
41 | top: 50%;
42 | margin-top: -8px;
43 | }
44 | .menu-line {
45 | position: absolute;
46 | left: 26px;
47 | top: 0;
48 | height: 2000px;
49 | font-size: 1px;
50 | }
51 | .menu-sep {
52 | margin: 3px 0px 3px 25px;
53 | font-size: 1px;
54 | }
55 | .menu-noline .menu-line {
56 | display: none;
57 | }
58 | .menu-noline .menu-sep {
59 | margin-left: 0;
60 | margin-right: 0;
61 | }
62 | .menu-active {
63 | -moz-border-radius: 5px 5px 5px 5px;
64 | -webkit-border-radius: 5px 5px 5px 5px;
65 | border-radius: 5px 5px 5px 5px;
66 | }
67 | .menu-item-disabled {
68 | opacity: 0.5;
69 | filter: alpha(opacity=50);
70 | cursor: default;
71 | }
72 | .menu-text,
73 | .menu-text span {
74 | font-size: 12px;
75 | }
76 | .menu-shadow {
77 | position: absolute;
78 | -moz-border-radius: 5px 5px 5px 5px;
79 | -webkit-border-radius: 5px 5px 5px 5px;
80 | border-radius: 5px 5px 5px 5px;
81 | background: #ccc;
82 | -moz-box-shadow: 2px 2px 3px #cccccc;
83 | -webkit-box-shadow: 2px 2px 3px #cccccc;
84 | box-shadow: 2px 2px 3px #cccccc;
85 | filter: progid:DXImageTransform.Microsoft.Blur(pixelRadius=2,MakeShadow=false,ShadowOpacity=0.2);
86 | }
87 | .menu-rightarrow {
88 | background: url('images/menu_arrows.png') no-repeat -32px center;
89 | }
90 | .menu-line {
91 | border-left: 1px solid #ccc;
92 | border-right: 1px solid #fff;
93 | }
94 | .menu-sep {
95 | border-top: 1px solid #ccc;
96 | border-bottom: 1px solid #fff;
97 | }
98 | .menu {
99 | background-color: #fafafa;
100 | border-color: #ddd;
101 | color: #444;
102 | }
103 | .menu-content {
104 | background: #ffffff;
105 | }
106 | .menu-item {
107 | border-color: transparent;
108 | _border-color: #fafafa;
109 | }
110 | .menu-active {
111 | border-color: #b7d2ff;
112 | color: #000000;
113 | background: #eaf2ff;
114 | }
115 | .menu-active-disabled {
116 | border-color: transparent;
117 | background: transparent;
118 | color: #444;
119 | }
120 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/menubutton.css:
--------------------------------------------------------------------------------
1 | .m-btn-downarrow,
2 | .s-btn-downarrow {
3 | display: inline-block;
4 | position: absolute;
5 | width: 16px;
6 | height: 16px;
7 | font-size: 1px;
8 | right: 0;
9 | top: 50%;
10 | margin-top: -8px;
11 | }
12 | .m-btn-active,
13 | .s-btn-active {
14 | background: #eaf2ff;
15 | color: #000000;
16 | border: 1px solid #b7d2ff;
17 | filter: none;
18 | }
19 | .m-btn-plain-active,
20 | .s-btn-plain-active {
21 | background: transparent;
22 | padding: 0;
23 | border-width: 1px;
24 | border-style: solid;
25 | -moz-border-radius: 5px 5px 5px 5px;
26 | -webkit-border-radius: 5px 5px 5px 5px;
27 | border-radius: 5px 5px 5px 5px;
28 | }
29 | .m-btn .l-btn-left .l-btn-text {
30 | margin-right: 20px;
31 | }
32 | .m-btn .l-btn-icon-right .l-btn-text {
33 | margin-right: 40px;
34 | }
35 | .m-btn .l-btn-icon-right .l-btn-icon {
36 | right: 20px;
37 | }
38 | .m-btn .l-btn-icon-top .l-btn-text {
39 | margin-right: 4px;
40 | margin-bottom: 14px;
41 | }
42 | .m-btn .l-btn-icon-bottom .l-btn-text {
43 | margin-right: 4px;
44 | margin-bottom: 34px;
45 | }
46 | .m-btn .l-btn-icon-bottom .l-btn-icon {
47 | top: auto;
48 | bottom: 20px;
49 | }
50 | .m-btn .l-btn-icon-top .m-btn-downarrow,
51 | .m-btn .l-btn-icon-bottom .m-btn-downarrow {
52 | top: auto;
53 | bottom: 0px;
54 | left: 50%;
55 | margin-left: -8px;
56 | }
57 | .m-btn-line {
58 | display: inline-block;
59 | position: absolute;
60 | font-size: 1px;
61 | display: none;
62 | }
63 | .m-btn .l-btn-left .m-btn-line {
64 | right: 0;
65 | width: 16px;
66 | height: 500px;
67 | border-style: solid;
68 | border-color: #aac5e7;
69 | border-width: 0 0 0 1px;
70 | }
71 | .m-btn .l-btn-icon-top .m-btn-line,
72 | .m-btn .l-btn-icon-bottom .m-btn-line {
73 | left: 0;
74 | bottom: 0;
75 | width: 500px;
76 | height: 16px;
77 | border-width: 1px 0 0 0;
78 | }
79 | .m-btn-large .l-btn-icon-right .l-btn-text {
80 | margin-right: 56px;
81 | }
82 | .m-btn-large .l-btn-icon-bottom .l-btn-text {
83 | margin-bottom: 50px;
84 | }
85 | .m-btn-downarrow,
86 | .s-btn-downarrow {
87 | background: url('images/menu_arrows.png') no-repeat 0 center;
88 | }
89 | .m-btn-plain-active,
90 | .s-btn-plain-active {
91 | border-color: #b7d2ff;
92 | background-color: #eaf2ff;
93 | color: #000000;
94 | }
95 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/messager.css:
--------------------------------------------------------------------------------
1 | .messager-body {
2 | padding: 10px 10px 30px 10px;
3 | overflow: auto;
4 | }
5 | .messager-button {
6 | text-align: center;
7 | padding: 5px;
8 | }
9 | .messager-button .l-btn {
10 | width: 70px;
11 | }
12 | .messager-icon {
13 | float: left;
14 | width: 32px;
15 | height: 32px;
16 | margin: 0 10px 10px 0;
17 | }
18 | .messager-error {
19 | background: url('images/messager_icons.png') no-repeat scroll -64px 0;
20 | }
21 | .messager-info {
22 | background: url('images/messager_icons.png') no-repeat scroll 0 0;
23 | }
24 | .messager-question {
25 | background: url('images/messager_icons.png') no-repeat scroll -32px 0;
26 | }
27 | .messager-warning {
28 | background: url('images/messager_icons.png') no-repeat scroll -96px 0;
29 | }
30 | .messager-progress {
31 | padding: 10px;
32 | }
33 | .messager-p-msg {
34 | margin-bottom: 5px;
35 | }
36 | .messager-body .messager-input {
37 | width: 100%;
38 | padding: 4px 0;
39 | outline-style: none;
40 | border: 1px solid #95B8E7;
41 | }
42 | .window-thinborder .messager-button {
43 | padding-bottom: 8px;
44 | }
45 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/numberbox.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/default/numberbox.css
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/pagination.css:
--------------------------------------------------------------------------------
1 | .pagination {
2 | zoom: 1;
3 | }
4 | .pagination table {
5 | float: left;
6 | height: 30px;
7 | }
8 | .pagination td {
9 | border: 0;
10 | }
11 | .pagination-btn-separator {
12 | float: left;
13 | height: 24px;
14 | border-left: 1px solid #ccc;
15 | border-right: 1px solid #fff;
16 | margin: 3px 1px;
17 | }
18 | .pagination .pagination-num {
19 | border-width: 1px;
20 | border-style: solid;
21 | margin: 0 2px;
22 | padding: 2px;
23 | width: 2em;
24 | height: auto;
25 | }
26 | .pagination-page-list {
27 | margin: 0px 6px;
28 | padding: 1px 2px;
29 | width: auto;
30 | height: auto;
31 | border-width: 1px;
32 | border-style: solid;
33 | }
34 | .pagination-info {
35 | float: right;
36 | margin: 0 6px;
37 | padding: 0;
38 | height: 30px;
39 | line-height: 30px;
40 | font-size: 12px;
41 | }
42 | .pagination span {
43 | font-size: 12px;
44 | }
45 | .pagination-link .l-btn-text {
46 | width: 24px;
47 | text-align: center;
48 | margin: 0;
49 | }
50 | .pagination-first {
51 | background: url('images/pagination_icons.png') no-repeat 0 center;
52 | }
53 | .pagination-prev {
54 | background: url('images/pagination_icons.png') no-repeat -16px center;
55 | }
56 | .pagination-next {
57 | background: url('images/pagination_icons.png') no-repeat -32px center;
58 | }
59 | .pagination-last {
60 | background: url('images/pagination_icons.png') no-repeat -48px center;
61 | }
62 | .pagination-load {
63 | background: url('images/pagination_icons.png') no-repeat -64px center;
64 | }
65 | .pagination-loading {
66 | background: url('images/loading.gif') no-repeat center center;
67 | }
68 | .pagination-page-list,
69 | .pagination .pagination-num {
70 | border-color: #95B8E7;
71 | }
72 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/passwordbox.css:
--------------------------------------------------------------------------------
1 | .passwordbox-open {
2 | background: url('images/passwordbox_open.png') no-repeat center center;
3 | }
4 | .passwordbox-close {
5 | background: url('images/passwordbox_close.png') no-repeat center center;
6 | }
7 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/progressbar.css:
--------------------------------------------------------------------------------
1 | .progressbar {
2 | border-width: 1px;
3 | border-style: solid;
4 | -moz-border-radius: 5px 5px 5px 5px;
5 | -webkit-border-radius: 5px 5px 5px 5px;
6 | border-radius: 5px 5px 5px 5px;
7 | overflow: hidden;
8 | position: relative;
9 | }
10 | .progressbar-text {
11 | text-align: center;
12 | position: absolute;
13 | }
14 | .progressbar-value {
15 | position: relative;
16 | overflow: hidden;
17 | width: 0;
18 | -moz-border-radius: 5px 0 0 5px;
19 | -webkit-border-radius: 5px 0 0 5px;
20 | border-radius: 5px 0 0 5px;
21 | }
22 | .progressbar {
23 | border-color: #95B8E7;
24 | }
25 | .progressbar-text {
26 | color: #000000;
27 | font-size: 12px;
28 | }
29 | .progressbar-value .progressbar-text {
30 | background-color: #ffe48d;
31 | color: #000000;
32 | }
33 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/propertygrid.css:
--------------------------------------------------------------------------------
1 | .propertygrid .datagrid-view1 .datagrid-body td {
2 | padding-bottom: 1px;
3 | border-width: 0 1px 0 0;
4 | }
5 | .propertygrid .datagrid-group {
6 | height: 21px;
7 | overflow: hidden;
8 | border-width: 0 0 1px 0;
9 | border-style: solid;
10 | }
11 | .propertygrid .datagrid-group span {
12 | font-weight: bold;
13 | }
14 | .propertygrid .datagrid-view1 .datagrid-body td {
15 | border-color: #dddddd;
16 | }
17 | .propertygrid .datagrid-view1 .datagrid-group {
18 | border-color: #E0ECFF;
19 | }
20 | .propertygrid .datagrid-view2 .datagrid-group {
21 | border-color: #dddddd;
22 | }
23 | .propertygrid .datagrid-group,
24 | .propertygrid .datagrid-view1 .datagrid-body,
25 | .propertygrid .datagrid-view1 .datagrid-row-over,
26 | .propertygrid .datagrid-view1 .datagrid-row-selected {
27 | background: #E0ECFF;
28 | }
29 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/searchbox.css:
--------------------------------------------------------------------------------
1 | .searchbox-button {
2 | width: 18px;
3 | height: 20px;
4 | overflow: hidden;
5 | display: inline-block;
6 | vertical-align: top;
7 | cursor: pointer;
8 | opacity: 0.6;
9 | filter: alpha(opacity=60);
10 | }
11 | .searchbox-button-hover {
12 | opacity: 1.0;
13 | filter: alpha(opacity=100);
14 | }
15 | .searchbox .l-btn-plain {
16 | border: 0;
17 | padding: 0;
18 | vertical-align: top;
19 | opacity: 0.6;
20 | filter: alpha(opacity=60);
21 | -moz-border-radius: 0 0 0 0;
22 | -webkit-border-radius: 0 0 0 0;
23 | border-radius: 0 0 0 0;
24 | }
25 | .searchbox .l-btn-plain:hover {
26 | border: 0;
27 | padding: 0;
28 | opacity: 1.0;
29 | filter: alpha(opacity=100);
30 | -moz-border-radius: 0 0 0 0;
31 | -webkit-border-radius: 0 0 0 0;
32 | border-radius: 0 0 0 0;
33 | }
34 | .searchbox a.m-btn-plain-active {
35 | -moz-border-radius: 0 0 0 0;
36 | -webkit-border-radius: 0 0 0 0;
37 | border-radius: 0 0 0 0;
38 | }
39 | .searchbox .m-btn-active {
40 | border-width: 0 1px 0 0;
41 | -moz-border-radius: 0 0 0 0;
42 | -webkit-border-radius: 0 0 0 0;
43 | border-radius: 0 0 0 0;
44 | }
45 | .searchbox .textbox-button-right {
46 | border-width: 0 0 0 1px;
47 | }
48 | .searchbox .textbox-button-left {
49 | border-width: 0 1px 0 0;
50 | }
51 | .searchbox-button {
52 | background: url('images/searchbox_button.png') no-repeat center center;
53 | }
54 | .searchbox .l-btn-plain {
55 | background: #E0ECFF;
56 | }
57 | .searchbox .l-btn-plain-disabled,
58 | .searchbox .l-btn-plain-disabled:hover {
59 | opacity: 0.5;
60 | filter: alpha(opacity=50);
61 | }
62 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/slider.css:
--------------------------------------------------------------------------------
1 | .slider-disabled {
2 | opacity: 0.5;
3 | filter: alpha(opacity=50);
4 | }
5 | .slider-h {
6 | height: 22px;
7 | }
8 | .slider-v {
9 | width: 22px;
10 | }
11 | .slider-inner {
12 | position: relative;
13 | height: 6px;
14 | top: 7px;
15 | border-width: 1px;
16 | border-style: solid;
17 | border-radius: 5px;
18 | }
19 | .slider-handle {
20 | position: absolute;
21 | display: block;
22 | outline: none;
23 | width: 20px;
24 | height: 20px;
25 | top: 50%;
26 | margin-top: -10px;
27 | margin-left: -10px;
28 | }
29 | .slider-tip {
30 | position: absolute;
31 | display: inline-block;
32 | line-height: 12px;
33 | font-size: 12px;
34 | white-space: nowrap;
35 | top: -22px;
36 | }
37 | .slider-rule {
38 | position: relative;
39 | top: 15px;
40 | }
41 | .slider-rule span {
42 | position: absolute;
43 | display: inline-block;
44 | font-size: 0;
45 | height: 5px;
46 | border-width: 0 0 0 1px;
47 | border-style: solid;
48 | }
49 | .slider-rulelabel {
50 | position: relative;
51 | top: 20px;
52 | }
53 | .slider-rulelabel span {
54 | position: absolute;
55 | display: inline-block;
56 | font-size: 12px;
57 | }
58 | .slider-v .slider-inner {
59 | width: 6px;
60 | left: 7px;
61 | top: 0;
62 | float: left;
63 | }
64 | .slider-v .slider-handle {
65 | left: 50%;
66 | margin-top: -10px;
67 | }
68 | .slider-v .slider-tip {
69 | left: -10px;
70 | margin-top: -6px;
71 | }
72 | .slider-v .slider-rule {
73 | float: left;
74 | top: 0;
75 | left: 16px;
76 | }
77 | .slider-v .slider-rule span {
78 | width: 5px;
79 | height: 'auto';
80 | border-left: 0;
81 | border-width: 1px 0 0 0;
82 | border-style: solid;
83 | }
84 | .slider-v .slider-rulelabel {
85 | float: left;
86 | top: 0;
87 | left: 23px;
88 | }
89 | .slider-handle {
90 | background: url('images/slider_handle.png') no-repeat;
91 | }
92 | .slider-inner {
93 | border-color: #95B8E7;
94 | background: #E0ECFF;
95 | }
96 | .slider-rule span {
97 | border-color: #95B8E7;
98 | }
99 | .slider-rulelabel span {
100 | color: #000000;
101 | }
102 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/spinner.css:
--------------------------------------------------------------------------------
1 | .spinner-arrow {
2 | background-color: #E0ECFF;
3 | display: inline-block;
4 | overflow: hidden;
5 | vertical-align: top;
6 | margin: 0;
7 | padding: 0;
8 | opacity: 1.0;
9 | filter: alpha(opacity=100);
10 | width: 18px;
11 | }
12 | .spinner-arrow-up,
13 | .spinner-arrow-down {
14 | opacity: 0.6;
15 | filter: alpha(opacity=60);
16 | display: block;
17 | font-size: 1px;
18 | width: 18px;
19 | height: 10px;
20 | width: 100%;
21 | height: 50%;
22 | color: #444;
23 | outline-style: none;
24 | }
25 | .spinner-arrow-hover {
26 | background-color: #eaf2ff;
27 | opacity: 1.0;
28 | filter: alpha(opacity=100);
29 | }
30 | .spinner-arrow-up:hover,
31 | .spinner-arrow-down:hover {
32 | opacity: 1.0;
33 | filter: alpha(opacity=100);
34 | background-color: #eaf2ff;
35 | }
36 | .textbox-icon-disabled .spinner-arrow-up:hover,
37 | .textbox-icon-disabled .spinner-arrow-down:hover {
38 | opacity: 0.6;
39 | filter: alpha(opacity=60);
40 | background-color: #E0ECFF;
41 | cursor: default;
42 | }
43 | .spinner .textbox-icon-disabled {
44 | opacity: 0.6;
45 | filter: alpha(opacity=60);
46 | }
47 | .spinner-arrow-up {
48 | background: url('images/spinner_arrows.png') no-repeat 1px center;
49 | }
50 | .spinner-arrow-down {
51 | background: url('images/spinner_arrows.png') no-repeat -15px center;
52 | }
53 | .spinner-button-up {
54 | background: url('images/spinner_arrows.png') no-repeat -32px center;
55 | }
56 | .spinner-button-down {
57 | background: url('images/spinner_arrows.png') no-repeat -48px center;
58 | }
59 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/splitbutton.css:
--------------------------------------------------------------------------------
1 | .s-btn:hover .m-btn-line,
2 | .s-btn-active .m-btn-line,
3 | .s-btn-plain-active .m-btn-line {
4 | display: inline-block;
5 | }
6 | .l-btn:hover .s-btn-downarrow,
7 | .s-btn-active .s-btn-downarrow,
8 | .s-btn-plain-active .s-btn-downarrow {
9 | border-style: solid;
10 | border-color: #aac5e7;
11 | border-width: 0 0 0 1px;
12 | }
13 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/switchbutton.css:
--------------------------------------------------------------------------------
1 | .switchbutton {
2 | text-decoration: none;
3 | display: inline-block;
4 | overflow: hidden;
5 | vertical-align: middle;
6 | margin: 0;
7 | padding: 0;
8 | cursor: pointer;
9 | background: #bbb;
10 | border: 1px solid #bbb;
11 | -moz-border-radius: 5px 5px 5px 5px;
12 | -webkit-border-radius: 5px 5px 5px 5px;
13 | border-radius: 5px 5px 5px 5px;
14 | }
15 | .switchbutton-inner {
16 | display: inline-block;
17 | overflow: hidden;
18 | position: relative;
19 | top: -1px;
20 | left: -1px;
21 | }
22 | .switchbutton-on,
23 | .switchbutton-off,
24 | .switchbutton-handle {
25 | display: inline-block;
26 | text-align: center;
27 | height: 100%;
28 | float: left;
29 | font-size: 12px;
30 | -moz-border-radius: 5px 5px 5px 5px;
31 | -webkit-border-radius: 5px 5px 5px 5px;
32 | border-radius: 5px 5px 5px 5px;
33 | }
34 | .switchbutton-on {
35 | background: #ffe48d;
36 | color: #000000;
37 | }
38 | .switchbutton-off {
39 | background-color: #ffffff;
40 | color: #000000;
41 | }
42 | .switchbutton-on,
43 | .switchbutton-reversed .switchbutton-off {
44 | -moz-border-radius: 5px 0 0 5px;
45 | -webkit-border-radius: 5px 0 0 5px;
46 | border-radius: 5px 0 0 5px;
47 | }
48 | .switchbutton-off,
49 | .switchbutton-reversed .switchbutton-on {
50 | -moz-border-radius: 0 5px 5px 0;
51 | -webkit-border-radius: 0 5px 5px 0;
52 | border-radius: 0 5px 5px 0;
53 | }
54 | .switchbutton-handle {
55 | position: absolute;
56 | top: 0;
57 | left: 50%;
58 | background-color: #ffffff;
59 | color: #000000;
60 | border: 1px solid #bbb;
61 | -moz-box-shadow: 0 0 3px 0 #bbb;
62 | -webkit-box-shadow: 0 0 3px 0 #bbb;
63 | box-shadow: 0 0 3px 0 #bbb;
64 | }
65 | .switchbutton-value {
66 | position: absolute;
67 | top: 0;
68 | left: -5000px;
69 | }
70 | .switchbutton-disabled {
71 | opacity: 0.5;
72 | filter: alpha(opacity=50);
73 | }
74 | .switchbutton-disabled,
75 | .switchbutton-readonly {
76 | cursor: default;
77 | }
78 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/tagbox.css:
--------------------------------------------------------------------------------
1 | .tagbox {
2 | cursor: text;
3 | }
4 | .tagbox .textbox-text {
5 | float: left;
6 | }
7 | .tagbox-label {
8 | position: relative;
9 | display: block;
10 | margin: 4px 0 0 4px;
11 | padding: 0 20px 0 4px;
12 | float: left;
13 | vertical-align: top;
14 | text-decoration: none;
15 | -moz-border-radius: 5px 5px 5px 5px;
16 | -webkit-border-radius: 5px 5px 5px 5px;
17 | border-radius: 5px 5px 5px 5px;
18 | background: #eaf2ff;
19 | color: #000000;
20 | }
21 | .tagbox-remove {
22 | background: url('images/tagbox_icons.png') no-repeat -16px center;
23 | position: absolute;
24 | display: block;
25 | width: 16px;
26 | height: 16px;
27 | right: 2px;
28 | top: 50%;
29 | margin-top: -8px;
30 | opacity: 0.6;
31 | filter: alpha(opacity=60);
32 | }
33 | .tagbox-remove:hover {
34 | opacity: 1;
35 | filter: alpha(opacity=100);
36 | }
37 | .textbox-disabled .tagbox-label {
38 | cursor: default;
39 | }
40 | .textbox-disabled .tagbox-remove:hover {
41 | cursor: default;
42 | opacity: 0.6;
43 | filter: alpha(opacity=60);
44 | }
45 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/textbox.css:
--------------------------------------------------------------------------------
1 | .textbox {
2 | position: relative;
3 | border: 1px solid #95B8E7;
4 | background-color: #fff;
5 | vertical-align: middle;
6 | display: inline-block;
7 | overflow: hidden;
8 | white-space: nowrap;
9 | margin: 0;
10 | padding: 0;
11 | -moz-border-radius: 5px 5px 5px 5px;
12 | -webkit-border-radius: 5px 5px 5px 5px;
13 | border-radius: 5px 5px 5px 5px;
14 | }
15 | .textbox .textbox-text {
16 | font-size: 12px;
17 | border: 0;
18 | margin: 0;
19 | padding: 4px;
20 | white-space: normal;
21 | vertical-align: top;
22 | outline-style: none;
23 | resize: none;
24 | -moz-border-radius: 5px 5px 5px 5px;
25 | -webkit-border-radius: 5px 5px 5px 5px;
26 | border-radius: 5px 5px 5px 5px;
27 | }
28 | .textbox .textbox-text::-ms-clear,
29 | .textbox .textbox-text::-ms-reveal {
30 | display: none;
31 | }
32 | .textbox textarea.textbox-text {
33 | white-space: pre-wrap;
34 | }
35 | .textbox .textbox-prompt {
36 | font-size: 12px;
37 | color: #aaa;
38 | }
39 | .textbox .textbox-bgicon {
40 | background-position: 3px center;
41 | padding-left: 21px;
42 | }
43 | .textbox .textbox-button,
44 | .textbox .textbox-button:hover {
45 | position: absolute;
46 | top: 0;
47 | padding: 0;
48 | vertical-align: top;
49 | -moz-border-radius: 0 0 0 0;
50 | -webkit-border-radius: 0 0 0 0;
51 | border-radius: 0 0 0 0;
52 | }
53 | .textbox .textbox-button-right,
54 | .textbox .textbox-button-right:hover {
55 | right: 0;
56 | border-width: 0 0 0 1px;
57 | }
58 | .textbox .textbox-button-left,
59 | .textbox .textbox-button-left:hover {
60 | left: 0;
61 | border-width: 0 1px 0 0;
62 | }
63 | .textbox .textbox-button-top,
64 | .textbox .textbox-button-top:hover {
65 | left: 0;
66 | border-width: 0 0 1px 0;
67 | }
68 | .textbox .textbox-button-bottom,
69 | .textbox .textbox-button-bottom:hover {
70 | top: auto;
71 | bottom: 0;
72 | left: 0;
73 | border-width: 1px 0 0 0;
74 | }
75 | .textbox-addon {
76 | position: absolute;
77 | top: 0;
78 | }
79 | .textbox-label {
80 | display: inline-block;
81 | width: 80px;
82 | height: 22px;
83 | line-height: 22px;
84 | vertical-align: middle;
85 | overflow: hidden;
86 | text-overflow: ellipsis;
87 | white-space: nowrap;
88 | margin: 0;
89 | padding-right: 5px;
90 | }
91 | .textbox-label-after {
92 | padding-left: 5px;
93 | padding-right: 0;
94 | }
95 | .textbox-label-top {
96 | display: block;
97 | width: auto;
98 | padding: 0;
99 | }
100 | .textbox-disabled,
101 | .textbox-label-disabled {
102 | opacity: 0.6;
103 | filter: alpha(opacity=60);
104 | }
105 | .textbox-icon {
106 | display: inline-block;
107 | width: 18px;
108 | height: 20px;
109 | overflow: hidden;
110 | vertical-align: top;
111 | background-position: center center;
112 | cursor: pointer;
113 | opacity: 0.6;
114 | filter: alpha(opacity=60);
115 | text-decoration: none;
116 | outline-style: none;
117 | }
118 | .textbox-icon-disabled,
119 | .textbox-icon-readonly {
120 | cursor: default;
121 | }
122 | .textbox-icon:hover {
123 | opacity: 1.0;
124 | filter: alpha(opacity=100);
125 | }
126 | .textbox-icon-disabled:hover {
127 | opacity: 0.6;
128 | filter: alpha(opacity=60);
129 | }
130 | .textbox-focused {
131 | border-color: #6b9cde;
132 | -moz-box-shadow: 0 0 3px 0 #95B8E7;
133 | -webkit-box-shadow: 0 0 3px 0 #95B8E7;
134 | box-shadow: 0 0 3px 0 #95B8E7;
135 | }
136 | .textbox-invalid {
137 | border-color: #ffa8a8;
138 | background-color: #fff3f3;
139 | }
140 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/tooltip.css:
--------------------------------------------------------------------------------
1 | .tooltip {
2 | position: absolute;
3 | display: none;
4 | z-index: 9900000;
5 | outline: none;
6 | opacity: 1;
7 | filter: alpha(opacity=100);
8 | padding: 5px;
9 | border-width: 1px;
10 | border-style: solid;
11 | border-radius: 5px;
12 | -moz-border-radius: 5px 5px 5px 5px;
13 | -webkit-border-radius: 5px 5px 5px 5px;
14 | border-radius: 5px 5px 5px 5px;
15 | }
16 | .tooltip-content {
17 | font-size: 12px;
18 | }
19 | .tooltip-arrow-outer,
20 | .tooltip-arrow {
21 | position: absolute;
22 | width: 0;
23 | height: 0;
24 | line-height: 0;
25 | font-size: 0;
26 | border-style: solid;
27 | border-width: 6px;
28 | border-color: transparent;
29 | _border-color: tomato;
30 | _filter: chroma(color=tomato);
31 | }
32 | .tooltip-arrow {
33 | display: none \9;
34 | }
35 | .tooltip-right .tooltip-arrow-outer {
36 | left: 0;
37 | top: 50%;
38 | margin: -6px 0 0 -13px;
39 | }
40 | .tooltip-right .tooltip-arrow {
41 | left: 0;
42 | top: 50%;
43 | margin: -6px 0 0 -12px;
44 | }
45 | .tooltip-left .tooltip-arrow-outer {
46 | right: 0;
47 | top: 50%;
48 | margin: -6px -13px 0 0;
49 | }
50 | .tooltip-left .tooltip-arrow {
51 | right: 0;
52 | top: 50%;
53 | margin: -6px -12px 0 0;
54 | }
55 | .tooltip-top .tooltip-arrow-outer {
56 | bottom: 0;
57 | left: 50%;
58 | margin: 0 0 -13px -6px;
59 | }
60 | .tooltip-top .tooltip-arrow {
61 | bottom: 0;
62 | left: 50%;
63 | margin: 0 0 -12px -6px;
64 | }
65 | .tooltip-bottom .tooltip-arrow-outer {
66 | top: 0;
67 | left: 50%;
68 | margin: -13px 0 0 -6px;
69 | }
70 | .tooltip-bottom .tooltip-arrow {
71 | top: 0;
72 | left: 50%;
73 | margin: -12px 0 0 -6px;
74 | }
75 | .tooltip {
76 | background-color: #ffffff;
77 | border-color: #95B8E7;
78 | color: #000000;
79 | }
80 | .tooltip-right .tooltip-arrow-outer {
81 | border-right-color: #95B8E7;
82 | }
83 | .tooltip-right .tooltip-arrow {
84 | border-right-color: #ffffff;
85 | }
86 | .tooltip-left .tooltip-arrow-outer {
87 | border-left-color: #95B8E7;
88 | }
89 | .tooltip-left .tooltip-arrow {
90 | border-left-color: #ffffff;
91 | }
92 | .tooltip-top .tooltip-arrow-outer {
93 | border-top-color: #95B8E7;
94 | }
95 | .tooltip-top .tooltip-arrow {
96 | border-top-color: #ffffff;
97 | }
98 | .tooltip-bottom .tooltip-arrow-outer {
99 | border-bottom-color: #95B8E7;
100 | }
101 | .tooltip-bottom .tooltip-arrow {
102 | border-bottom-color: #ffffff;
103 | }
104 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/tree.css:
--------------------------------------------------------------------------------
1 | .tree {
2 | margin: 0;
3 | padding: 0;
4 | list-style-type: none;
5 | }
6 | .tree li {
7 | white-space: nowrap;
8 | }
9 | .tree li ul {
10 | list-style-type: none;
11 | margin: 0;
12 | padding: 0;
13 | }
14 | .tree-node {
15 | height: 18px;
16 | white-space: nowrap;
17 | cursor: pointer;
18 | }
19 | .tree-hit {
20 | cursor: pointer;
21 | }
22 | .tree-expanded,
23 | .tree-collapsed,
24 | .tree-folder,
25 | .tree-file,
26 | .tree-checkbox,
27 | .tree-indent {
28 | display: inline-block;
29 | width: 16px;
30 | height: 18px;
31 | vertical-align: top;
32 | overflow: hidden;
33 | }
34 | .tree-expanded {
35 | background: url('images/tree_icons.png') no-repeat -18px 0px;
36 | }
37 | .tree-expanded-hover {
38 | background: url('images/tree_icons.png') no-repeat -50px 0px;
39 | }
40 | .tree-collapsed {
41 | background: url('images/tree_icons.png') no-repeat 0px 0px;
42 | }
43 | .tree-collapsed-hover {
44 | background: url('images/tree_icons.png') no-repeat -32px 0px;
45 | }
46 | .tree-lines .tree-expanded,
47 | .tree-lines .tree-root-first .tree-expanded {
48 | background: url('images/tree_icons.png') no-repeat -144px 0;
49 | }
50 | .tree-lines .tree-collapsed,
51 | .tree-lines .tree-root-first .tree-collapsed {
52 | background: url('images/tree_icons.png') no-repeat -128px 0;
53 | }
54 | .tree-lines .tree-node-last .tree-expanded,
55 | .tree-lines .tree-root-one .tree-expanded {
56 | background: url('images/tree_icons.png') no-repeat -80px 0;
57 | }
58 | .tree-lines .tree-node-last .tree-collapsed,
59 | .tree-lines .tree-root-one .tree-collapsed {
60 | background: url('images/tree_icons.png') no-repeat -64px 0;
61 | }
62 | .tree-line {
63 | background: url('images/tree_icons.png') no-repeat -176px 0;
64 | }
65 | .tree-join {
66 | background: url('images/tree_icons.png') no-repeat -192px 0;
67 | }
68 | .tree-joinbottom {
69 | background: url('images/tree_icons.png') no-repeat -160px 0;
70 | }
71 | .tree-folder {
72 | background: url('images/tree_icons.png') no-repeat -208px 0;
73 | }
74 | .tree-folder-open {
75 | background: url('images/tree_icons.png') no-repeat -224px 0;
76 | }
77 | .tree-file {
78 | background: url('images/tree_icons.png') no-repeat -240px 0;
79 | }
80 | .tree-loading {
81 | background: url('images/loading.gif') no-repeat center center;
82 | }
83 | .tree-checkbox0 {
84 | background: url('images/tree_icons.png') no-repeat -208px -18px;
85 | }
86 | .tree-checkbox1 {
87 | background: url('images/tree_icons.png') no-repeat -224px -18px;
88 | }
89 | .tree-checkbox2 {
90 | background: url('images/tree_icons.png') no-repeat -240px -18px;
91 | }
92 | .tree-title {
93 | font-size: 12px;
94 | display: inline-block;
95 | text-decoration: none;
96 | vertical-align: top;
97 | white-space: nowrap;
98 | padding: 0 2px;
99 | height: 18px;
100 | line-height: 18px;
101 | }
102 | .tree-node-proxy {
103 | font-size: 12px;
104 | line-height: 20px;
105 | padding: 0 2px 0 20px;
106 | border-width: 1px;
107 | border-style: solid;
108 | z-index: 9900000;
109 | }
110 | .tree-dnd-icon {
111 | display: inline-block;
112 | position: absolute;
113 | width: 16px;
114 | height: 18px;
115 | left: 2px;
116 | top: 50%;
117 | margin-top: -9px;
118 | }
119 | .tree-dnd-yes {
120 | background: url('images/tree_icons.png') no-repeat -256px 0;
121 | }
122 | .tree-dnd-no {
123 | background: url('images/tree_icons.png') no-repeat -256px -18px;
124 | }
125 | .tree-node-top {
126 | border-top: 1px dotted red;
127 | }
128 | .tree-node-bottom {
129 | border-bottom: 1px dotted red;
130 | }
131 | .tree-node-append .tree-title {
132 | border: 1px dotted red;
133 | }
134 | .tree-editor {
135 | border: 1px solid #95B8E7;
136 | font-size: 12px;
137 | line-height: 16px;
138 | padding: 0 4px;
139 | margin: 0;
140 | width: 80px;
141 | outline-style: none;
142 | vertical-align: top;
143 | position: absolute;
144 | top: 0;
145 | }
146 | .tree-node-proxy {
147 | background-color: #ffffff;
148 | color: #000000;
149 | border-color: #95B8E7;
150 | }
151 | .tree-node-hover {
152 | background: #eaf2ff;
153 | color: #000000;
154 | }
155 | .tree-node-selected {
156 | background: #ffe48d;
157 | color: #000000;
158 | }
159 | .tree-node-hidden {
160 | display: none;
161 | }
162 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/validatebox.css:
--------------------------------------------------------------------------------
1 | .validatebox-invalid {
2 | border-color: #ffa8a8;
3 | background-color: #fff3f3;
4 | color: #000;
5 | }
6 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/default/window.css:
--------------------------------------------------------------------------------
1 | .window {
2 | overflow: hidden;
3 | padding: 5px;
4 | border-width: 1px;
5 | border-style: solid;
6 | }
7 | .window .window-header {
8 | background: transparent;
9 | padding: 0px 0px 6px 0px;
10 | }
11 | .window .window-body {
12 | border-width: 1px;
13 | border-style: solid;
14 | border-top-width: 0px;
15 | }
16 | .window .window-body-noheader {
17 | border-top-width: 1px;
18 | }
19 | .window .panel-body-nobottom {
20 | border-bottom-width: 0;
21 | }
22 | .window .window-header .panel-icon,
23 | .window .window-header .panel-tool {
24 | top: 50%;
25 | margin-top: -11px;
26 | }
27 | .window .window-header .panel-icon {
28 | left: 1px;
29 | }
30 | .window .window-header .panel-tool {
31 | right: 1px;
32 | }
33 | .window .window-header .panel-with-icon {
34 | padding-left: 18px;
35 | }
36 | .window-proxy {
37 | position: absolute;
38 | overflow: hidden;
39 | }
40 | .window-proxy-mask {
41 | position: absolute;
42 | filter: alpha(opacity=5);
43 | opacity: 0.05;
44 | }
45 | .window-mask {
46 | position: absolute;
47 | left: 0;
48 | top: 0;
49 | width: 100%;
50 | height: 100%;
51 | filter: alpha(opacity=40);
52 | opacity: 0.40;
53 | font-size: 1px;
54 | overflow: hidden;
55 | }
56 | .window,
57 | .window-shadow {
58 | position: absolute;
59 | -moz-border-radius: 5px 5px 5px 5px;
60 | -webkit-border-radius: 5px 5px 5px 5px;
61 | border-radius: 5px 5px 5px 5px;
62 | }
63 | .window-shadow {
64 | background: #ccc;
65 | -moz-box-shadow: 2px 2px 3px #cccccc;
66 | -webkit-box-shadow: 2px 2px 3px #cccccc;
67 | box-shadow: 2px 2px 3px #cccccc;
68 | filter: progid:DXImageTransform.Microsoft.Blur(pixelRadius=2,MakeShadow=false,ShadowOpacity=0.2);
69 | }
70 | .window,
71 | .window .window-body {
72 | border-color: #95B8E7;
73 | }
74 | .window {
75 | background-color: #E0ECFF;
76 | background: -webkit-linear-gradient(top,#EFF5FF 0,#E0ECFF 20%);
77 | background: -moz-linear-gradient(top,#EFF5FF 0,#E0ECFF 20%);
78 | background: -o-linear-gradient(top,#EFF5FF 0,#E0ECFF 20%);
79 | background: linear-gradient(to bottom,#EFF5FF 0,#E0ECFF 20%);
80 | background-repeat: repeat-x;
81 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#EFF5FF,endColorstr=#E0ECFF,GradientType=0);
82 | }
83 | .window-proxy {
84 | border: 1px dashed #95B8E7;
85 | }
86 | .window-proxy-mask,
87 | .window-mask {
88 | background: #ccc;
89 | }
90 | .window .panel-footer {
91 | border: 1px solid #95B8E7;
92 | position: relative;
93 | top: -1px;
94 | }
95 | .window-thinborder {
96 | padding: 0;
97 | }
98 | .window-thinborder .window-header {
99 | padding: 5px 5px 6px 5px;
100 | }
101 | .window-thinborder .window-body {
102 | border-width: 0px;
103 | }
104 | .window-thinborder .window-header .panel-icon,
105 | .window-thinborder .window-header .panel-tool {
106 | margin-top: -9px;
107 | margin-left: 5px;
108 | margin-right: 5px;
109 | }
110 | .window-noborder {
111 | border: 0;
112 | }
113 | .window.panel-hleft .window-header {
114 | padding: 0 6px 0 0;
115 | }
116 | .window.panel-hright .window-header {
117 | padding: 0 0 0 6px;
118 | }
119 | .window.panel-hleft>.panel-header .panel-title {
120 | top: auto;
121 | left: 16px;
122 | }
123 | .window.panel-hright>.panel-header .panel-title {
124 | top: auto;
125 | right: 16px;
126 | }
127 | .window.panel-hleft>.panel-header .panel-title-up,
128 | .window.panel-hright>.panel-header .panel-title-up {
129 | bottom: 0;
130 | }
131 | .window.panel-hleft .window-body {
132 | border-width: 1px 1px 1px 0;
133 | }
134 | .window.panel-hright .window-body {
135 | border-width: 1px 0 1px 1px;
136 | }
137 | .window.panel-hleft .window-header .panel-icon {
138 | top: 1px;
139 | margin-top: 0;
140 | left: 0;
141 | }
142 | .window.panel-hright .window-header .panel-icon {
143 | top: 1px;
144 | margin-top: 0;
145 | left: auto;
146 | right: 1px;
147 | }
148 | .window.panel-hleft .window-header .panel-tool,
149 | .window.panel-hright .window-header .panel-tool {
150 | margin-top: 0;
151 | top: auto;
152 | bottom: 1px;
153 | right: auto;
154 | margin-right: 0;
155 | left: 50%;
156 | margin-left: -11px;
157 | }
158 | .window.panel-hright .window-header .panel-tool {
159 | left: auto;
160 | right: 1px;
161 | }
162 | .window-thinborder.panel-hleft .window-header {
163 | padding: 5px 6px 5px 5px;
164 | }
165 | .window-thinborder.panel-hright .window-header {
166 | padding: 5px 5px 5px 6px;
167 | }
168 | .window-thinborder.panel-hleft>.panel-header .panel-title {
169 | left: 21px;
170 | }
171 | .window-thinborder.panel-hleft>.panel-header .panel-title-up,
172 | .window-thinborder.panel-hright>.panel-header .panel-title-up {
173 | bottom: 5px;
174 | }
175 | .window-thinborder.panel-hleft .window-header .panel-icon,
176 | .window-thinborder.panel-hright .window-header .panel-icon {
177 | margin-top: 5px;
178 | }
179 | .window-thinborder.panel-hleft .window-header .panel-tool,
180 | .window-thinborder.panel-hright .window-header .panel-tool {
181 | left: 16px;
182 | bottom: 5px;
183 | }
184 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icon.css:
--------------------------------------------------------------------------------
1 | .icon-blank{
2 | background:url('icons/blank.gif') no-repeat center center;
3 | }
4 | .icon-add{
5 | background:url('icons/edit_add.png') no-repeat center center;
6 | }
7 | .icon-edit{
8 | background:url('icons/pencil.png') no-repeat center center;
9 | }
10 | .icon-clear{
11 | background:url('icons/clear.png') no-repeat center center;
12 | }
13 | .icon-remove{
14 | background:url('icons/edit_remove.png') no-repeat center center;
15 | }
16 | .icon-save{
17 | background:url('icons/filesave.png') no-repeat center center;
18 | }
19 | .icon-cut{
20 | background:url('icons/cut.png') no-repeat center center;
21 | }
22 | .icon-ok{
23 | background:url('icons/ok.png') no-repeat center center;
24 | }
25 | .icon-no{
26 | background:url('icons/no.png') no-repeat center center;
27 | }
28 | .icon-cancel{
29 | background:url('icons/cancel.png') no-repeat center center;
30 | }
31 | .icon-reload{
32 | background:url('icons/reload.png') no-repeat center center;
33 | }
34 | .icon-search{
35 | background:url('icons/search.png') no-repeat center center;
36 | }
37 | .icon-print{
38 | background:url('icons/print.png') no-repeat center center;
39 | }
40 | .icon-help{
41 | background:url('icons/help.png') no-repeat center center;
42 | }
43 | .icon-undo{
44 | background:url('icons/undo.png') no-repeat center center;
45 | }
46 | .icon-redo{
47 | background:url('icons/redo.png') no-repeat center center;
48 | }
49 | .icon-back{
50 | background:url('icons/back.png') no-repeat center center;
51 | }
52 | .icon-sum{
53 | background:url('icons/sum.png') no-repeat center center;
54 | }
55 | .icon-tip{
56 | background:url('icons/tip.png') no-repeat center center;
57 | }
58 | .icon-filter{
59 | background:url('icons/filter.png') no-repeat center center;
60 | }
61 | .icon-man{
62 | background:url('icons/man.png') no-repeat center center;
63 | }
64 | .icon-lock{
65 | background:url('icons/lock.png') no-repeat center center;
66 | }
67 | .icon-more{
68 | background:url('icons/more.png') no-repeat center center;
69 | }
70 |
71 |
72 | .icon-mini-add{
73 | background:url('icons/mini_add.png') no-repeat center center;
74 | }
75 | .icon-mini-edit{
76 | background:url('icons/mini_edit.png') no-repeat center center;
77 | }
78 | .icon-mini-refresh{
79 | background:url('icons/mini_refresh.png') no-repeat center center;
80 | }
81 |
82 | .icon-large-picture{
83 | background:url('icons/large_picture.png') no-repeat center center;
84 | }
85 | .icon-large-clipart{
86 | background:url('icons/large_clipart.png') no-repeat center center;
87 | }
88 | .icon-large-shapes{
89 | background:url('icons/large_shapes.png') no-repeat center center;
90 | }
91 | .icon-large-smartart{
92 | background:url('icons/large_smartart.png') no-repeat center center;
93 | }
94 | .icon-large-chart{
95 | background:url('icons/large_chart.png') no-repeat center center;
96 | }
97 |
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/back.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/blank.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/blank.gif
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/cancel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/cancel.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/clear.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/clear.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/cut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/cut.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/edit_add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/edit_add.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/edit_remove.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/edit_remove.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/filesave.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/filesave.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/filter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/filter.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/help.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/help.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/large_chart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/large_chart.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/large_clipart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/large_clipart.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/large_picture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/large_picture.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/large_shapes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/large_shapes.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/large_smartart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/large_smartart.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/lock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/lock.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/man.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/man.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/mini_add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/mini_add.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/mini_edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/mini_edit.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/mini_refresh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/mini_refresh.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/more.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/more.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/no.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/no.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/ok.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/ok.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/pencil.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/pencil.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/print.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/print.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/redo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/redo.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/reload.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/reload.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/search.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/sum.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/sum.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/tip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/tip.png
--------------------------------------------------------------------------------
/public/jquery-easyui/themes/icons/undo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zengming00/go-server-js/3d4e2189093eb28d6efc54a64e830b4571c1d3d4/public/jquery-easyui/themes/icons/undo.png
--------------------------------------------------------------------------------
/session.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "crypto/rand"
5 | "encoding/base64"
6 | "io"
7 | "net/http"
8 | "net/url"
9 | "strconv"
10 | "sync"
11 | "time"
12 |
13 | "github.com/dop251/goja"
14 | )
15 |
16 | type Session struct {
17 | mLastTimeAccessed time.Time
18 | mValues map[string]interface{}
19 | }
20 |
21 | type SessionMgr struct {
22 | mCookieName string // 客户端cookie名称
23 | mLock sync.RWMutex // 互斥(保证线程安全)
24 | mMaxLifeTimeSec int64 // 垃圾回收时间(秒)
25 |
26 | mSessions map[string]*Session
27 | }
28 |
29 | func NewSessionMgr(cookieName string, maxLifeTimeSec int64) *SessionMgr {
30 | mgr := &SessionMgr{mCookieName: cookieName, mMaxLifeTimeSec: maxLifeTimeSec, mSessions: make(map[string]*Session)}
31 | go mgr.GC()
32 | return mgr
33 | }
34 |
35 | func (mgr *SessionMgr) StartSession(w http.ResponseWriter, r *http.Request) string {
36 | mgr.mLock.Lock()
37 | defer mgr.mLock.Unlock()
38 |
39 | var sessionID string
40 | cookie, err := r.Cookie(mgr.mCookieName)
41 | if err == nil {
42 | if session, ok := mgr.mSessions[cookie.Value]; ok {
43 | session.mLastTimeAccessed = time.Now()
44 | sessionID = cookie.Value
45 | }
46 | }
47 |
48 | if sessionID == "" {
49 | sessionID = url.QueryEscape(mgr.NewSessionID())
50 | session := &Session{mLastTimeAccessed: time.Now(), mValues: make(map[string]interface{})}
51 | mgr.mSessions[sessionID] = session
52 | }
53 |
54 | cookie = &http.Cookie{Name: mgr.mCookieName, Value: sessionID, Path: "/", HttpOnly: true, MaxAge: int(mgr.mMaxLifeTimeSec)}
55 | http.SetCookie(w, cookie)
56 | return sessionID
57 | }
58 |
59 | func (mgr *SessionMgr) EndSession(w http.ResponseWriter, r *http.Request) {
60 | cookie, err := r.Cookie(mgr.mCookieName)
61 | if err != nil || cookie.Value == "" {
62 | return
63 | }
64 | mgr.mLock.Lock()
65 | defer mgr.mLock.Unlock()
66 |
67 | delete(mgr.mSessions, cookie.Value)
68 |
69 | // 让浏览器cookie立刻过期
70 | cookie = &http.Cookie{Name: mgr.mCookieName, Path: "/", HttpOnly: true, MaxAge: -1}
71 | http.SetCookie(w, cookie)
72 | }
73 |
74 | func (mgr *SessionMgr) EndSessionByID(sessionID string) {
75 | mgr.mLock.Lock()
76 | defer mgr.mLock.Unlock()
77 |
78 | delete(mgr.mSessions, sessionID)
79 | }
80 |
81 | func (mgr *SessionMgr) SetSessionVal(sessionID string, key string, value interface{}) {
82 | mgr.mLock.Lock()
83 | defer mgr.mLock.Unlock()
84 |
85 | if session, ok := mgr.mSessions[sessionID]; ok {
86 | session.mValues[key] = value
87 | }
88 | }
89 |
90 | func (mgr *SessionMgr) GetSessionVal(sessionID string, key string) (interface{}, bool) {
91 | mgr.mLock.RLock()
92 | defer mgr.mLock.RUnlock()
93 |
94 | if session, ok := mgr.mSessions[sessionID]; ok {
95 | value, ok := session.mValues[key]
96 | return value, ok
97 | }
98 | return nil, false
99 | }
100 |
101 | func (mgr *SessionMgr) GetSessionIDList() []string {
102 | mgr.mLock.RLock()
103 | defer mgr.mLock.RUnlock()
104 |
105 | sessionIDList := make([]string, len(mgr.mSessions))
106 | i := 0
107 | for k := range mgr.mSessions {
108 | sessionIDList[i] = k
109 | i++
110 | }
111 | return sessionIDList
112 | }
113 |
114 | func (mgr *SessionMgr) GC() {
115 | for {
116 | <-time.After(time.Duration(mgr.mMaxLifeTimeSec) * time.Second)
117 | mgr.mLock.Lock()
118 | for sessionID, session := range mgr.mSessions {
119 | if session.mLastTimeAccessed.Unix()+mgr.mMaxLifeTimeSec < time.Now().Unix() {
120 | delete(mgr.mSessions, sessionID)
121 | }
122 | }
123 | mgr.mLock.Unlock()
124 | }
125 | }
126 |
127 | func (mgr *SessionMgr) NewSessionID() string {
128 | // todo 为了更加安全,sessionID应该考虑加上验证
129 | b := make([]byte, 32)
130 | if _, err := io.ReadFull(rand.Reader, b); err != nil {
131 | nano := time.Now().UnixNano()
132 | return strconv.FormatInt(nano, 10)
133 | }
134 | return base64.URLEncoding.EncodeToString(b)
135 | }
136 |
137 | /////////////////////////////////////////////////////////////////////////////////
138 |
139 | type _session struct {
140 | runtime *goja.Runtime
141 | sessionMgr *SessionMgr
142 | sessionID *string
143 | w http.ResponseWriter
144 | r *http.Request
145 | }
146 |
147 | func (This *_session) start(call goja.FunctionCall) goja.Value {
148 | sessionID := This.sessionMgr.StartSession(This.w, This.r)
149 | This.sessionID = &sessionID
150 | return nil
151 | }
152 |
153 | func (This *_session) end(call goja.FunctionCall) goja.Value {
154 | This.sessionMgr.EndSession(This.w, This.r)
155 | This.sessionID = nil
156 | return nil
157 | }
158 |
159 | func (This *_session) get(call goja.FunctionCall) goja.Value {
160 | if This.sessionID == nil {
161 | This.start(call)
162 | }
163 | key := call.Argument(0).String()
164 | if value, ok := This.sessionMgr.GetSessionVal(*This.sessionID, key); ok {
165 | return This.runtime.ToValue(value)
166 | }
167 | return goja.Null()
168 | }
169 |
170 | func (This *_session) set(call goja.FunctionCall) goja.Value {
171 | if This.sessionID == nil {
172 | This.start(call)
173 | }
174 | key := call.Argument(0).String()
175 | value := call.Argument(1).Export()
176 | if IsValidType(value) {
177 | This.sessionMgr.SetSessionVal(*This.sessionID, key, value)
178 | return nil
179 | }
180 | panic(This.runtime.NewTypeError("value type %T is not permitted", value))
181 | }
182 |
183 | func NewSession(runtime *goja.Runtime, sessionMgr *SessionMgr, w http.ResponseWriter, r *http.Request) *goja.Object {
184 | This := &_session{
185 | runtime: runtime,
186 | sessionMgr: sessionMgr,
187 | w: w,
188 | r: r,
189 | }
190 |
191 | o := runtime.NewObject()
192 | o.Set("start", This.start)
193 | o.Set("end", This.end)
194 | o.Set("get", This.get)
195 | o.Set("set", This.set)
196 | return o
197 | }
198 |
--------------------------------------------------------------------------------
/test/sql.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "database/sql"
5 | "encoding/json"
6 | "fmt"
7 | "reflect"
8 |
9 | "github.com/go-sql-driver/mysql"
10 | )
11 |
12 | func handErr(err error) {
13 | if err != nil {
14 | panic(err)
15 | }
16 | }
17 |
18 | func main() {
19 | // db, err := sql.Open("mysql", "root:root@/test?parseTime=true&loc="+url.QueryEscape("Asia/Shanghai"))
20 | db, err := sql.Open("mysql", "root:root@/test2")
21 | handErr(err)
22 | rows, err := db.Query("select * from users")
23 | handErr(err)
24 | defer rows.Close()
25 |
26 | cols, err := rows.Columns()
27 | handErr(err)
28 | ct, err := rows.ColumnTypes()
29 | handErr(err)
30 |
31 | arr := make([]interface{}, len(ct))
32 | for i, v := range ct {
33 | t := v.ScanType()
34 | v := reflect.New(t).Interface()
35 | arr[i] = v
36 | fmt.Println(cols[i], t)
37 | }
38 |
39 | for rows.Next() {
40 | err = rows.Scan(arr...)
41 | handErr(err)
42 |
43 | m := make(map[string]interface{})
44 | for i, col := range cols {
45 | if col == "template_info" || col == "state" {
46 | m[col] = ""
47 | continue
48 | }
49 | v := arr[i]
50 | switch vv := v.(type) {
51 | case *int32:
52 | m[col] = *vv
53 | case *sql.NullString:
54 | m[col] = *vv
55 | case *sql.NullBool:
56 | m[col] = *vv
57 | case *sql.NullFloat64:
58 | m[col] = *vv
59 | case *sql.NullInt64:
60 | m[col] = *vv
61 | case *sql.RawBytes:
62 | m[col] = string(*vv)
63 | case *mysql.NullTime:
64 | m[col] = *vv
65 | default:
66 | m[col] = vv
67 | panic("unknow type")
68 | }
69 | }
70 |
71 | if bts, err := json.MarshalIndent(m, "", " "); err != nil {
72 | panic(err)
73 | } else {
74 | fmt.Println(string(bts))
75 | }
76 | }
77 | err = rows.Err()
78 | handErr(err)
79 | }
80 |
--------------------------------------------------------------------------------