├── .gitignore ├── .vscode └── settings.json ├── chromedp └── main.go ├── editor ├── .gitignore ├── README.md ├── config-overrides.js ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── manifest.json │ ├── qmux.min.js │ ├── qrpc.min.js │ └── test.html ├── server │ ├── cmd │ │ └── daemon │ │ │ └── daemon.go │ ├── hierarchy │ │ ├── NodeA │ │ │ └── node.json │ │ ├── NodeB │ │ │ ├── Test │ │ │ │ └── node.json │ │ │ └── node.json │ │ ├── Server │ │ │ └── node.json │ │ └── node.json │ ├── manifold │ │ ├── daemon │ │ │ ├── daemon.go │ │ │ └── mwc.go │ │ ├── frontend │ │ │ └── frontend.go │ │ ├── manifold.go │ │ ├── manifold_test.go │ │ ├── reflect.go │ │ └── workspace │ │ │ └── workspace.go │ ├── repl │ │ └── repl.go │ └── workspace │ │ ├── delegates │ │ ├── bhecfajmvbaicpltnghg │ │ │ └── delegate.go │ │ ├── bhecffbmvbaicpltngi0 │ │ │ └── delegate.go │ │ └── delegates.go │ │ └── server.go ├── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── Hierarchy.js │ ├── Inspector.js │ ├── index.css │ ├── index.js │ └── util.js └── yarn.lock ├── electrond ├── Makefile ├── client │ ├── debug.go │ └── electrond │ │ └── electrond.go ├── demos │ ├── 1beepbounce │ │ └── main.go │ ├── 2clipdialog │ │ └── main.go │ ├── 3clipshortcut │ │ └── main.go │ └── 4menu │ │ └── main.go ├── dev ├── dist │ ├── schema │ │ ├── schema.js │ │ └── schema.js.map │ └── src │ │ └── main │ │ ├── api.js │ │ ├── api.js.map │ │ ├── main.js │ │ ├── main.js.map │ │ ├── rpc.js │ │ ├── rpc.js.map │ │ ├── util.js │ │ └── util.js.map ├── package.json ├── schema │ ├── docs │ │ ├── assets │ │ │ ├── css │ │ │ │ ├── main.css │ │ │ │ └── main.css.map │ │ │ ├── images │ │ │ │ ├── icons.png │ │ │ │ ├── icons@2x.png │ │ │ │ ├── widgets.png │ │ │ │ └── widgets@2x.png │ │ │ └── js │ │ │ │ ├── main.js │ │ │ │ └── search.js │ │ ├── classes │ │ │ ├── _schema_.accelerator.html │ │ │ ├── _schema_.browserwindow.html │ │ │ ├── _schema_.double.html │ │ │ ├── _schema_.electron.cpuusage.html │ │ │ ├── _schema_.electron.desktopcapturersource.html │ │ │ ├── _schema_.electron.display.html │ │ │ ├── _schema_.electron.filefilter.html │ │ │ ├── _schema_.electron.memoryinfo.html │ │ │ ├── _schema_.electron.menu.html │ │ │ ├── _schema_.electron.menuitem.html │ │ │ ├── _schema_.electron.nativeimage.html │ │ │ ├── _schema_.electron.point.html │ │ │ ├── _schema_.electron.processmetric.html │ │ │ ├── _schema_.electron.rectangle.html │ │ │ ├── _schema_.electron.shortcutdetails.html │ │ │ ├── _schema_.electron.size.html │ │ │ ├── _schema_.electron.tray.html │ │ │ ├── _schema_.electron.uploaddata.html │ │ │ ├── _schema_.float.html │ │ │ ├── _schema_.integer.html │ │ │ ├── _schema_.menuitemconstructoroptions.html │ │ │ ├── _schema_.protocol.html │ │ │ ├── _schema_.touchbaritem.html │ │ │ └── _schema_.webframe.html │ │ ├── globals.html │ │ ├── index.html │ │ └── modules │ │ │ ├── _schema_.electron.app.dock.html │ │ │ ├── _schema_.electron.app.html │ │ │ ├── _schema_.electron.clipboard.html │ │ │ ├── _schema_.electron.desktopcapturer.html │ │ │ ├── _schema_.electron.dialog.html │ │ │ ├── _schema_.electron.globalshortcut.html │ │ │ ├── _schema_.electron.html │ │ │ ├── _schema_.electron.powermonitor.html │ │ │ ├── _schema_.electron.process.html │ │ │ ├── _schema_.electron.process.versions.html │ │ │ ├── _schema_.electron.protocol.html │ │ │ ├── _schema_.electron.screen.html │ │ │ ├── _schema_.electron.shell.html │ │ │ └── _schema_.html │ ├── exclude │ │ ├── events │ │ ├── methods │ │ ├── params │ │ └── props │ ├── helpers.js │ ├── include │ │ ├── classes │ │ ├── metatypes │ │ ├── modules │ │ └── structs │ ├── lib │ │ ├── clientgen.go │ │ ├── clientheader.go │ │ └── tsgen.js │ ├── schema.json │ ├── schema.ts │ └── versions │ │ ├── 1.8.4.json │ │ ├── 3.0.0-beta.2.json │ │ └── latest.json ├── src │ └── main │ │ ├── main.ts │ │ ├── rpc.ts │ │ └── util.ts ├── sutil ├── tsconfig.json └── yarn.lock ├── go-apple ├── appkit │ └── AppKit.bridgesupport ├── bridgesupport │ └── bridgesupport.go └── foundation │ ├── Foundation.bridgesupport │ ├── classes.go │ ├── classes_gen.go │ ├── enums.go │ ├── enums_gen.go │ ├── foundation.go │ ├── functions.go │ ├── functions_gen.go │ ├── protocols.go │ ├── protocols_gen.go │ ├── structs.go │ └── structs_gen.go ├── go-less ├── less.min.js └── main.go ├── go-obs-websocket ├── demo │ └── demo.go └── obs.go ├── go-reflected ├── reflected.go └── reflected_test.go ├── go-vtemplate ├── _example │ └── main.go ├── goja │ └── goja.go ├── html │ └── html.go ├── parser │ ├── README.md │ ├── atom │ │ ├── atom.go │ │ ├── atom_test.go │ │ ├── gen.go │ │ ├── table.go │ │ └── table_test.go │ ├── charset │ │ ├── charset.go │ │ ├── charset_test.go │ │ └── testdata │ │ │ ├── HTTP-charset.html │ │ │ ├── HTTP-vs-UTF-8-BOM.html │ │ │ ├── HTTP-vs-meta-charset.html │ │ │ ├── HTTP-vs-meta-content.html │ │ │ ├── No-encoding-declaration.html │ │ │ ├── README │ │ │ ├── UTF-16BE-BOM.html │ │ │ ├── UTF-16LE-BOM.html │ │ │ ├── UTF-8-BOM-vs-meta-charset.html │ │ │ ├── UTF-8-BOM-vs-meta-content.html │ │ │ ├── meta-charset-attribute.html │ │ │ └── meta-content-attribute.html │ ├── const.go │ ├── doc.go │ ├── doctype.go │ ├── entity.go │ ├── entity_test.go │ ├── escape.go │ ├── escape_test.go │ ├── example_test.go │ ├── foreign.go │ ├── node.go │ ├── node_test.go │ ├── parse.go │ ├── parse_test.go │ ├── render.go │ ├── render_test.go │ ├── testdata │ │ ├── go │ │ │ └── template.dat │ │ ├── go1.html │ │ └── webkit │ │ │ ├── README │ │ │ ├── adoption01.dat │ │ │ ├── adoption02.dat │ │ │ ├── comments01.dat │ │ │ ├── doctype01.dat │ │ │ ├── entities01.dat │ │ │ ├── entities02.dat │ │ │ ├── html5test-com.dat │ │ │ ├── inbody01.dat │ │ │ ├── isindex.dat │ │ │ ├── pending-spec-changes-plain-text-unsafe.dat │ │ │ ├── pending-spec-changes.dat │ │ │ ├── plain-text-unsafe.dat │ │ │ ├── ruby.dat │ │ │ ├── scriptdata01.dat │ │ │ ├── scripted │ │ │ ├── adoption01.dat │ │ │ └── webkit01.dat │ │ │ ├── tables01.dat │ │ │ ├── template.dat │ │ │ ├── tests1.dat │ │ │ ├── tests10.dat │ │ │ ├── tests11.dat │ │ │ ├── tests12.dat │ │ │ ├── tests14.dat │ │ │ ├── tests15.dat │ │ │ ├── tests16.dat │ │ │ ├── tests17.dat │ │ │ ├── tests18.dat │ │ │ ├── tests19.dat │ │ │ ├── tests2.dat │ │ │ ├── tests20.dat │ │ │ ├── tests21.dat │ │ │ ├── tests22.dat │ │ │ ├── tests23.dat │ │ │ ├── tests24.dat │ │ │ ├── tests25.dat │ │ │ ├── tests26.dat │ │ │ ├── tests3.dat │ │ │ ├── tests4.dat │ │ │ ├── tests5.dat │ │ │ ├── tests6.dat │ │ │ ├── tests7.dat │ │ │ ├── tests8.dat │ │ │ ├── tests9.dat │ │ │ ├── tests_innerHTML_1.dat │ │ │ ├── tricky01.dat │ │ │ ├── webkit01.dat │ │ │ └── webkit02.dat │ ├── token.go │ └── token_test.go ├── vecty │ └── vecty.go └── vtemplate.go ├── go-webui └── webui.go ├── goth └── goth.go ├── libmux ├── Makefile ├── _examples │ ├── websocket-server.go │ └── websocket.go ├── libmux.go ├── libmux.h ├── mux │ ├── api.go │ ├── muxado.go │ ├── qmux.go │ ├── quic.go │ ├── ssh.go │ ├── tcp.go │ └── websocket.go └── node │ ├── README.md │ ├── _debug.js │ ├── _demo.js │ ├── libmux.js │ ├── libmux.ts │ ├── package.json │ └── yarn.lock ├── pkg └── supervisor │ ├── README.md │ ├── _example │ ├── example.go │ └── plugins │ │ ├── counter │ │ ├── counter.go │ │ └── date │ ├── supervisor.go │ └── supervisor_test.go ├── qbus ├── hooks │ └── change ├── modules │ ├── demo │ ├── demo.go │ ├── demo.js │ ├── demo.py │ └── package-lock.json └── qbus.go ├── qc └── qc.go ├── qmux ├── SPEC.md ├── node │ ├── Makefile │ ├── demos │ │ ├── browser-client.html │ │ ├── browser-server.js │ │ ├── node-tcp.js │ │ └── node-ws.js │ ├── dist │ │ ├── browser │ │ │ └── qmux.min.js │ │ ├── qmux.js │ │ └── qmux_node.js │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── qmux.ts │ │ ├── qmux_browser.ts │ │ └── qmux_node.ts │ ├── tsconfig.browser.json │ └── tsconfig.node.json ├── qmux.go └── qmux_test.go ├── qrpc ├── _examples │ ├── bus │ │ └── bus.go │ ├── hijack │ │ └── hijack.go │ └── simple │ │ └── simple.go ├── api.go ├── bus │ └── bus.go ├── codec.go ├── demo │ ├── client.go │ └── demo.go ├── export.go ├── node │ ├── Makefile │ ├── _demo_libmux.js │ ├── _demo_mock.js │ ├── _demo_qmux.js │ ├── _dev.js │ ├── debug.jxa.js │ ├── demo │ │ └── browser-server.js │ ├── dist │ │ ├── browser │ │ │ ├── qrpc.js │ │ │ └── qrpc.min.js │ │ └── qrpc.js │ ├── package.json │ ├── server.go │ ├── src │ │ └── qrpc.ts │ ├── tsconfig.browser.json │ ├── tsconfig.node.json │ └── yarn.lock ├── objects.go └── qrpc.go ├── wasm-dockable ├── Makefile ├── assets │ ├── assets.go │ ├── assets_generated.go │ ├── assets_pregen.go │ └── generate.go ├── dev │ └── main.go ├── static │ ├── app.wasm │ ├── icons │ │ ├── brush-1.svg │ │ ├── brush.svg │ │ ├── crop.svg │ │ ├── dropper.svg │ │ ├── edit.svg │ │ ├── eraser.svg │ │ ├── hamburger.svg │ │ ├── magic-wand.svg │ │ ├── paint-bucket.svg │ │ ├── palette.svg │ │ ├── pen.svg │ │ ├── pencil.svg │ │ ├── picture.svg │ │ ├── scale.svg │ │ ├── spray.svg │ │ └── writing.svg │ ├── index.css │ ├── index.html │ └── wasm.js ├── ui │ ├── app.go │ ├── app.html │ ├── button.go │ ├── button.html │ ├── divider.go │ ├── divider.html │ ├── dragger.go │ ├── dragger.html │ ├── panel.go │ ├── panel.html │ ├── panelgroup.go │ ├── panelgroup.html │ ├── panelwrapper.go │ ├── panelwrapper.html │ ├── slider.go │ ├── slider.html │ ├── util.go │ ├── window.go │ ├── window.html │ ├── windowtab.go │ ├── windowtab.html │ ├── wrapper.go │ ├── wrapper.html │ ├── wrapperwrapped.go │ └── wrapperwrapped.html └── wasm │ └── main.go ├── wasm-manifold ├── Makefile ├── TODO ├── assets │ ├── assets.go │ ├── assets_generated.go │ ├── assets_pregen.go │ └── generate.go ├── design │ ├── demo.go │ └── design.txt ├── dev │ └── main.go ├── manifold │ ├── components.go │ ├── dev │ │ └── components.go │ └── node.go ├── static │ ├── app.wasm │ ├── index.html │ ├── jqPropertyGrid.js │ └── wasm.js ├── ui │ ├── app.go │ ├── app.html │ ├── button.go │ ├── button.html │ ├── inspector.go │ ├── inspector.html │ ├── propertyinput.go │ ├── propertyset.go │ ├── propertyset.html │ └── treeview.go └── wasm │ └── main.go └── wasm-markdown ├── Makefile ├── app ├── footer.go ├── footer.html ├── markdown.go ├── pageview.go └── pageview.html ├── assets ├── assets.go ├── assets_generated.go ├── assets_pregen.go └── generate.go ├── dev └── main.go ├── static ├── app.wasm ├── index.html └── wasm.js └── wasm └── main.go /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | youtube-export/data 3 | youtube-export/node_modules 4 | node_modules 5 | libmux/libmux.dylib 6 | typing 7 | yarn-error.log 8 | token.json 9 | state.json 10 | twitch.json -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "go.testOnSave": true, 3 | "go.testFlags": ["-v", "-cover", "-race"], 4 | "emeraldwalk.runonsave": { 5 | "commands": [ 6 | { 7 | "match": "counter.go", 8 | "cmd": "cd ${workspaceRoot}; go build -o supervisor/_example/plugins/counter ./supervisor/_example/plugins/..." 9 | }, 10 | { 11 | "match": "qmux/node/qmux.ts", 12 | "cmd": "cd ${workspaceRoot}/qmux/node; tsc --lib es2015 --inlineSourceMap qmux.ts" 13 | } 14 | ] 15 | }, 16 | "python.linting.pylintEnabled": false 17 | } -------------------------------------------------------------------------------- /chromedp/main.go: -------------------------------------------------------------------------------- 1 | // Command text is a chromedp example demonstrating how to extract text from a 2 | // specific element. 3 | package main 4 | 5 | import ( 6 | "context" 7 | "log" 8 | 9 | "github.com/chromedp/chromedp" 10 | "github.com/chromedp/chromedp/client" 11 | ) 12 | 13 | func main() { 14 | var err error 15 | 16 | // create context 17 | ctxt, cancel := context.WithCancel(context.Background()) 18 | defer cancel() 19 | 20 | // create chrome 21 | c, err := chromedp.New(ctxt, chromedp.WithTargets(client.New().WatchPageTargets(ctxt)), chromedp.WithLog(log.Printf)) 22 | if err != nil { 23 | log.Fatal(err) 24 | } 25 | 26 | // run task list 27 | var res string 28 | err = c.Run(ctxt, text(&res)) 29 | if err != nil { 30 | log.Fatal(err) 31 | } 32 | 33 | // shutdown chrome 34 | err = c.Shutdown(ctxt) 35 | if err != nil { 36 | log.Fatal(err) 37 | } 38 | 39 | // wait for chrome to finish 40 | err = c.Wait() 41 | if err != nil { 42 | log.Fatal(err) 43 | } 44 | 45 | log.Printf("overview: %s", res) 46 | } 47 | 48 | func text(res *string) chromedp.Tasks { 49 | return chromedp.Tasks{ 50 | chromedp.Navigate(`https://golang.org/pkg/time/`), 51 | chromedp.Text(`#pkg-overview`, res, chromedp.NodeVisible, chromedp.ByID), 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /editor/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /editor/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Web based editor 3 | 4 | Using tools: 5 | 6 | - React 7 | - Ant 8 | - Monaco 9 | - qrpc 10 | - Go -------------------------------------------------------------------------------- /editor/config-overrides.js: -------------------------------------------------------------------------------- 1 | const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin'); 2 | 3 | module.exports = function override(config, env) { 4 | if (!config.plugins) { 5 | config.plugins = []; 6 | } 7 | config.plugins.push( 8 | new MonacoWebpackPlugin() 9 | ); 10 | return config; 11 | } -------------------------------------------------------------------------------- /editor/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "editor", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "antd": "^3.11.6", 7 | "chai": "^4.2.0", 8 | "console-feed": "^2.8.5", 9 | "express-ws": "^4.0.0", 10 | "monaco-editor-webpack-plugin": "^1.7.0", 11 | "react": "^16.7.0", 12 | "react-dom": "^16.7.0", 13 | "react-monaco-editor": "^0.22.0", 14 | "react-panelgroup": "^1.0.7", 15 | "react-scripts": "2.1.2", 16 | "react-splitter-layout": "^3.0.1", 17 | "react-xterm": "^2.0.4", 18 | "underscore": "^1.9.1", 19 | "xterm": "^3.11.0" 20 | }, 21 | "scripts": { 22 | "start": "react-app-rewired start", 23 | "build": "react-scripts build", 24 | "test": "react-scripts test", 25 | "eject": "react-scripts eject" 26 | }, 27 | "eslintConfig": { 28 | "extends": "react-app" 29 | }, 30 | "browserslist": [ 31 | ">0.2%", 32 | "not dead", 33 | "not ie <= 11", 34 | "not op_mini all" 35 | ], 36 | "devDependencies": { 37 | "react-app-rewired": "^2.1.0" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /editor/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/prototypes/d9b2b4ba3a4f52a3c56bf57ed25d8b751cf9aa56/editor/public/favicon.ico -------------------------------------------------------------------------------- /editor/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 13 | 14 | 18 | 19 | 28 | React App 29 | 30 | 31 | 32 |
33 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /editor/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /editor/public/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 18 | 19 | Hello 20 | -------------------------------------------------------------------------------- /editor/server/cmd/daemon/daemon.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "github.com/progrium/prototypes/editor/server/manifold/daemon" 4 | 5 | func main() { 6 | daemon.Run() 7 | } 8 | -------------------------------------------------------------------------------- /editor/server/hierarchy/NodeA/node.json: -------------------------------------------------------------------------------- 1 | { 2 | "Children": null, 3 | "Active": true, 4 | "Name": "NodeA", 5 | "ID": "bhecfajmvbaicpltngh0", 6 | "Components": null 7 | } -------------------------------------------------------------------------------- /editor/server/hierarchy/NodeB/Test/node.json: -------------------------------------------------------------------------------- 1 | { 2 | "Children": null, 3 | "Active": true, 4 | "Name": "Test", 5 | "ID": "bhka7a3mvbaovdlj5kqg", 6 | "Components": null 7 | } -------------------------------------------------------------------------------- /editor/server/hierarchy/NodeB/node.json: -------------------------------------------------------------------------------- 1 | { 2 | "Children": [ 3 | "Test" 4 | ], 5 | "Active": true, 6 | "Name": "NodeB", 7 | "ID": "bhecfajmvbaicpltnghg", 8 | "Components": [ 9 | { 10 | "Data": { 11 | "Message": "From NodeB" 12 | }, 13 | "Delegate": "bhecfajmvbaicpltnghg", 14 | "Name": "Delegate" 15 | }, 16 | { 17 | "Data": { 18 | "Foobar": "", 19 | "RefTest": null 20 | }, 21 | "Delegate": "", 22 | "Name": "AnotherComponent" 23 | } 24 | ] 25 | } -------------------------------------------------------------------------------- /editor/server/hierarchy/node.json: -------------------------------------------------------------------------------- 1 | { 2 | "Children": [ 3 | "NodeA", 4 | "NodeB", 5 | "Server" 6 | ], 7 | "Active": true, 8 | "Name": "", 9 | "ID": "bhecfajmvbaicpltnggg", 10 | "Components": null 11 | } -------------------------------------------------------------------------------- /editor/server/manifold/daemon/mwc.go: -------------------------------------------------------------------------------- 1 | package daemon 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "sync" 7 | ) 8 | 9 | type writeMeta struct { 10 | closer chan int64 11 | bytes int64 12 | } 13 | 14 | func (wm writeMeta) close() { 15 | wm.closer <- wm.bytes 16 | } 17 | 18 | type MulticastWriteCloser struct { 19 | sync.Mutex 20 | writers map[io.Writer]writeMeta 21 | closed bool 22 | } 23 | 24 | func NewMulticastWriteCloser() *MulticastWriteCloser { 25 | return &MulticastWriteCloser{ 26 | writers: make(map[io.Writer]writeMeta), 27 | } 28 | } 29 | 30 | func (mw *MulticastWriteCloser) Write(p []byte) (n int, err error) { 31 | mw.Lock() 32 | defer mw.Unlock() 33 | if mw.closed { 34 | return 0, fmt.Errorf("closed") 35 | } 36 | n = len(p) 37 | for w, m := range mw.writers { 38 | n, err := w.Write(p) 39 | m.bytes += int64(n) 40 | if err != nil { 41 | m.close() 42 | delete(mw.writers, w) 43 | } 44 | } 45 | return 46 | } 47 | 48 | func (mw *MulticastWriteCloser) Close() error { 49 | mw.Lock() 50 | defer mw.Unlock() 51 | for _, m := range mw.writers { 52 | m.close() 53 | } 54 | mw.writers = make(map[io.Writer]writeMeta) 55 | mw.closed = true 56 | return nil 57 | } 58 | 59 | func (mw *MulticastWriteCloser) WriteTo(w io.Writer) (n int64, err error) { 60 | mw.Lock() 61 | if mw.closed { 62 | mw.Unlock() 63 | return 0, fmt.Errorf("closed") 64 | } 65 | if _, exists := mw.writers[w]; !exists { 66 | mw.writers[w] = writeMeta{make(chan int64), 0} 67 | } 68 | m := mw.writers[w] 69 | mw.Unlock() 70 | // TODO: error? 71 | return <-m.closer, nil 72 | } 73 | 74 | func (mw *MulticastWriteCloser) Count() int { 75 | mw.Lock() 76 | defer mw.Unlock() 77 | return len(mw.writers) 78 | } 79 | -------------------------------------------------------------------------------- /editor/server/workspace/delegates/bhecfajmvbaicpltnghg/delegate.go: -------------------------------------------------------------------------------- 1 | package node 2 | 3 | import ( 4 | "io" 5 | 6 | "github.com/gliderlabs/ssh" 7 | "github.com/progrium/prototypes/editor/server/manifold" 8 | ) 9 | 10 | func init() { 11 | manifold.RegisterDelegate(&Delegate{}, "bhecfajmvbaicpltnghg") 12 | } 13 | 14 | 15 | type Delegate struct { 16 | Message string 17 | } 18 | 19 | func (d *Delegate) HandleSSH(sess ssh.Session) { 20 | io.WriteString(sess, d.Message+"\n") 21 | } 22 | -------------------------------------------------------------------------------- /editor/server/workspace/delegates/bhecffbmvbaicpltngi0/delegate.go: -------------------------------------------------------------------------------- 1 | package node 2 | 3 | import ( 4 | "io" 5 | "net/http" 6 | 7 | "github.com/gliderlabs/ssh" 8 | "github.com/gliderlabs/stdcom/web/auth" 9 | "github.com/progrium/prototypes/editor/server/manifold" 10 | ) 11 | 12 | func init() { 13 | manifold.RegisterDelegate(&Delegate{}, "bhecffbmvbaicpltngi0") 14 | } 15 | 16 | type Delegate struct { 17 | Message string 18 | Hello string 19 | Auth auth.Requestor `com:"singleton" json:"-"` 20 | } 21 | 22 | func (d *Delegate) HandleSSH(sess ssh.Session) { 23 | io.WriteString(sess, d.Message+"\n") 24 | } 25 | 26 | func (d *Delegate) MatchHTTP(r *http.Request) bool { 27 | return r.URL.Path == "/" 28 | } 29 | 30 | func (d *Delegate) ServeHTTP(w http.ResponseWriter, r *http.Request) { 31 | // user := d.Auth.CurrentUser(r) 32 | // if user == nil { 33 | // io.WriteString(w, d.Message) 34 | // } else { 35 | // io.WriteString(w, fmt.Sprintf("%#v", user)) 36 | // } 37 | io.WriteString(w, "") 38 | } 39 | -------------------------------------------------------------------------------- /editor/server/workspace/delegates/delegates.go: -------------------------------------------------------------------------------- 1 | package delegates 2 | import ( 3 | _ "github.com/progrium/prototypes/editor/server/workspace/delegates/bhecffbmvbaicpltngi0" 4 | _ "github.com/progrium/prototypes/editor/server/workspace/delegates/bhecfajmvbaicpltnghg" 5 | ) 6 | -------------------------------------------------------------------------------- /editor/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 40vmin; 8 | } 9 | 10 | .App-header { 11 | background-color: #282c34; 12 | min-height: 100vh; 13 | display: flex; 14 | flex-direction: column; 15 | align-items: center; 16 | justify-content: center; 17 | font-size: calc(10px + 2vmin); 18 | color: white; 19 | } 20 | 21 | .App-link { 22 | color: #61dafb; 23 | } 24 | 25 | @keyframes App-logo-spin { 26 | from { 27 | transform: rotate(0deg); 28 | } 29 | to { 30 | transform: rotate(360deg); 31 | } 32 | } 33 | 34 | .projects li { 35 | padding-left: 10px !important; 36 | padding-top: 8px !important; 37 | padding-bottom: 8px !important; 38 | height: 60px !important; 39 | margin-top: 0px !important; 40 | margin-bottom: 0px !important; 41 | } -------------------------------------------------------------------------------- /editor/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | ReactDOM.unmountComponentAtNode(div); 9 | }); 10 | -------------------------------------------------------------------------------- /editor/src/Hierarchy.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Row, Button, Col, Dropdown, Tree, Menu } from 'antd'; 3 | import {pathsToTree} from './util'; 4 | 5 | const DirectoryTree = Tree.DirectoryTree; 6 | const { TreeNode } = Tree; 7 | 8 | export function Hierarchy(props) { 9 | return ( 10 |
11 | 12 | 13 | 14 | 15 | 16 | 19 | 20 | {pathsToTree(props.hierarchy, props.nodePaths).map(convertNodeToTree)} 21 | 22 |
23 | ) 24 | } 25 | 26 | class HierarchyNode extends TreeNode { 27 | render() { 28 | var onClick = ({item, key, keyPath}) => { 29 | //console.log(key, this.props.eventKey); 30 | if (key === "delete") { 31 | window.rpc.call("deleteNode", this.props.eventKey); 32 | } 33 | if (key === "add") { 34 | let name = prompt("New Node"); 35 | window.rpc.call("appendNode", {"ID": this.props.eventKey, "Name": name}); 36 | } 37 | } 38 | const contextMenu = ( 39 | 40 | Add Node 41 | Delete 42 | 43 | ) 44 | return {super.render()}; 45 | } 46 | } 47 | 48 | function convertNodeToTree(node) { 49 | var isLeaf = node.children.length === 0; 50 | return 54 | 55 | {node.children.map((n) => { return convertNodeToTree(n) })} 56 | 57 | } 58 | 59 | 60 | -------------------------------------------------------------------------------- /editor/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 5 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 6 | sans-serif; 7 | -webkit-font-smoothing: antialiased; 8 | -moz-osx-font-smoothing: grayscale; 9 | } 10 | 11 | code { 12 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 13 | monospace; 14 | } 15 | 16 | .splitter-layout-vertical .layout-pane { 17 | height: 100%; 18 | } 19 | 20 | .ant-tabs-bar { 21 | margin-bottom: 0px !important; 22 | } 23 | 24 | .ant-tabs-content { 25 | height: 100%; 26 | } 27 | 28 | .ant-tabs { 29 | height: 100%; 30 | } 31 | 32 | .ant-collapse.embedded .ant-collapse-header { 33 | padding: 0px !important; 34 | font-size: smaller; 35 | } 36 | 37 | .ant-collapse.embedded .anticon { 38 | font-size: 8px !important; 39 | left: 0px !important; 40 | margin-left: -10px; 41 | } 42 | 43 | .ant-collapse.embedded .ant-collapse-item { 44 | border-bottom: 0px; 45 | } 46 | 47 | .embedded .ant-collapse-content-box { 48 | padding-right: 0px !important; 49 | } -------------------------------------------------------------------------------- /editor/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | 6 | ReactDOM.render(, document.getElementById('root')); 7 | -------------------------------------------------------------------------------- /editor/src/util.js: -------------------------------------------------------------------------------- 1 | import _ from 'underscore'; 2 | 3 | export function pathsToTree(paths, nodePaths) { 4 | var tree = []; 5 | 6 | // This example uses the underscore.js library. 7 | _.each(paths, function(path) { 8 | 9 | var pathParts = path.split('/'); 10 | pathParts.shift(); // Remove first blank element from the parts array. 11 | 12 | var currentLevel = tree; // initialize currentLevel to root 13 | var currentPath = ""; 14 | 15 | _.each(pathParts, function(part) { 16 | currentPath = currentPath+"/"+part; 17 | 18 | // check to see if the path already exists. 19 | var existingPath = _.findWhere(currentLevel, { 20 | name: part 21 | }); 22 | 23 | if (existingPath) { 24 | // The path to this item was already in the tree, so don't add it again. 25 | // Set the current level to this path's children 26 | currentLevel = existingPath.children; 27 | } else { 28 | var newPart = { 29 | name: part, 30 | path: currentPath, 31 | id: nodePaths[currentPath], 32 | children: [], 33 | } 34 | 35 | currentLevel.push(newPart); 36 | currentLevel = newPart.children; 37 | } 38 | }); 39 | }); 40 | 41 | return tree; 42 | } -------------------------------------------------------------------------------- /electrond/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: schema 2 | 3 | all: schema rpc client/types 4 | 5 | schema: schema/schema.json schema/schema.ts schema/docs 6 | 7 | schema/schema.json: 8 | ./sutil build > schema/schema.json 9 | 10 | schema/schema.ts: 11 | ./sutil ts > schema/schema.ts 12 | 13 | schema/docs: schema/schema.ts 14 | typedoc --out schema/docs schema 15 | 16 | client/types: schema/lib/clientgen.go 17 | mkdir -p client/electrond 18 | go run schema/lib/clientgen.go > client/electrond/electrond.go 19 | 20 | rpc: 21 | ./sutil rpc | tsfmt --stdin > src/main/rpc.ts -------------------------------------------------------------------------------- /electrond/client/debug.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | 6 | "github.com/progrium/prototypes/qrpc" 7 | 8 | "github.com/progrium/prototypes/electrond/client/electrond" 9 | ) 10 | 11 | const addr = "localhost:4242" 12 | 13 | func must(err error) { 14 | if err != nil { 15 | panic(err) 16 | } 17 | } 18 | 19 | func main() { 20 | api := qrpc.NewAPI() 21 | om := qrpc.NewObjectManager() 22 | om.Mount(api, "objects") 23 | 24 | electron, err := electrond.Dial(addr, api) 25 | if err != nil { 26 | panic(err) 27 | } 28 | 29 | flag.Parse() 30 | 31 | err = electron.Shell.Beep(nil) 32 | if err != nil { 33 | panic(err) 34 | } 35 | 36 | var icon qrpc.ObjectHandle 37 | must(electron.NativeImage.CreateFromPath(electrond.NativeImageCreateFromPathParams{ 38 | Path: "/Users/progrium/src/github.com/progrium/fluxbot/assets/Icon.png", 39 | }, &icon)) 40 | 41 | var tray qrpc.ObjectHandle 42 | must(electron.Call("Tray.make", electrond.TrayParams{ 43 | Image: icon, 44 | }, &tray)) 45 | 46 | var menu qrpc.ObjectHandle 47 | must(electron.Menu.BuildFromTemplate(electrond.MenuBuildFromTemplateParams{ 48 | Template: []*electrond.MenuItemConstructorOptions{ 49 | &electrond.MenuItemConstructorOptions{ 50 | Label: "Hello world", 51 | }, 52 | }, 53 | }, &menu)) 54 | 55 | must(electron.Call(tray.ObjectPath+"/setContextMenu", map[string]interface{}{ 56 | "menu": menu, 57 | }, nil)) 58 | 59 | electron.ServeAPI() 60 | 61 | // err = electron.App.SetBadgeCount(electrond.AppSetBadgeCountParams{2}, nil) 62 | // if err != nil { 63 | // panic(err) 64 | // } 65 | 66 | // err = electron.AppDock.Bounce(electrond.DockBounceParams{"critical"}, nil) 67 | // if err != nil { 68 | // panic(err) 69 | // } 70 | 71 | //fmt.Printf("resp: %#v\n", resp2) 72 | } 73 | -------------------------------------------------------------------------------- /electrond/demos/1beepbounce/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/progrium/prototypes/electrond/client/electrond" 5 | ) 6 | 7 | func must(err error) { 8 | if err != nil { 9 | panic(err) 10 | } 11 | } 12 | 13 | func main() { 14 | electron, err := electrond.Dial("localhost:4242", nil) 15 | must(err) 16 | 17 | must(electron.Shell.Beep(nil)) 18 | 19 | must(electron.AppDock.Bounce(electrond.DockBounceParams{Type: "critical"}, nil)) 20 | 21 | } 22 | -------------------------------------------------------------------------------- /electrond/demos/2clipdialog/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/progrium/prototypes/electrond/client/electrond" 7 | ) 8 | 9 | func must(err error) { 10 | if err != nil { 11 | panic(err) 12 | } 13 | } 14 | 15 | func main() { 16 | electron, err := electrond.Dial("localhost:4242", nil) 17 | must(err) 18 | 19 | var clipboard string 20 | must(electron.Clipboard.ReadText(electrond.ClipboardReadTextParams{}, &clipboard)) 21 | 22 | fmt.Println(clipboard) 23 | 24 | must(electron.Dialog.ShowMessageBox(electrond.DialogShowMessageBoxParams{ 25 | Options: electrond.DialogShowMessageBoxParamsOptions{ 26 | Message: clipboard, 27 | }, 28 | }, nil)) 29 | 30 | } 31 | -------------------------------------------------------------------------------- /electrond/demos/3clipshortcut/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | "github.com/progrium/prototypes/electrond/client/electrond" 8 | "github.com/progrium/prototypes/qrpc" 9 | ) 10 | 11 | func must(err error) { 12 | if err != nil { 13 | panic(err) 14 | } 15 | } 16 | 17 | func main() { 18 | api := qrpc.NewAPI() 19 | om := qrpc.NewObjectManager() 20 | om.Mount(api, "objects") 21 | 22 | electron, err := electrond.Dial("localhost:4242", api) 23 | must(err) 24 | 25 | must(electron.GlobalShortcut.Register(electrond.GlobalShortcutRegisterParams{ 26 | Accelerator: "CommandOrControl+Shift+T", 27 | Callback: om.Handle(func() { 28 | must(electron.Clipboard.WriteText(electrond.ClipboardWriteTextParams{ 29 | Text: fmt.Sprint(time.Now()), 30 | }, nil)) 31 | }), 32 | }, nil)) 33 | 34 | electron.ServeAPI() 35 | } 36 | -------------------------------------------------------------------------------- /electrond/demos/4menu/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/progrium/prototypes/qrpc" 5 | 6 | "github.com/progrium/prototypes/electrond/client/electrond" 7 | ) 8 | 9 | func must(err error) { 10 | if err != nil { 11 | panic(err) 12 | } 13 | } 14 | 15 | func objPtr(h qrpc.ObjectHandle) *qrpc.ObjectHandle { 16 | return &h 17 | } 18 | 19 | func main() { 20 | api := qrpc.NewAPI() 21 | om := qrpc.NewObjectManager() 22 | om.Mount(api, "objects") 23 | 24 | electron, err := electrond.Dial("localhost:4242", api) 25 | must(err) 26 | 27 | var icon qrpc.ObjectHandle 28 | must(electron.NativeImage.CreateFromPath(electrond.NativeImageCreateFromPathParams{ 29 | Path: "/Users/progrium/src/github.com/progrium/fluxbot/assets/Icon.png", 30 | }, &icon)) 31 | 32 | var tray qrpc.ObjectHandle 33 | must(electron.Call("Tray.make", electrond.TrayParams{ 34 | Image: icon, 35 | }, &tray)) 36 | 37 | var notify qrpc.ObjectHandle 38 | must(electron.Call("Notification.make", electrond.NotificationParams{ 39 | Options: electrond.NotificationParamsOptions{ 40 | Title: "Golang ATX", 41 | Body: "Hello world", 42 | }, 43 | }, ¬ify)) 44 | 45 | var menu qrpc.ObjectHandle 46 | must(electron.Menu.BuildFromTemplate(electrond.MenuBuildFromTemplateParams{ 47 | Template: []*electrond.MenuItemConstructorOptions{ 48 | &electrond.MenuItemConstructorOptions{ 49 | Label: "Hello world", 50 | Click: objPtr(om.Handle(func() { 51 | electron.Call(notify.ObjectPath+"/show", nil, nil) 52 | })), 53 | }, 54 | }, 55 | }, &menu)) 56 | 57 | must(electron.Call(tray.ObjectPath+"/setContextMenu", map[string]interface{}{ 58 | "menu": menu, 59 | }, nil)) 60 | 61 | electron.ServeAPI() 62 | } 63 | -------------------------------------------------------------------------------- /electrond/dev: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const { spawn, spawnSync } = require('child_process'); 4 | const fs = require("fs"); 5 | const ejs = require("ejs"); 6 | 7 | var electronDev = null; 8 | 9 | process.on("SIGINT", () => { 10 | if (electronDev) { 11 | spawnSync("kill", ["-9", "-"+electronDev.pid]); 12 | } 13 | }); 14 | 15 | 16 | 17 | (function() { 18 | console.log("Compiling TypeScript..."); 19 | var tsc = spawnSync('tsc'); 20 | console.log(tsc.stdout.toString('ascii')); 21 | console.log(tsc.stderr.toString('ascii')); 22 | if (tsc.status != 0) { 23 | return; 24 | } 25 | electronDev = spawn('./node_modules/.bin/electron', ['./dist/src/main/main.js']); 26 | electronDev.stdout.on('data', (data) => { 27 | console.log(data.toString().trimRight()); 28 | }); 29 | electronDev.stderr.on('data', (data) => { 30 | console.log(data.toString().trimRight()); 31 | }); 32 | electronDev.on('exit', (code) => { 33 | console.log(`Child exited with code ${code}`); 34 | }); 35 | })(); -------------------------------------------------------------------------------- /electrond/dist/src/main/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | return new (P || (P = Promise))(function (resolve, reject) { 4 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 5 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 6 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } 7 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 8 | }); 9 | }; 10 | Object.defineProperty(exports, "__esModule", { value: true }); 11 | const electron_1 = require("electron"); 12 | const qrpc = require("qrpc"); 13 | const libmux = require("libmux"); 14 | const rpc = require("./rpc"); 15 | let listener; 16 | function sleep(ms) { 17 | return new Promise(res => setTimeout(res, ms)); 18 | } 19 | electron_1.app.on("ready", () => __awaiter(this, void 0, void 0, function* () { 20 | var api = new qrpc.API(); 21 | var om = new qrpc.ObjectManager(); 22 | om.mount(api, "objects"); 23 | rpc.register(api, om); 24 | listener = yield libmux.ListenWebsocket("localhost:4242"); 25 | var server = new qrpc.Server(); 26 | console.log("serving..."); 27 | //loop() 28 | yield server.serve(listener, api); 29 | })); 30 | function loop() { 31 | return __awaiter(this, void 0, void 0, function* () { 32 | while (true) { 33 | console.log("ping"); 34 | yield sleep(3000); 35 | } 36 | }); 37 | } 38 | // Quit when all windows are closed. 39 | electron_1.app.on("window-all-closed", () => { 40 | // On OS X it is common for applications and their menu bar 41 | // to stay active until the user quits explicitly with Cmd + Q 42 | if (process.platform !== "darwin") { 43 | electron_1.app.quit(); 44 | } 45 | }); 46 | electron_1.app.on("before-quit", () => { 47 | }); 48 | //# sourceMappingURL=main.js.map -------------------------------------------------------------------------------- /electrond/dist/src/main/main.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"main.js","sourceRoot":"","sources":["../../../src/main/main.ts"],"names":[],"mappings":";;;;;;;;;;AACA,uCAA+C;AAC/C,6BAA6B;AAC7B,iCAAiC;AAEjC,6BAA6B;AAE7B,IAAI,QAAa,CAAC;AAElB,eAAe,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;AACjD,CAAC;AAED,cAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAS,EAAE;IACzB,IAAI,GAAG,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,IAAI,EAAE,GAAG,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;IAClC,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,SAAS,CAAC,CAAA;IACxB,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACtB,QAAQ,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC;IAC1D,IAAI,MAAM,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;IAC/B,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAC1B,QAAQ;IACR,MAAM,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;AACpC,CAAC,CAAA,CAAC,CAAC;AAEH;;QACE,OAAO,IAAI,EAAE;YACX,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;YACnB,MAAM,KAAK,CAAC,IAAI,CAAC,CAAA;SAClB;IACH,CAAC;CAAA;AAED,oCAAoC;AACpC,cAAG,CAAC,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;IAC/B,2DAA2D;IAC3D,8DAA8D;IAC9D,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE;QACjC,cAAG,CAAC,IAAI,EAAE,CAAC;KACZ;AACH,CAAC,CAAC,CAAC;AAEH,cAAG,CAAC,EAAE,CAAC,aAAa,EAAE,GAAG,EAAE;AAE3B,CAAC,CAAC,CAAC","sourcesContent":["import * as electron from \"electron\";\nimport { app, globalShortcut } from \"electron\";\nimport * as qrpc from \"qrpc\";\nimport * as libmux from \"libmux\";\n\nimport * as rpc from \"./rpc\";\n\nlet listener: any;\n\nfunction sleep(ms: number): Promise {\n return new Promise(res => setTimeout(res, ms));\n}\n\napp.on(\"ready\", async () => {\n var api = new qrpc.API();\n var om = new qrpc.ObjectManager();\n om.mount(api, \"objects\")\n rpc.register(api, om);\n listener = await libmux.ListenWebsocket(\"localhost:4242\");\n var server = new qrpc.Server();\n console.log(\"serving...\"); \n //loop()\n await server.serve(listener, api);\n});\n\nasync function loop() {\n while (true) {\n console.log(\"ping\")\n await sleep(3000)\n }\n}\n\n// Quit when all windows are closed.\napp.on(\"window-all-closed\", () => {\n // On OS X it is common for applications and their menu bar\n // to stay active until the user quits explicitly with Cmd + Q\n if (process.platform !== \"darwin\") {\n app.quit();\n }\n});\n\napp.on(\"before-quit\", () => {\n\n});\n"]} -------------------------------------------------------------------------------- /electrond/dist/src/main/util.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | function argX(arg) { 4 | if (arg == null) 5 | return null; 6 | switch (arg.constructor.name) { 7 | case "NativeImage": 8 | return arg.toDataURL(); 9 | default: 10 | return arg; 11 | } 12 | } 13 | exports.argX = argX; 14 | //# sourceMappingURL=util.js.map -------------------------------------------------------------------------------- /electrond/dist/src/main/util.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"util.js","sourceRoot":"","sources":["../../../src/main/util.ts"],"names":[],"mappings":";;AAAA,cAAqB,GAAQ;IACzB,IAAI,GAAG,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IAC7B,QAAQ,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE;QAC1B,KAAK,aAAa;YACd,OAAO,GAAG,CAAC,SAAS,EAAE,CAAC;QAC3B;YACI,OAAO,GAAG,CAAC;KAClB;AACL,CAAC;AARD,oBAQC","sourcesContent":["export function argX(arg: any): any {\n if (arg == null) return null;\n switch (arg.constructor.name) {\n case \"NativeImage\":\n return arg.toDataURL();\n default:\n return arg;\n }\n}"]} -------------------------------------------------------------------------------- /electrond/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "electrond", 3 | "version": "0.1.0", 4 | "devDependencies": { 5 | "ejs": "^2.6.1", 6 | "electron": "^3.0.0-beta.2", 7 | "electron-builder": "^20.20.4", 8 | "lodash": "^4.17.10", 9 | "tree-walk": "^0.4.0", 10 | "typescript": "^2.9.2" 11 | }, 12 | "build": { 13 | "appId": "electrond", 14 | "mac": { 15 | "category": "your.app.category.type" 16 | } 17 | }, 18 | "dependencies": { 19 | "ffi": "node-ffi/node-ffi" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /electrond/schema/docs/assets/images/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/prototypes/d9b2b4ba3a4f52a3c56bf57ed25d8b751cf9aa56/electrond/schema/docs/assets/images/icons.png -------------------------------------------------------------------------------- /electrond/schema/docs/assets/images/icons@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/prototypes/d9b2b4ba3a4f52a3c56bf57ed25d8b751cf9aa56/electrond/schema/docs/assets/images/icons@2x.png -------------------------------------------------------------------------------- /electrond/schema/docs/assets/images/widgets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/prototypes/d9b2b4ba3a4f52a3c56bf57ed25d8b751cf9aa56/electrond/schema/docs/assets/images/widgets.png -------------------------------------------------------------------------------- /electrond/schema/docs/assets/images/widgets@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/prototypes/d9b2b4ba3a4f52a3c56bf57ed25d8b751cf9aa56/electrond/schema/docs/assets/images/widgets@2x.png -------------------------------------------------------------------------------- /electrond/schema/exclude/events: -------------------------------------------------------------------------------- 1 | // internal use 2 | app.will-finish-launching 3 | app.window-all-closed 4 | app.new-window-for-tab 5 | app.ready 6 | app.session-created 7 | app.second-instance 8 | 9 | process.loaded 10 | 11 | // maybe later 12 | app.before-quit 13 | app.open-file 14 | app.open-url 15 | app.activate 16 | app.continue-activity 17 | app.will-continue-activity 18 | app.continue-activity-error 19 | app.activity-was-continued 20 | app.update-activity-state 21 | app.certificate-error 22 | app.select-client-certificate 23 | app.login 24 | app.gpu-process-crashed 25 | app.accessibility-support-changed 26 | app.web-contents-created 27 | app.browser-window-blur 28 | app.browser-window-focus 29 | app.browser-window-created -------------------------------------------------------------------------------- /electrond/schema/exclude/methods: -------------------------------------------------------------------------------- 1 | // temporary, complex params 2 | app.dock.setIcon 3 | app.dock.setMenu 4 | 5 | // internal 6 | app.whenReady 7 | app.exit 8 | app.relaunch 9 | app.isReady 10 | app.disableHardwareAcceleration 11 | app.disableDomainBlockingFor3DAPIs 12 | app.isInApplicationsFolder 13 | app.moveToApplicationsFolder 14 | app.makeSingleInstance 15 | app.releaseSingleInstance 16 | app.setAppUserModelId 17 | app.getAppMemoryInfo 18 | app.getLoginItemSettings 19 | app.setLoginItemSettings 20 | app.setAboutPanelOptions 21 | app.enableMixedSandbox 22 | app.setName 23 | app.getName 24 | app.setPath 25 | app.requestSingleInstanceLock 26 | app.hasSingleInstanceLock 27 | app.releaseSingleInstanceLock 28 | app.startAccessingSecurityScopedResource 29 | 30 | process.crash 31 | process.hang 32 | process.setFdLimit 33 | process.getIOCounters 34 | 35 | protocol.uninterceptProtocol 36 | protocol.interceptStreamProtocol 37 | protocol.interceptHttpProtocol 38 | protocol.interceptBufferProtocol 39 | protocol.interceptStringProtocol 40 | protocol.interceptFileProtocol 41 | protocol.registerServiceWorkerSchemes 42 | 43 | // maybe later 44 | app.setAsDefaultProtocolClient 45 | app.removeAsDefaultProtocolClient 46 | app.isDefaultProtocolClient 47 | app.setUserTasks 48 | app.getJumpListSettings 49 | app.setJumpList 50 | app.setUserActivity 51 | app.getCurrentActivityType 52 | app.invalidateCurrentActivity 53 | app.updateCurrentActivity 54 | app.importCertificate 55 | app.isUnityRunning 56 | app.isAccessibilitySupportEnabled 57 | app.setAccessibilitySupportEnabled 58 | app.addRecentDocument 59 | app.clearRecentDocuments 60 | 61 | clipboard.readFindText 62 | clipboard.writeFindText 63 | clipboard.write 64 | 65 | dialog.showCertificateTrustDialog 66 | 67 | globalShortcut.unregisterAll 68 | 69 | protocol.registerStreamProtocol 70 | protocol.registerBufferProtocol 71 | 72 | screen.screenToDipRect 73 | screen.dipToScreenRect 74 | 75 | // buggy properties on GPUFeatureStatus 76 | app.getGPUFeatureStatus 77 | 78 | // experimental 79 | clipboard.has 80 | clipboard.read 81 | clipboard.readBuffer 82 | clipboard.writeBuffer -------------------------------------------------------------------------------- /electrond/schema/exclude/params: -------------------------------------------------------------------------------- 1 | dialog.showOpenDialog.browserWindow 2 | dialog.showSaveDialog.browserWindow 3 | dialog.showMessageBox.browserWindow -------------------------------------------------------------------------------- /electrond/schema/exclude/props: -------------------------------------------------------------------------------- 1 | // internal use 2 | process.type 3 | process.traceProcessWarnings 4 | process.traceDeprecation 5 | process.throwDeprecation 6 | process.noDeprecation 7 | process.noAsar 8 | process.defaultApp 9 | 10 | app.commandLine 11 | app.isPackaged -------------------------------------------------------------------------------- /electrond/schema/include/classes: -------------------------------------------------------------------------------- 1 | Menu 2 | MenuItem 3 | NativeImage 4 | Tray 5 | Notification 6 | // temporary 7 | -------------------------------------------------------------------------------- /electrond/schema/include/metatypes: -------------------------------------------------------------------------------- 1 | Module 2 | Structure 3 | Class -------------------------------------------------------------------------------- /electrond/schema/include/modules: -------------------------------------------------------------------------------- 1 | app 2 | app.dock 3 | clipboard 4 | desktopCapturer 5 | dialog 6 | globalShortcut 7 | powerMonitor 8 | process 9 | protocol 10 | screen 11 | shell 12 | nativeImage -------------------------------------------------------------------------------- /electrond/schema/include/structs: -------------------------------------------------------------------------------- 1 | CPUUsage 2 | Display 3 | FileFilter 4 | Point 5 | ProcessMetric 6 | Rectangle 7 | ShortcutDetails 8 | Size 9 | MemoryInfo 10 | // temporary 11 | DesktopCapturerSource 12 | UploadData 13 | NotificationAction 14 | MenuItemConstructorOptions -------------------------------------------------------------------------------- /electrond/schema/lib/clientheader.go: -------------------------------------------------------------------------------- 1 | package electrond 2 | 3 | import ( 4 | "github.com/progrium/prototypes/libmux/mux" 5 | "github.com/progrium/prototypes/qrpc" 6 | ) 7 | 8 | func Dial(addr string, api qrpc.API) (*Client, error) { 9 | sess, err := mux.DialWebsocket(addr) 10 | if err != nil { 11 | return nil, err 12 | } 13 | return (&Client{ 14 | Client: &qrpc.Client{ 15 | Session: sess, 16 | API: api, 17 | }, 18 | }).setup(), nil 19 | } 20 | -------------------------------------------------------------------------------- /electrond/schema/lib/tsgen.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = class Generator { 3 | constructor() { 4 | this.stack = [] 5 | this.stmts = [] 6 | } 7 | 8 | decl(...args) { 9 | if (typeof args[args.length-1] == "function") { 10 | var blockFn = args.pop() 11 | this.stmts.push(`${args.join(" ")} {\n${this.block(blockFn)}\n}`) 12 | } else { 13 | var line = args.join(" ") 14 | var end = (line.startsWith("/") || line.endsWith("}")) ? "" : ";" 15 | this.stmts.push(line+end) 16 | } 17 | } 18 | 19 | inline() { 20 | var stmt = this.stmts.pop() 21 | return (stmt.endsWith(";")) ? stmt.slice(0, -1) : stmt 22 | } 23 | 24 | export() { 25 | this.decl("export", this.inline()) 26 | } 27 | 28 | async() { 29 | this.decl("async", this.inline()) 30 | } 31 | 32 | func(name, args, type, blockFn) { 33 | this.decl("function", `${name}${this.signature(args, type)}`, blockFn) 34 | } 35 | 36 | call(name, ...args) { 37 | this.decl(`${name}(${(args||[]).join(", ")})`) 38 | } 39 | 40 | comment(str) { 41 | this.decl(`// ${str}`) 42 | } 43 | 44 | commentBlock(str) { 45 | this.decl("/**\n * "+(str||"").split("\n").join("\n * ")+"\n */") 46 | } 47 | 48 | block(blockFn) { 49 | this.stack.push(this.stmts) 50 | this.stmts = [] 51 | blockFn(this) 52 | var blockStmts = this.stmts 53 | this.stmts = this.stack.pop() 54 | return blockStmts.join("\n") 55 | } 56 | 57 | signature(args, type) { 58 | return `(${(args||[]).join(", ")})${(type) ? `: ${type} ` : ""}` 59 | } 60 | 61 | str(v) { 62 | return `"${v}"` 63 | } 64 | 65 | arr(...args) { 66 | return `[${args.join(", ")}]` 67 | } 68 | 69 | idx(name, key) { 70 | return `${name}[${key}]` 71 | } 72 | 73 | chain(...args) { 74 | return args.join(".") 75 | } 76 | 77 | lambda(...args) { 78 | var async = "" 79 | if (args[0] === "async") { 80 | async = args.shift()+" " 81 | } 82 | var blockFn = args.pop() 83 | var type = args.pop() 84 | return `${async}${this.signature(args, type)} => {\n${this.block(blockFn)}\n}` 85 | } 86 | 87 | var(name, type, value) { 88 | return (value) ? `${name}: ${type} = ${value}` : `${name}: ${type}` 89 | } 90 | 91 | toString() { 92 | return this.stmts.join("\n") 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /electrond/schema/versions/latest.json: -------------------------------------------------------------------------------- 1 | 3.0.0-beta.2.json -------------------------------------------------------------------------------- /electrond/src/main/main.ts: -------------------------------------------------------------------------------- 1 | import * as electron from "electron"; 2 | import { app, globalShortcut } from "electron"; 3 | import * as qrpc from "qrpc"; 4 | import * as libmux from "libmux"; 5 | 6 | import * as rpc from "./rpc"; 7 | 8 | let listener: any; 9 | 10 | function sleep(ms: number): Promise { 11 | return new Promise(res => setTimeout(res, ms)); 12 | } 13 | 14 | app.on("ready", async () => { 15 | var api = new qrpc.API(); 16 | var om = new qrpc.ObjectManager(); 17 | om.mount(api, "objects") 18 | rpc.register(api, om); 19 | listener = await libmux.ListenWebsocket("localhost:4242"); 20 | var server = new qrpc.Server(); 21 | console.log("serving..."); 22 | //loop() 23 | await server.serve(listener, api); 24 | }); 25 | 26 | async function loop() { 27 | while (true) { 28 | console.log("ping") 29 | await sleep(3000) 30 | } 31 | } 32 | 33 | // Quit when all windows are closed. 34 | app.on("window-all-closed", () => { 35 | // On OS X it is common for applications and their menu bar 36 | // to stay active until the user quits explicitly with Cmd + Q 37 | if (process.platform !== "darwin") { 38 | app.quit(); 39 | } 40 | }); 41 | 42 | app.on("before-quit", () => { 43 | 44 | }); 45 | -------------------------------------------------------------------------------- /electrond/src/main/util.ts: -------------------------------------------------------------------------------- 1 | export function argX(arg: any): any { 2 | if (arg == null) return null; 3 | switch (arg.constructor.name) { 4 | case "NativeImage": 5 | return arg.toDataURL(); 6 | default: 7 | return arg; 8 | } 9 | } -------------------------------------------------------------------------------- /electrond/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "dist", 4 | 5 | "target": "es2015", 6 | "module": "commonjs", 7 | "moduleResolution": "node", 8 | 9 | "inlineSources": true, 10 | "sourceMap": true, 11 | 12 | "allowSyntheticDefaultImports": true, 13 | "experimentalDecorators": true, 14 | 15 | "newLine": "lf", 16 | 17 | "noEmitOnError": true, 18 | 19 | "strict": false, 20 | "noUnusedLocals": false, 21 | "noFallthroughCasesInSwitch": false, 22 | "noImplicitReturns": false 23 | } 24 | } -------------------------------------------------------------------------------- /go-apple/foundation/classes_gen.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "reflect" 8 | "regexp" 9 | "strings" 10 | 11 | "github.com/dave/jennifer/jen" 12 | "github.com/progrium/prototypes/go-apple/bridgesupport" 13 | ) 14 | 15 | func toID(ti bridgesupport.TypeInfo) string { 16 | switch ti.Kind() { 17 | case reflect.Struct: 18 | return strings.Trim(ti.Name, "_") 19 | default: 20 | return ti.String() 21 | } 22 | } 23 | 24 | var selectorRegex = regexp.MustCompile(`:[[:lower:]]`) 25 | 26 | func selectorToFuncName(s string) string { 27 | sel := selectorRegex.ReplaceAllStringFunc(s, func(ss string) string { 28 | return strings.Title(ss[1:]) 29 | }) 30 | return strings.TrimRight(strings.Title(sel), ":") 31 | } 32 | 33 | func main() { 34 | sigs, err := bridgesupport.LoadSignatures("./Foundation.bridgesupport") 35 | if err != nil { 36 | panic(err) 37 | } 38 | f := jen.NewFile("foundation") 39 | for _, c := range sigs.Classes { 40 | f.Type().Id(c.Name).Struct( 41 | jen.Qual("github.com/progrium/objc", "Object"), 42 | ) 43 | for _, m := range c.Methods { 44 | if !m.ClassMethod { 45 | continue 46 | } 47 | var args []jen.Code 48 | for i, arg := range m.Args { 49 | if arg.Type.Code == "" && arg.Type64 == nil { 50 | // TODO: handle 51 | goto skip 52 | } 53 | rt := arg.Type 54 | if arg.Type64 != nil { 55 | rt = *arg.Type64 56 | } 57 | varName := string(byte(97 + i)) 58 | args = append(args, jen.Id(varName).Id(toID(rt))) 59 | } 60 | if m.RetVal != nil { 61 | rt := m.RetVal.Type 62 | if m.RetVal.Type64 != nil { 63 | rt = *m.RetVal.Type64 64 | } 65 | f.Func().Id(selectorToFuncName(m.Selector)).Params(args...).Id(toID(rt)).Block() 66 | } else { 67 | f.Func().Id(selectorToFuncName(m.Selector)).Params(args...).Block() 68 | } 69 | skip: 70 | } 71 | } 72 | fmt.Printf("%#v", f) 73 | } 74 | -------------------------------------------------------------------------------- /go-apple/foundation/enums_gen.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "strconv" 8 | "strings" 9 | 10 | "github.com/dave/jennifer/jen" 11 | "github.com/progrium/prototypes/go-apple/bridgesupport" 12 | ) 13 | 14 | func main() { 15 | sigs, err := bridgesupport.LoadSignatures("./Foundation.bridgesupport") 16 | if err != nil { 17 | panic(err) 18 | } 19 | f := jen.NewFile("foundation") 20 | for _, s := range sigs.Enums { 21 | v := s.Value64 22 | if v == "" { 23 | v = s.Value 24 | } 25 | t := "int64" 26 | var val interface{} 27 | var err error 28 | if strings.Contains(v, ".") { 29 | t = "float64" 30 | if val, err = strconv.ParseFloat(v, 64); err != nil { 31 | fmt.Println(s.Name) 32 | panic(err) 33 | } 34 | } else { 35 | if val, err = strconv.ParseInt(v, 10, 64); err != nil { 36 | if val, err = strconv.ParseUint(v, 10, 64); err != nil { 37 | fmt.Println(s.Name) 38 | panic(err) 39 | } 40 | } 41 | } 42 | if s.Name == "NSTimeIntervalSince1970" { 43 | // otherwise Lit will turn it into 9.783072e+08.0 44 | f.Const().Id(s.Name).Id(t).Op("=").Id(v) 45 | } else { 46 | f.Const().Id(s.Name).Id(t).Op("=").Lit(val) 47 | } 48 | 49 | } 50 | fmt.Printf("%#v", f) 51 | } 52 | -------------------------------------------------------------------------------- /go-apple/foundation/foundation.go: -------------------------------------------------------------------------------- 1 | //go:generate sh -c "go run structs_gen.go > structs.go" 2 | //go:generate sh -c "go run enums_gen.go > enums.go" 3 | //go:generate sh -c "go run functions_gen.go > functions.go" 4 | //go:generate sh -c "go run classes_gen.go > classes.go" 5 | //go:generate sh -c "go run protocols_gen.go > protocols.go" 6 | package foundation 7 | -------------------------------------------------------------------------------- /go-apple/foundation/functions_gen.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "reflect" 8 | "strings" 9 | 10 | "github.com/dave/jennifer/jen" 11 | "github.com/progrium/prototypes/go-apple/bridgesupport" 12 | ) 13 | 14 | func toID(ti bridgesupport.TypeInfo) string { 15 | switch ti.Kind() { 16 | case reflect.Struct: 17 | return strings.Trim(ti.Name, "_") 18 | default: 19 | return ti.String() 20 | } 21 | } 22 | 23 | func main() { 24 | sigs, err := bridgesupport.LoadSignatures("./Foundation.bridgesupport") 25 | if err != nil { 26 | panic(err) 27 | } 28 | f := jen.NewFile("foundation") 29 | for _, fn := range sigs.Functions { 30 | if fn.Inline { 31 | continue 32 | } 33 | var args []jen.Code 34 | for i, arg := range fn.Args { 35 | rt := arg.Type 36 | if arg.Type64 != nil { 37 | rt = *arg.Type64 38 | } 39 | varName := string(byte(97 + i)) 40 | args = append(args, jen.Id(varName).Id(toID(rt))) 41 | } 42 | if fn.RetVal != nil { 43 | rt := fn.RetVal.Type 44 | if fn.RetVal.Type64 != nil { 45 | rt = *fn.RetVal.Type64 46 | } 47 | f.Func().Id(fn.Name).Params(args...).Id(toID(rt)).Block() 48 | } else { 49 | f.Func().Id(fn.Name).Params(args...).Block() 50 | } 51 | 52 | } 53 | fmt.Printf("%#v", f) 54 | } 55 | -------------------------------------------------------------------------------- /go-apple/foundation/protocols_gen.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | 8 | "github.com/dave/jennifer/jen" 9 | "github.com/progrium/prototypes/go-apple/bridgesupport" 10 | ) 11 | 12 | func main() { 13 | sigs, err := bridgesupport.LoadSignatures("./Foundation.bridgesupport") 14 | if err != nil { 15 | panic(err) 16 | } 17 | f := jen.NewFile("foundation") 18 | for _, p := range sigs.InformalProtocols { 19 | f.Type().Id(p.Name).Interface() 20 | } 21 | fmt.Printf("%#v", f) 22 | } 23 | -------------------------------------------------------------------------------- /go-apple/foundation/structs.go: -------------------------------------------------------------------------------- 1 | package foundation 2 | 3 | type NSAffineTransformStruct struct { 4 | M11 float32 5 | M12 float32 6 | M21 float32 7 | M22 float32 8 | TX float32 9 | TY float32 10 | } 11 | type NSDecimal struct { 12 | _exponent int32 13 | _length uint32 14 | _isNegative uint32 15 | _isCompact uint32 16 | _reserved uint32 17 | } 18 | type NSEdgeInsets struct { 19 | Top float32 20 | Left float32 21 | Bottom float32 22 | Right float32 23 | } 24 | type NSFastEnumerationState struct { 25 | State uint32 26 | ItemsPtr uintptr 27 | MutationsPtr uintptr 28 | Extra slice 29 | } 30 | type NSHashEnumerator struct { 31 | _pi uint32 32 | _si uint32 33 | _bs uintptr 34 | } 35 | type NSHashTableCallBacks struct { 36 | Hash uintptr 37 | IsEqual uintptr 38 | Retain uintptr 39 | Release uintptr 40 | Describe uintptr 41 | } 42 | type NSMapEnumerator struct { 43 | _pi uint32 44 | _si uint32 45 | _bs uintptr 46 | } 47 | type NSMapTableKeyCallBacks struct { 48 | Hash uintptr 49 | IsEqual uintptr 50 | Retain uintptr 51 | Release uintptr 52 | Describe uintptr 53 | } 54 | type NSMapTableValueCallBacks struct { 55 | Retain uintptr 56 | Release uintptr 57 | Describe uintptr 58 | } 59 | type NSOperatingSystemVersion struct { 60 | MajorVersion int32 61 | MinorVersion int32 62 | PatchVersion int32 63 | } 64 | type NSPoint struct { 65 | X float32 66 | Y float32 67 | } 68 | type NSPointArray struct { 69 | X float32 70 | Y float32 71 | } 72 | type NSPointPointer struct { 73 | X float32 74 | Y float32 75 | } 76 | type NSRange struct { 77 | Location uint32 78 | Length uint32 79 | } 80 | type NSRangePointer struct { 81 | Location uint32 82 | Length uint32 83 | } 84 | type NSRect struct { 85 | Origin NSPoint 86 | Size NSSize 87 | } 88 | type NSRectArray struct { 89 | Origin NSPoint 90 | Size NSSize 91 | } 92 | type NSRectPointer struct { 93 | Origin NSPoint 94 | Size NSSize 95 | } 96 | type NSSize struct { 97 | Width float32 98 | Height float32 99 | } 100 | type NSSizeArray struct { 101 | Width float32 102 | Height float32 103 | } 104 | type NSSizePointer struct { 105 | Width float32 106 | Height float32 107 | } 108 | type NSSwappedDouble struct { 109 | V uint64 110 | } 111 | type NSSwappedFloat struct { 112 | V uint32 113 | } 114 | -------------------------------------------------------------------------------- /go-apple/foundation/structs_gen.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "reflect" 8 | "strings" 9 | 10 | "github.com/dave/jennifer/jen" 11 | "github.com/progrium/prototypes/go-apple/bridgesupport" 12 | ) 13 | 14 | func main() { 15 | sigs, err := bridgesupport.LoadSignatures("./Foundation.bridgesupport") 16 | if err != nil { 17 | panic(err) 18 | } 19 | f := jen.NewFile("foundation") 20 | for _, s := range sigs.Structs { 21 | var fields []jen.Code 22 | for i, f := range s.Type.Names { 23 | t := s.Type.Types[i].String() 24 | if s.Type.Types[i].Kind() == reflect.Struct { 25 | t = strings.Trim(s.Type.Types[i].Name, "_") 26 | } 27 | fields = append(fields, jen.Id(strings.Title(f)).Id(t)) 28 | } 29 | f.Type().Id(s.Name).Struct(fields...) 30 | } 31 | fmt.Printf("%#v", f) 32 | } 33 | -------------------------------------------------------------------------------- /go-less/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io/ioutil" 7 | "log" 8 | 9 | "github.com/dop251/goja" 10 | "github.com/krpors/dom" 11 | ) 12 | 13 | func Uint8Array(call goja.ConstructorCall) *goja.Object { 14 | // call.This contains the newly created object as per http://www.ecma-international.org/ecma-262/5.1/index.html#sec-13.2.2 15 | // call.Arguments contain arguments passed to the function 16 | 17 | //call.This.Set("method", method) 18 | 19 | // If return value is a non-nil *Object, it will be used instead of call.This 20 | // This way it is possible to return a Go struct or a map converted 21 | // into goja.Value using runtime.ToValue(), however in this case 22 | // instanceof will not work as expected. 23 | return nil 24 | } 25 | 26 | func main() { 27 | d, err := ioutil.ReadFile("./less.min.js") 28 | if err != nil { 29 | log.Fatal(err) 30 | } 31 | builder := dom.NewParser(bytes.NewBufferString("")) 32 | doc, err := builder.Parse() 33 | if err != nil { 34 | panic(err) 35 | } 36 | vm := goja.New() 37 | var console = vm.NewObject() 38 | console.Set("log", fmt.Println) 39 | vm.Set("console", console) 40 | var window = vm.NewObject() 41 | window.Set("location", map[string]string{ 42 | "protocol": "http", 43 | }) 44 | var document = vm.NewObject() 45 | var currentScript = vm.NewObject() 46 | currentScript.Set("dataset", vm.NewObject()) 47 | document.Set("currentScript", currentScript) 48 | document.Set("getElementsByTagName", doc.GetElementsByTagName) 49 | document.Set("createElement", doc.CreateElement) 50 | document.Set("createTextNode", doc.CreateText) 51 | document.Set("appendChild", doc.AppendChild) 52 | window.Set("document", document) 53 | vm.Set("window", window) 54 | vm.Set("document", document) 55 | vm.Set("Uint8Array", Uint8Array) 56 | _, err = vm.RunString(string(d)) 57 | //_, err = vm.RunString(`console.log(window.document.getElementsByTagName("body")[0])`) 58 | if err != nil { 59 | panic(err) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /go-obs-websocket/demo/demo.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | 7 | "github.com/progrium/prototypes/go-obs-websocket" 8 | ) 9 | 10 | func fatal(err error) { 11 | if err != nil { 12 | log.Fatal(err) 13 | } 14 | } 15 | 16 | func main() { 17 | url := "ws://192.168.1.200:4444/" 18 | client, err := obs.DialWebsocket(url, "12345") 19 | fatal(err) 20 | defer client.Close() 21 | 22 | resp, err := client.Request("GetSceneList", nil) 23 | fatal(err) 24 | 25 | fmt.Println(resp) 26 | 27 | for event := range client.Events { 28 | fmt.Println(event) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /go-vtemplate/_example/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "os" 6 | 7 | vtemplate "github.com/progrium/prototypes/go-vtemplate" 8 | "github.com/progrium/prototypes/go-vtemplate/goja" 9 | "github.com/progrium/prototypes/go-vtemplate/html" 10 | ) 11 | 12 | type Person struct { 13 | Name string 14 | YOB int 15 | } 16 | 17 | func main() { 18 | data := map[string]interface{}{ 19 | "People": []Person{ 20 | { 21 | Name: "Jeff Lindsay", 22 | YOB: 1985, 23 | }, 24 | { 25 | Name: "Gary Oldman", 26 | YOB: 1958, 27 | }, 28 | }, 29 | } 30 | template := ` 31 |
    32 |
  • 33 | {{ Person.Name.split(" ")[0] }} is {{ new Date().getFullYear() - Person.YOB }}. 34 |
  • 35 |
` 36 | p := &vtemplate.Parser{ 37 | Directives: html.BuiltinDirectives(), 38 | Evaluator: goja.Evaluator(), 39 | } 40 | n, _ := p.Parse(bytes.NewBufferString(template), data) 41 | html.Render(os.Stdout, n) 42 | } 43 | -------------------------------------------------------------------------------- /go-vtemplate/goja/goja.go: -------------------------------------------------------------------------------- 1 | package goja 2 | 3 | import ( 4 | "github.com/dop251/goja" 5 | reflected "github.com/progrium/prototypes/go-reflected" 6 | vtemplate "github.com/progrium/prototypes/go-vtemplate" 7 | ) 8 | 9 | type evaluator struct { 10 | *goja.Runtime 11 | } 12 | 13 | func Evaluator() vtemplate.Evaluator { 14 | return &evaluator{ 15 | goja.New(), 16 | } 17 | } 18 | 19 | func (e *evaluator) Set(name string, value interface{}) { 20 | e.Runtime.Set(name, value) 21 | } 22 | func (e *evaluator) Unset(name string) { 23 | e.Runtime.Set(name, goja.Undefined()) 24 | } 25 | func (e *evaluator) Eval(exp string) (reflected.Value, error) { 26 | v, err := e.RunString(exp) 27 | if err != nil { 28 | return reflected.Undefined(), err 29 | } 30 | return reflected.ValueOf(v.Export()), nil 31 | } 32 | -------------------------------------------------------------------------------- /go-vtemplate/parser/README.md: -------------------------------------------------------------------------------- 1 | This is a fork of golang.org/x/net/html because it forces 2 | tags and attributes to lowercase and we don't want that. -------------------------------------------------------------------------------- /go-vtemplate/parser/atom/atom.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package atom provides integer codes (also known as atoms) for a fixed set of 6 | // frequently occurring HTML strings: tag names and attribute keys such as "p" 7 | // and "id". 8 | // 9 | // Sharing an atom's name between all elements with the same tag can result in 10 | // fewer string allocations when tokenizing and parsing HTML. Integer 11 | // comparisons are also generally faster than string comparisons. 12 | // 13 | // The value of an atom's particular code is not guaranteed to stay the same 14 | // between versions of this package. Neither is any ordering guaranteed: 15 | // whether atom.H1 < atom.H2 may also change. The codes are not guaranteed to 16 | // be dense. The only guarantees are that e.g. looking up "div" will yield 17 | // atom.Div, calling atom.Div.String will return "div", and atom.Div != 0. 18 | package atom // import "golang.org/x/net/html/atom" 19 | 20 | // Atom is an integer code for a string. The zero value maps to "". 21 | type Atom uint32 22 | 23 | // String returns the atom's name. 24 | func (a Atom) String() string { 25 | start := uint32(a >> 8) 26 | n := uint32(a & 0xff) 27 | if start+n > uint32(len(atomText)) { 28 | return "" 29 | } 30 | return atomText[start : start+n] 31 | } 32 | 33 | func (a Atom) string() string { 34 | return atomText[a>>8 : a>>8+a&0xff] 35 | } 36 | 37 | // fnv computes the FNV hash with an arbitrary starting value h. 38 | func fnv(h uint32, s []byte) uint32 { 39 | for i := range s { 40 | h ^= uint32(s[i]) 41 | h *= 16777619 42 | } 43 | return h 44 | } 45 | 46 | func match(s string, t []byte) bool { 47 | for i, c := range t { 48 | if s[i] != c { 49 | return false 50 | } 51 | } 52 | return true 53 | } 54 | 55 | // Lookup returns the atom whose name is s. It returns zero if there is no 56 | // such atom. The lookup is case sensitive. 57 | func Lookup(s []byte) Atom { 58 | if len(s) == 0 || len(s) > maxAtomLen { 59 | return 0 60 | } 61 | h := fnv(hash0, s) 62 | if a := table[h&uint32(len(table)-1)]; int(a&0xff) == len(s) && match(a.string(), s) { 63 | return a 64 | } 65 | if a := table[(h>>16)&uint32(len(table)-1)]; int(a&0xff) == len(s) && match(a.string(), s) { 66 | return a 67 | } 68 | return 0 69 | } 70 | 71 | // String returns a string whose contents are equal to s. In that sense, it is 72 | // equivalent to string(s) but may be more efficient. 73 | func String(s []byte) string { 74 | if a := Lookup(s); a != 0 { 75 | return a.String() 76 | } 77 | return string(s) 78 | } 79 | -------------------------------------------------------------------------------- /go-vtemplate/parser/atom/atom_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package atom 6 | 7 | import ( 8 | "sort" 9 | "testing" 10 | ) 11 | 12 | func TestKnown(t *testing.T) { 13 | for _, s := range testAtomList { 14 | if atom := Lookup([]byte(s)); atom.String() != s { 15 | t.Errorf("Lookup(%q) = %#x (%q)", s, uint32(atom), atom.String()) 16 | } 17 | } 18 | } 19 | 20 | func TestHits(t *testing.T) { 21 | for _, a := range table { 22 | if a == 0 { 23 | continue 24 | } 25 | got := Lookup([]byte(a.String())) 26 | if got != a { 27 | t.Errorf("Lookup(%q) = %#x, want %#x", a.String(), uint32(got), uint32(a)) 28 | } 29 | } 30 | } 31 | 32 | func TestMisses(t *testing.T) { 33 | testCases := []string{ 34 | "", 35 | "\x00", 36 | "\xff", 37 | "A", 38 | "DIV", 39 | "Div", 40 | "dIV", 41 | "aa", 42 | "a\x00", 43 | "ab", 44 | "abb", 45 | "abbr0", 46 | "abbr ", 47 | " abbr", 48 | " a", 49 | "acceptcharset", 50 | "acceptCharset", 51 | "accept_charset", 52 | "h0", 53 | "h1h2", 54 | "h7", 55 | "onClick", 56 | "λ", 57 | // The following string has the same hash (0xa1d7fab7) as "onmouseover". 58 | "\x00\x00\x00\x00\x00\x50\x18\xae\x38\xd0\xb7", 59 | } 60 | for _, tc := range testCases { 61 | got := Lookup([]byte(tc)) 62 | if got != 0 { 63 | t.Errorf("Lookup(%q): got %d, want 0", tc, got) 64 | } 65 | } 66 | } 67 | 68 | func TestForeignObject(t *testing.T) { 69 | const ( 70 | afo = Foreignobject 71 | afO = ForeignObject 72 | sfo = "foreignobject" 73 | sfO = "foreignObject" 74 | ) 75 | if got := Lookup([]byte(sfo)); got != afo { 76 | t.Errorf("Lookup(%q): got %#v, want %#v", sfo, got, afo) 77 | } 78 | if got := Lookup([]byte(sfO)); got != afO { 79 | t.Errorf("Lookup(%q): got %#v, want %#v", sfO, got, afO) 80 | } 81 | if got := afo.String(); got != sfo { 82 | t.Errorf("Atom(%#v).String(): got %q, want %q", afo, got, sfo) 83 | } 84 | if got := afO.String(); got != sfO { 85 | t.Errorf("Atom(%#v).String(): got %q, want %q", afO, got, sfO) 86 | } 87 | } 88 | 89 | func BenchmarkLookup(b *testing.B) { 90 | sortedTable := make([]string, 0, len(table)) 91 | for _, a := range table { 92 | if a != 0 { 93 | sortedTable = append(sortedTable, a.String()) 94 | } 95 | } 96 | sort.Strings(sortedTable) 97 | 98 | x := make([][]byte, 1000) 99 | for i := range x { 100 | x[i] = []byte(sortedTable[i%len(sortedTable)]) 101 | } 102 | 103 | b.ResetTimer() 104 | for i := 0; i < b.N; i++ { 105 | for _, s := range x { 106 | Lookup(s) 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /go-vtemplate/parser/charset/testdata/HTTP-charset.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | HTTP charset 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 15 | 16 | 17 |

HTTP charset

18 | 19 | 20 |
21 | 22 | 23 |
 
24 | 25 | 26 | 27 | 28 | 29 |
30 |

The character encoding of a page can be set using the HTTP header charset declaration.

31 |

The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector .test div.ÜÀÚ. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.

The only character encoding declaration for this HTML file is in the HTTP header, which sets the encoding to ISO 8859-15.

32 |
33 |
34 |
HTML5
35 |

the-input-byte-stream-001
Result summary & related tests
Detailed results for this test
Link to spec

36 |
Assumptions:
  • The default encoding for the browser you are testing is not set to ISO 8859-15.
  • 37 |
  • The test is read from a server that supports HTTP.
38 |
39 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /go-vtemplate/parser/charset/testdata/No-encoding-declaration.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | No encoding declaration 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 15 | 16 | 17 |

No encoding declaration

18 | 19 | 20 |
21 | 22 | 23 |
 
24 | 25 | 26 | 27 | 28 | 29 |
30 |

A page with no encoding information in HTTP, BOM, XML declaration or meta element will be treated as UTF-8.

31 |

The test on this page contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector .test div.ýäè. This matches the sequence of bytes above when they are interpreted as UTF-8. If the class name matches the selector then the test will pass.

32 |
33 |
34 |
HTML5
35 |

the-input-byte-stream-015
Result summary & related tests
Detailed results for this test
Link to spec

36 |
Assumptions:
  • The test is read from a server that supports HTTP.
37 |
38 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /go-vtemplate/parser/charset/testdata/README: -------------------------------------------------------------------------------- 1 | These test cases come from 2 | http://www.w3.org/International/tests/repository/html5/the-input-byte-stream/results-basics 3 | 4 | Distributed under both the W3C Test Suite License 5 | (http://www.w3.org/Consortium/Legal/2008/04-testsuite-license) 6 | and the W3C 3-clause BSD License 7 | (http://www.w3.org/Consortium/Legal/2008/03-bsd-license). 8 | To contribute to a W3C Test Suite, see the policies and contribution 9 | forms (http://www.w3.org/2004/10/27-testcases). 10 | -------------------------------------------------------------------------------- /go-vtemplate/parser/charset/testdata/UTF-16BE-BOM.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/prototypes/d9b2b4ba3a4f52a3c56bf57ed25d8b751cf9aa56/go-vtemplate/parser/charset/testdata/UTF-16BE-BOM.html -------------------------------------------------------------------------------- /go-vtemplate/parser/charset/testdata/UTF-16LE-BOM.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/progrium/prototypes/d9b2b4ba3a4f52a3c56bf57ed25d8b751cf9aa56/go-vtemplate/parser/charset/testdata/UTF-16LE-BOM.html -------------------------------------------------------------------------------- /go-vtemplate/parser/entity_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package html 6 | 7 | import ( 8 | "testing" 9 | "unicode/utf8" 10 | ) 11 | 12 | func TestEntityLength(t *testing.T) { 13 | // We verify that the length of UTF-8 encoding of each value is <= 1 + len(key). 14 | // The +1 comes from the leading "&". This property implies that the length of 15 | // unescaped text is <= the length of escaped text. 16 | for k, v := range entity { 17 | if 1+len(k) < utf8.RuneLen(v) { 18 | t.Error("escaped entity &" + k + " is shorter than its UTF-8 encoding " + string(v)) 19 | } 20 | if len(k) > longestEntityWithoutSemicolon && k[len(k)-1] != ';' { 21 | t.Errorf("entity name %s is %d characters, but longestEntityWithoutSemicolon=%d", k, len(k), longestEntityWithoutSemicolon) 22 | } 23 | } 24 | for k, v := range entity2 { 25 | if 1+len(k) < utf8.RuneLen(v[0])+utf8.RuneLen(v[1]) { 26 | t.Error("escaped entity &" + k + " is shorter than its UTF-8 encoding " + string(v[0]) + string(v[1])) 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /go-vtemplate/parser/escape_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package html 6 | 7 | import "testing" 8 | 9 | type unescapeTest struct { 10 | // A short description of the test case. 11 | desc string 12 | // The HTML text. 13 | html string 14 | // The unescaped text. 15 | unescaped string 16 | } 17 | 18 | var unescapeTests = []unescapeTest{ 19 | // Handle no entities. 20 | { 21 | "copy", 22 | "A\ttext\nstring", 23 | "A\ttext\nstring", 24 | }, 25 | // Handle simple named entities. 26 | { 27 | "simple", 28 | "& > <", 29 | "& > <", 30 | }, 31 | // Handle hitting the end of the string. 32 | { 33 | "stringEnd", 34 | "& &", 35 | "& &", 36 | }, 37 | // Handle entities with two codepoints. 38 | { 39 | "multiCodepoint", 40 | "text ⋛︀ blah", 41 | "text \u22db\ufe00 blah", 42 | }, 43 | // Handle decimal numeric entities. 44 | { 45 | "decimalEntity", 46 | "Delta = Δ ", 47 | "Delta = Δ ", 48 | }, 49 | // Handle hexadecimal numeric entities. 50 | { 51 | "hexadecimalEntity", 52 | "Lambda = λ = λ ", 53 | "Lambda = λ = λ ", 54 | }, 55 | // Handle numeric early termination. 56 | { 57 | "numericEnds", 58 | "&# &#x €43 © = ©f = ©", 59 | "&# &#x €43 © = ©f = ©", 60 | }, 61 | // Handle numeric ISO-8859-1 entity replacements. 62 | { 63 | "numericReplacements", 64 | "Footnote‡", 65 | "Footnote‡", 66 | }, 67 | } 68 | 69 | func TestUnescape(t *testing.T) { 70 | for _, tt := range unescapeTests { 71 | unescaped := UnescapeString(tt.html) 72 | if unescaped != tt.unescaped { 73 | t.Errorf("TestUnescape %s: want %q, got %q", tt.desc, tt.unescaped, unescaped) 74 | } 75 | } 76 | } 77 | 78 | func TestUnescapeEscape(t *testing.T) { 79 | ss := []string{ 80 | ``, 81 | `abc def`, 82 | `a & b`, 83 | `a&b`, 84 | `a & b`, 85 | `"`, 86 | `"`, 87 | `"<&>"`, 88 | `"<&>"`, 89 | `3&5==1 && 0<1, "0<1", a+acute=á`, 90 | `The special characters are: <, >, &, ' and "`, 91 | } 92 | for _, s := range ss { 93 | if got := UnescapeString(EscapeString(s)); got != s { 94 | t.Errorf("got %q want %q", got, s) 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /go-vtemplate/parser/example_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This example demonstrates parsing HTML data and walking the resulting tree. 6 | package html_test 7 | 8 | import ( 9 | "fmt" 10 | "log" 11 | "strings" 12 | 13 | "golang.org/x/net/html" 14 | ) 15 | 16 | func ExampleParse() { 17 | s := `

Links:

` 18 | doc, err := html.Parse(strings.NewReader(s)) 19 | if err != nil { 20 | log.Fatal(err) 21 | } 22 | var f func(*html.Node) 23 | f = func(n *html.Node) { 24 | if n.Type == html.ElementNode && n.Data == "a" { 25 | for _, a := range n.Attr { 26 | if a.Key == "href" { 27 | fmt.Println(a.Val) 28 | break 29 | } 30 | } 31 | } 32 | for c := n.FirstChild; c != nil; c = c.NextSibling { 33 | f(c) 34 | } 35 | } 36 | f(doc) 37 | // Output: 38 | // foo 39 | // /bar/baz 40 | } 41 | -------------------------------------------------------------------------------- /go-vtemplate/parser/testdata/go/template.dat: -------------------------------------------------------------------------------- 1 | #data 2 | 3 | #errors 4 | #document 5 | | 6 | | 7 | | 8 | |