mirror of
https://github.com/antos-rde/antosdk-apps.git
synced 2024-11-15 09:58:21 +01:00
first release of libantosdk
This commit is contained in:
parent
211753bfdc
commit
90864aabb7
@ -1 +1,35 @@
|
|||||||
(function(){var t;(t=class extends this.OS.application.BaseApplication{constructor(t){super("About",t)}main(){var t,n;return t=this,this.container=this.find("container"),(n="https://raw.githubusercontent.com/lxsang/antos/master/README.md").asFileHandle().read().then((function(n){var i;return i=new showdown.Converter,$(t.container).html(i.makeHtml(n))})).catch(()=>this.notify(__("Unable to read: {0}",n))),this.find("btnclose").onbtclick=()=>this.quit()}}).singleton=!0,t.dependencies=["os://scripts/showdown.min.js"],this.OS.register("About",t)}).call(this);
|
|
||||||
|
(function() {
|
||||||
|
var About;
|
||||||
|
|
||||||
|
About = class About extends this.OS.application.BaseApplication {
|
||||||
|
constructor(args) {
|
||||||
|
super("About", args);
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
var me, path;
|
||||||
|
me = this;
|
||||||
|
this.container = this.find("container");
|
||||||
|
path = "https://raw.githubusercontent.com/lxsang/antos/master/README.md";
|
||||||
|
path.asFileHandle().read().then(function(txt) {
|
||||||
|
var converter;
|
||||||
|
converter = new showdown.Converter();
|
||||||
|
return ($(me.container)).html(converter.makeHtml(txt));
|
||||||
|
}).catch(() => {
|
||||||
|
return this.notify(__("Unable to read: {0}", path));
|
||||||
|
});
|
||||||
|
return this.find("btnclose").onbtclick = () => {
|
||||||
|
return this.quit();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
About.singleton = true;
|
||||||
|
|
||||||
|
About.dependencies = ["os://scripts/showdown.min.js"];
|
||||||
|
|
||||||
|
this.OS.register("About", About);
|
||||||
|
|
||||||
|
}).call(this);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
"name": "About",
|
"name": "About",
|
||||||
"css": ["css/main.css"],
|
"css": ["css/main.css"],
|
||||||
"javascripts": [],
|
"javascripts": [],
|
||||||
|
"ts": [],
|
||||||
"coffees": ["coffees/main.coffee"],
|
"coffees": ["coffees/main.coffee"],
|
||||||
"copies": ["assets/scheme.html", "package.json", "README.md"]
|
"copies": ["assets/scheme.html", "package.json", "README.md"]
|
||||||
}
|
}
|
@ -1,3 +1,38 @@
|
|||||||
<afx-app-window apptitle="Antedit" width="500" height="400" data-id="Antedit">
|
<afx-app-window apptitle="Antos Editor" width="600" height="400" data-id="antedit">
|
||||||
<afx-hbox ></afx-hbox>
|
<afx-vbox>
|
||||||
|
<afx-hbox data-id="wrapper">
|
||||||
|
<afx-vbox data-width = "155" min-width="155" data-id = "sidebar">
|
||||||
|
<div data-height="10"></div>
|
||||||
|
<afx-file-view chdir="false" data-id = "fileview" view="tree" status = "false">
|
||||||
|
</afx-file-view>
|
||||||
|
</afx-vbox>
|
||||||
|
<afx-resizer data-width = "3" ></afx-resizer>
|
||||||
|
<afx-vbox>
|
||||||
|
<afx-hbox>
|
||||||
|
<afx-vbox data-id="left-panel">
|
||||||
|
<afx-tab-bar closable="true" data-height="26" data-id = "left-tabbar"></afx-tab-bar>
|
||||||
|
<div data-id="left-editorarea"></div>
|
||||||
|
</afx-vbox>
|
||||||
|
<afx-resizer data-width="3"></afx-resizer>
|
||||||
|
<afx-vbox data-id="right-panel">
|
||||||
|
<afx-tab-bar closable="true" data-height="26" data-id = "right-tabbar"></afx-tab-bar>
|
||||||
|
<div data-id="right-editorarea"></div>
|
||||||
|
</afx-vbox>
|
||||||
|
</afx-hbox>
|
||||||
|
<afx-resizer data-height = "3" dir = "ve" attachnext = "true" ></afx-resizer>
|
||||||
|
<afx-tab-container data-id = "bottombar" data-height="150" min-height="150" tabbarheight= "22">
|
||||||
|
<afx-hbox tabname="__(Output)" iconclass = "fa fa-file-text" class = "bottom-tab-content">
|
||||||
|
<afx-button text = "" data-id="logger-clear" iconclass="fa fa-trash" data-width="21"></afx-button>
|
||||||
|
<div data-id="output-tab" iconclass = "fa fa-file-text" >
|
||||||
|
</div>
|
||||||
|
</afx-hbox>
|
||||||
|
</afx-tab-container>
|
||||||
|
</afx-vbox>
|
||||||
|
</afx-hbox>
|
||||||
|
<div data-height="20" data-id="statctn">
|
||||||
|
<afx-label text=" " data-id = "current-file-lbl" style="float:left;"></afx-label>
|
||||||
|
<afx-label data-id="langstat" style="float:right; padding-right: 10px;"></afx-label>
|
||||||
|
<afx-label data-id="editorstat" style="float:right;"></afx-label>
|
||||||
|
</div>
|
||||||
|
</afx-vbox>
|
||||||
</afx-app-window>
|
</afx-app-window>
|
15
Antedit/build/debug/README.md
Normal file
15
Antedit/build/debug/README.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Antedit
|
||||||
|
This is an example project, generated by AntOS Development Kit
|
||||||
|
|
||||||
|
## Howto
|
||||||
|
Use the CodePad command palette to access to the SDK functionalities:
|
||||||
|
|
||||||
|
1. Create new project
|
||||||
|
2. Init the project from the current folder located in side bar
|
||||||
|
3. Build and run the project
|
||||||
|
4. Release the project in zip package
|
||||||
|
|
||||||
|
## Set up build target
|
||||||
|
|
||||||
|
Open the `project.json` file from the current project tree and add/remove
|
||||||
|
build target entries. Save the file
|
19
Antedit/build/debug/extensions/EditorExtensionMaker/main.tpl
Normal file
19
Antedit/build/debug/extensions/EditorExtensionMaker/main.tpl
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
(function() {
|
||||||
|
// import the CodePad application module
|
||||||
|
const App = this.OS.application.Antedit;
|
||||||
|
|
||||||
|
// define the extension
|
||||||
|
App.extensions.{0} = class {0} extends App.EditorBaseExtension {
|
||||||
|
constructor(app) {
|
||||||
|
super("{0}",app);
|
||||||
|
}
|
||||||
|
|
||||||
|
test() {
|
||||||
|
return this.notify("Test action is invoked");
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup() {}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}).call(this);
|
15
Antedit/build/debug/extensions/EditorExtensionMaker/meta.tpl
Normal file
15
Antedit/build/debug/extensions/EditorExtensionMaker/meta.tpl
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"javascripts": ["{0}.js"],
|
||||||
|
"copies": [],
|
||||||
|
"meta": {
|
||||||
|
"name": "{0}",
|
||||||
|
"text": "{0}",
|
||||||
|
"version": "0.0.1-a",
|
||||||
|
"actions" : [
|
||||||
|
{
|
||||||
|
"text": "__(Example action)",
|
||||||
|
"name": "test"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
33
Antedit/build/debug/extensions/extensions.json
Normal file
33
Antedit/build/debug/extensions/extensions.json
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "EditorExtensionMaker",
|
||||||
|
"text": "Antedit Extension",
|
||||||
|
"version": "0.0.1-a",
|
||||||
|
"actions" : [
|
||||||
|
{
|
||||||
|
"text": "__(New Extension)",
|
||||||
|
"name": "create"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "__(Build)",
|
||||||
|
"name": "build"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "__(Run)",
|
||||||
|
"name": "run"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "__(Build release)",
|
||||||
|
"name": "release"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "__(Install extension from file)",
|
||||||
|
"name": "install"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "__(Install extension from URL)",
|
||||||
|
"name": "installFromURL"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
168
Antedit/build/debug/main.css
Normal file
168
Antedit/build/debug/main.css
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
|
||||||
|
afx-app-window[data-id = "antedit"] afx-tab-bar> afx-list-view > div.list-container
|
||||||
|
{
|
||||||
|
/*border-top: 1px solid #272822;*/
|
||||||
|
overflow: hidden;
|
||||||
|
overflow-x: auto;
|
||||||
|
font-size: 12px;
|
||||||
|
scrollbar-width: none;
|
||||||
|
/*scrollbar-color: #656565 transparent;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "antedit"] afx-tab-bar> afx-list-view > div.list-container::-webkit-scrollbar {
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id = "antedit"] afx-tab-bar> afx-list-view > div.list-container::-webkit-scrollbar-track {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id = "antedit"] afx-tab-bar> afx-list-view > div.list-container::-webkit-scrollbar-thumb {
|
||||||
|
background-color: #656565;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "antedit"] afx-tab-bar> afx-list-view > div.list-container > ul
|
||||||
|
{
|
||||||
|
width: intrinsic;
|
||||||
|
width: -moz-max-content;
|
||||||
|
width: -webkit-max-content;
|
||||||
|
width: max-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "antedit"] afx-tab-bar> afx-list-view ul afx-list-item:nth-child(even) li.selected,
|
||||||
|
afx-app-window[data-id = "antedit"] afx-tab-bar> afx-list-view > div.list-container > ul > afx-list-item > li.selected{
|
||||||
|
background-color:#272822;
|
||||||
|
color:white;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id = "antedit"] afx-tab-bar> afx-list-view afx-list-view i.closable:before {
|
||||||
|
color:afafaf;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id = "antedit"] afx-tab-bar> afx-list-view ul afx-list-item:nth-child(even) li,
|
||||||
|
afx-app-window[data-id = "antedit"] afx-tab-bar> afx-list-view > div.list-container > ul li{
|
||||||
|
background-color:#333333;
|
||||||
|
color:#afafaf;
|
||||||
|
border-radius: 0;
|
||||||
|
border: 0;
|
||||||
|
padding-top: 5px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
padding-right: 20px;
|
||||||
|
border-right: 1px solid #272822;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id = "antedit"] .afx-window-wrapper afx-vbox[data-id = "sidebar"]{
|
||||||
|
background-color:#272822;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id = "antedit"] div.afx-window-content {
|
||||||
|
background-color:#333333;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id = "antedit"] afx-resizer {
|
||||||
|
background-color:#272822;
|
||||||
|
border-right: 1px solid #656565;
|
||||||
|
border-bottom: 1px solid #656565;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "antedit"] .bottom-tab-content {
|
||||||
|
background-color:#272822;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "antedit"] .afx-window-wrapper afx-tree-view{
|
||||||
|
color: white;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id = "antedit"] .afx-window-wrapper afx-tree-view afx-tree-view-item ul li{
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id = "antedit"] .afx-window-wrapper .afx_tree_item_selected ul{
|
||||||
|
background-color: #116cd6;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "antedit"] afx-file-view afx-tree-view .afx-tree-view-item:before{
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "antedit"] .afx-window-wrapper div[data-id="statctn"]{
|
||||||
|
color: white;
|
||||||
|
background-color: #007acc;
|
||||||
|
padding-right: 10px;
|
||||||
|
padding-top: 5px;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "antedit"] .afx-window-wrapper div[data-id="statctn"] afx-label {
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "cmd-win"] .afx-window-wrapper{
|
||||||
|
border-radius: 0px;
|
||||||
|
border: 0;
|
||||||
|
/*border: 1px solid #37373d;*/
|
||||||
|
background-color: transparent;
|
||||||
|
box-shadow: 0px 3px 6px 0px rgba(0,0,0,0.65);
|
||||||
|
}
|
||||||
|
afx-app-window[data-id = "cmd-win"] .afx-window-wrapper afx-list-view ul afx-list-item:nth-child(even) li
|
||||||
|
{
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id = "cmd-win"] .afx-window-wrapper afx-list-view afx-list-item li{
|
||||||
|
background-color: transparent;
|
||||||
|
color:#afafaf;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id = "cmd-win"] .afx-window-wrapper div.list-container > ul li:hover{
|
||||||
|
background-color: #37373d;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "cmd-win"] .afx-window-wrapper afx-list-view ul afx-list-item:nth-child(even) li.selected,
|
||||||
|
afx-app-window[data-id = "cmd-win"] .afx-window-wrappe dafx-list-viewafx-list-view ul li.selected
|
||||||
|
{
|
||||||
|
background-color: #116cd6;
|
||||||
|
color:white;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id = "cmd-win"] .afx-window-top{
|
||||||
|
height: 0;
|
||||||
|
border:0;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id = "cmd-win"] input{
|
||||||
|
border: 1px solid #007acc;
|
||||||
|
border-radius: 0;
|
||||||
|
font-size: 12px;
|
||||||
|
color:#afafaf;
|
||||||
|
background-color:#272822;
|
||||||
|
padding-left: 5px;
|
||||||
|
margin: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "cmd-win"] .afx-window-content{
|
||||||
|
background-color:#272822;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "antedit"] div[data-id="output-tab"] {
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "antedit"] div[data-id="output-tab"] pre {
|
||||||
|
margin: 3px;
|
||||||
|
white-space: pre-wrap; /* css-3 */
|
||||||
|
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
|
||||||
|
white-space: -pre-wrap; /* Opera 4-6 */
|
||||||
|
white-space: -o-pre-wrap; /* Opera 7 */
|
||||||
|
word-wrap: break-word; /* Internet Explorer 5.5+ */
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "antedit"] div[data-id="output-tab"] pre.code-pad-log-error {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "antedit"] div[data-id="output-tab"] pre.code-pad-log-warn {
|
||||||
|
color: orange;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "antedit"] div[data-id="output-tab"] pre.code-pad-log-info {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "antedit"] afx-button[ data-id="logger-clear" ] button{
|
||||||
|
border: 0;
|
||||||
|
background: transparent;
|
||||||
|
}
|
1
Antedit/build/debug/main.js
Normal file
1
Antedit/build/debug/main.js
Normal file
File diff suppressed because one or more lines are too long
24
Antedit/build/debug/package.json
Normal file
24
Antedit/build/debug/package.json
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"pkgname": "Antedit",
|
||||||
|
"app":"Antedit",
|
||||||
|
"name":"Antos Editor",
|
||||||
|
"description":"Antos text/code editor",
|
||||||
|
"info":{
|
||||||
|
"author": "Xuan Sang LE",
|
||||||
|
"email": "mrsang@iohub.dev"
|
||||||
|
},
|
||||||
|
"version":"0.1.0-a",
|
||||||
|
"category":"Development",
|
||||||
|
"iconclass":"bi bi-journal-code",
|
||||||
|
"mimes":[
|
||||||
|
"text/.*",
|
||||||
|
"[^/]*/json.*",
|
||||||
|
"[^/]*/.*ml",
|
||||||
|
"[^/]*/javascript",
|
||||||
|
"dir"
|
||||||
|
],
|
||||||
|
"dependencies":[
|
||||||
|
"MonacoCore@0.23.0-r"
|
||||||
|
],
|
||||||
|
"locale": {}
|
||||||
|
}
|
38
Antedit/build/debug/scheme.html
Normal file
38
Antedit/build/debug/scheme.html
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<afx-app-window apptitle="Antos Editor" width="600" height="400" data-id="antedit">
|
||||||
|
<afx-vbox>
|
||||||
|
<afx-hbox data-id="wrapper">
|
||||||
|
<afx-vbox data-width = "155" min-width="155" data-id = "sidebar">
|
||||||
|
<div data-height="10"></div>
|
||||||
|
<afx-file-view chdir="false" data-id = "fileview" view="tree" status = "false">
|
||||||
|
</afx-file-view>
|
||||||
|
</afx-vbox>
|
||||||
|
<afx-resizer data-width = "3" ></afx-resizer>
|
||||||
|
<afx-vbox>
|
||||||
|
<afx-hbox>
|
||||||
|
<afx-vbox data-id="left-panel">
|
||||||
|
<afx-tab-bar closable="true" data-height="26" data-id = "left-tabbar"></afx-tab-bar>
|
||||||
|
<div data-id="left-editorarea"></div>
|
||||||
|
</afx-vbox>
|
||||||
|
<afx-resizer data-width="3"></afx-resizer>
|
||||||
|
<afx-vbox data-id="right-panel">
|
||||||
|
<afx-tab-bar closable="true" data-height="26" data-id = "right-tabbar"></afx-tab-bar>
|
||||||
|
<div data-id="right-editorarea"></div>
|
||||||
|
</afx-vbox>
|
||||||
|
</afx-hbox>
|
||||||
|
<afx-resizer data-height = "3" dir = "ve" attachnext = "true" ></afx-resizer>
|
||||||
|
<afx-tab-container data-id = "bottombar" data-height="150" min-height="150" tabbarheight= "22">
|
||||||
|
<afx-hbox tabname="__(Output)" iconclass = "fa fa-file-text" class = "bottom-tab-content">
|
||||||
|
<afx-button text = "" data-id="logger-clear" iconclass="fa fa-trash" data-width="21"></afx-button>
|
||||||
|
<div data-id="output-tab" iconclass = "fa fa-file-text" >
|
||||||
|
</div>
|
||||||
|
</afx-hbox>
|
||||||
|
</afx-tab-container>
|
||||||
|
</afx-vbox>
|
||||||
|
</afx-hbox>
|
||||||
|
<div data-height="20" data-id="statctn">
|
||||||
|
<afx-label text=" " data-id = "current-file-lbl" style="float:left;"></afx-label>
|
||||||
|
<afx-label data-id="langstat" style="float:right; padding-right: 10px;"></afx-label>
|
||||||
|
<afx-label data-id="editorstat" style="float:right;"></afx-label>
|
||||||
|
</div>
|
||||||
|
</afx-vbox>
|
||||||
|
</afx-app-window>
|
BIN
Antedit/build/release/Antedit.zip
Normal file
BIN
Antedit/build/release/Antedit.zip
Normal file
Binary file not shown.
@ -1,7 +0,0 @@
|
|||||||
class Antedit extends this.OS.application.BaseApplication
|
|
||||||
constructor: ( args ) ->
|
|
||||||
super "Antedit", args
|
|
||||||
|
|
||||||
main: () ->
|
|
||||||
|
|
||||||
this.OS.register "Antedit", Antedit
|
|
167
Antedit/css/main.css
Normal file
167
Antedit/css/main.css
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
afx-app-window[data-id = "antedit"] afx-tab-bar> afx-list-view > div.list-container
|
||||||
|
{
|
||||||
|
/*border-top: 1px solid #272822;*/
|
||||||
|
overflow: hidden;
|
||||||
|
overflow-x: auto;
|
||||||
|
font-size: 12px;
|
||||||
|
scrollbar-width: none;
|
||||||
|
/*scrollbar-color: #656565 transparent;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "antedit"] afx-tab-bar> afx-list-view > div.list-container::-webkit-scrollbar {
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id = "antedit"] afx-tab-bar> afx-list-view > div.list-container::-webkit-scrollbar-track {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id = "antedit"] afx-tab-bar> afx-list-view > div.list-container::-webkit-scrollbar-thumb {
|
||||||
|
background-color: #656565;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "antedit"] afx-tab-bar> afx-list-view > div.list-container > ul
|
||||||
|
{
|
||||||
|
width: intrinsic;
|
||||||
|
width: -moz-max-content;
|
||||||
|
width: -webkit-max-content;
|
||||||
|
width: max-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "antedit"] afx-tab-bar> afx-list-view ul afx-list-item:nth-child(even) li.selected,
|
||||||
|
afx-app-window[data-id = "antedit"] afx-tab-bar> afx-list-view > div.list-container > ul > afx-list-item > li.selected{
|
||||||
|
background-color:#272822;
|
||||||
|
color:white;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id = "antedit"] afx-tab-bar> afx-list-view afx-list-view i.closable:before {
|
||||||
|
color:afafaf;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id = "antedit"] afx-tab-bar> afx-list-view ul afx-list-item:nth-child(even) li,
|
||||||
|
afx-app-window[data-id = "antedit"] afx-tab-bar> afx-list-view > div.list-container > ul li{
|
||||||
|
background-color:#333333;
|
||||||
|
color:#afafaf;
|
||||||
|
border-radius: 0;
|
||||||
|
border: 0;
|
||||||
|
padding-top: 5px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
padding-right: 20px;
|
||||||
|
border-right: 1px solid #272822;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id = "antedit"] .afx-window-wrapper afx-vbox[data-id = "sidebar"]{
|
||||||
|
background-color:#272822;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id = "antedit"] div.afx-window-content {
|
||||||
|
background-color:#333333;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id = "antedit"] afx-resizer {
|
||||||
|
background-color:#272822;
|
||||||
|
border-right: 1px solid #656565;
|
||||||
|
border-bottom: 1px solid #656565;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "antedit"] .bottom-tab-content {
|
||||||
|
background-color:#272822;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "antedit"] .afx-window-wrapper afx-tree-view{
|
||||||
|
color: white;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id = "antedit"] .afx-window-wrapper afx-tree-view afx-tree-view-item ul li{
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id = "antedit"] .afx-window-wrapper .afx_tree_item_selected ul{
|
||||||
|
background-color: #116cd6;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "antedit"] afx-file-view afx-tree-view .afx-tree-view-item:before{
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "antedit"] .afx-window-wrapper div[data-id="statctn"]{
|
||||||
|
color: white;
|
||||||
|
background-color: #007acc;
|
||||||
|
padding-right: 10px;
|
||||||
|
padding-top: 5px;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "antedit"] .afx-window-wrapper div[data-id="statctn"] afx-label {
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "cmd-win"] .afx-window-wrapper{
|
||||||
|
border-radius: 0px;
|
||||||
|
border: 0;
|
||||||
|
/*border: 1px solid #37373d;*/
|
||||||
|
background-color: transparent;
|
||||||
|
box-shadow: 0px 3px 6px 0px rgba(0,0,0,0.65);
|
||||||
|
}
|
||||||
|
afx-app-window[data-id = "cmd-win"] .afx-window-wrapper afx-list-view ul afx-list-item:nth-child(even) li
|
||||||
|
{
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id = "cmd-win"] .afx-window-wrapper afx-list-view afx-list-item li{
|
||||||
|
background-color: transparent;
|
||||||
|
color:#afafaf;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id = "cmd-win"] .afx-window-wrapper div.list-container > ul li:hover{
|
||||||
|
background-color: #37373d;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "cmd-win"] .afx-window-wrapper afx-list-view ul afx-list-item:nth-child(even) li.selected,
|
||||||
|
afx-app-window[data-id = "cmd-win"] .afx-window-wrappe dafx-list-viewafx-list-view ul li.selected
|
||||||
|
{
|
||||||
|
background-color: #116cd6;
|
||||||
|
color:white;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id = "cmd-win"] .afx-window-top{
|
||||||
|
height: 0;
|
||||||
|
border:0;
|
||||||
|
}
|
||||||
|
afx-app-window[data-id = "cmd-win"] input{
|
||||||
|
border: 1px solid #007acc;
|
||||||
|
border-radius: 0;
|
||||||
|
font-size: 12px;
|
||||||
|
color:#afafaf;
|
||||||
|
background-color:#272822;
|
||||||
|
padding-left: 5px;
|
||||||
|
margin: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "cmd-win"] .afx-window-content{
|
||||||
|
background-color:#272822;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "antedit"] div[data-id="output-tab"] {
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "antedit"] div[data-id="output-tab"] pre {
|
||||||
|
margin: 3px;
|
||||||
|
white-space: pre-wrap; /* css-3 */
|
||||||
|
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
|
||||||
|
white-space: -pre-wrap; /* Opera 4-6 */
|
||||||
|
white-space: -o-pre-wrap; /* Opera 7 */
|
||||||
|
word-wrap: break-word; /* Internet Explorer 5.5+ */
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "antedit"] div[data-id="output-tab"] pre.code-pad-log-error {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "antedit"] div[data-id="output-tab"] pre.code-pad-log-warn {
|
||||||
|
color: orange;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "antedit"] div[data-id="output-tab"] pre.code-pad-log-info {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
afx-app-window[data-id = "antedit"] afx-button[ data-id="logger-clear" ] button{
|
||||||
|
border: 0;
|
||||||
|
background: transparent;
|
||||||
|
}
|
19
Antedit/extensions/EditorExtensionMaker/main.tpl
Normal file
19
Antedit/extensions/EditorExtensionMaker/main.tpl
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
(function() {
|
||||||
|
// import the CodePad application module
|
||||||
|
const App = this.OS.application.Antedit;
|
||||||
|
|
||||||
|
// define the extension
|
||||||
|
App.extensions.{0} = class {0} extends App.EditorBaseExtension {
|
||||||
|
constructor(app) {
|
||||||
|
super("{0}",app);
|
||||||
|
}
|
||||||
|
|
||||||
|
test() {
|
||||||
|
return this.notify("Test action is invoked");
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup() {}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}).call(this);
|
15
Antedit/extensions/EditorExtensionMaker/meta.tpl
Normal file
15
Antedit/extensions/EditorExtensionMaker/meta.tpl
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"javascripts": ["{0}.js"],
|
||||||
|
"copies": [],
|
||||||
|
"meta": {
|
||||||
|
"name": "{0}",
|
||||||
|
"text": "{0}",
|
||||||
|
"version": "0.0.1-a",
|
||||||
|
"actions" : [
|
||||||
|
{
|
||||||
|
"text": "__(Example action)",
|
||||||
|
"name": "test"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
33
Antedit/extensions/extensions.json
Normal file
33
Antedit/extensions/extensions.json
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "EditorExtensionMaker",
|
||||||
|
"text": "Antedit Extension",
|
||||||
|
"version": "0.0.1-a",
|
||||||
|
"actions" : [
|
||||||
|
{
|
||||||
|
"text": "__(New Extension)",
|
||||||
|
"name": "create"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "__(Build)",
|
||||||
|
"name": "build"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "__(Run)",
|
||||||
|
"name": "run"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "__(Build release)",
|
||||||
|
"name": "release"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "__(Install extension from file)",
|
||||||
|
"name": "install"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "__(Install extension from URL)",
|
||||||
|
"name": "installFromURL"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
@ -1,16 +1,24 @@
|
|||||||
{
|
{
|
||||||
"pkgname": "Antedit",
|
"pkgname": "Antedit",
|
||||||
"app":"Antedit",
|
"app":"Antedit",
|
||||||
"name":"Antedit",
|
"name":"Antos Editor",
|
||||||
"description":"Antedit",
|
"description":"Antos text/code editor",
|
||||||
"info":{
|
"info":{
|
||||||
"author": "",
|
"author": "Xuan Sang LE",
|
||||||
"email": ""
|
"email": "mrsang@iohub.dev"
|
||||||
},
|
},
|
||||||
"version":"0.0.1-a",
|
"version":"0.1.0-a",
|
||||||
"category":"Other",
|
"category":"Development",
|
||||||
"iconclass":"fa fa-adn",
|
"iconclass":"bi bi-journal-code",
|
||||||
"mimes":["none"],
|
"mimes":[
|
||||||
"dependencies":[],
|
"text/.*",
|
||||||
|
"[^/]*/json.*",
|
||||||
|
"[^/]*/.*ml",
|
||||||
|
"[^/]*/javascript",
|
||||||
|
"dir"
|
||||||
|
],
|
||||||
|
"dependencies":[
|
||||||
|
"MonacoCore@0.23.0-r"
|
||||||
|
],
|
||||||
"locale": {}
|
"locale": {}
|
||||||
}
|
}
|
@ -1,8 +1,14 @@
|
|||||||
{
|
{
|
||||||
"name": "Antedit",
|
"name": "Antedit",
|
||||||
"css": [],
|
"css": ["css/main.css"],
|
||||||
"javascripts": [],
|
"javascripts": [],
|
||||||
"coffees": ["coffees/main.coffee"],
|
"coffees": [],
|
||||||
"ts": [],
|
"ts": [
|
||||||
"copies": ["assets/scheme.html", "package.json", "README.md"]
|
"ts/monaco.d.ts",
|
||||||
|
"ts/BaseEditorModel.ts",
|
||||||
|
"ts/MonacoEditorModel.ts",
|
||||||
|
"ts/main.ts",
|
||||||
|
"ts/EditorExtensionMaker.ts"
|
||||||
|
],
|
||||||
|
"copies": ["extensions","assets/scheme.html", "package.json", "README.md"]
|
||||||
}
|
}
|
570
Antedit/ts/BaseEditorModel.ts
Normal file
570
Antedit/ts/BaseEditorModel.ts
Normal file
@ -0,0 +1,570 @@
|
|||||||
|
namespace OS {
|
||||||
|
export namespace application {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extends the [[RemoteFileHandle]] interface with some useful
|
||||||
|
* properties used by [[BaseEditorModel]]
|
||||||
|
*/
|
||||||
|
export type EditorFileHandle = API.VFS.RemoteFileHandle & {
|
||||||
|
/**
|
||||||
|
* The text will be displayed on the tab bar when opened
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
text: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Editor text model attached to the file
|
||||||
|
* modification history of the file
|
||||||
|
*
|
||||||
|
* @type {any}
|
||||||
|
*/
|
||||||
|
textModel: any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate whether the file is selected
|
||||||
|
*
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
selected: boolean;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
export abstract class BaseEditorModel {
|
||||||
|
/**
|
||||||
|
* Reference to the current editing file handle
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
* @type {EditorFileHandle}
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
protected currfile: EditorFileHandle;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Referent to the parent app
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @type {BaseApplication}
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
private app: BaseApplication;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reference to the editor tab bar UI
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @type {GUI.tag.TabBarTag}
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
private tabbar: GUI.tag.TabBarTag;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Referent to the editor container
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @type {HTMLElement}
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
private container: HTMLElement;
|
||||||
|
|
||||||
|
onstatuschange: (stat: GenericObject<any>) => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Editor mutex
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @type {boolean}
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
private editormux: boolean;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance of BaseEditorModel.
|
||||||
|
*
|
||||||
|
* @param {Antedit} app parent app
|
||||||
|
* @param {GUI.tag.TabBarTag} tabbar tabbar DOM element
|
||||||
|
* @param {HTMLElement} editorarea editor container DOM element
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
constructor(app: BaseApplication, tabbar: GUI.tag.TabBarTag, editorarea: HTMLElement) {
|
||||||
|
this.container = editorarea;
|
||||||
|
this.currfile = "Untitled".asFileHandle() as EditorFileHandle;
|
||||||
|
this.tabbar = tabbar;
|
||||||
|
this.editorSetup(editorarea);
|
||||||
|
this.app = app;
|
||||||
|
this.editormux = false;
|
||||||
|
this.onstatuschange = undefined;
|
||||||
|
|
||||||
|
this.on("focus", () => {
|
||||||
|
if (this.onstatuschange)
|
||||||
|
this.onstatuschange(this.getEditorStatus());
|
||||||
|
});
|
||||||
|
this.on("input", () => {
|
||||||
|
if (this.editormux) {
|
||||||
|
this.editormux = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!this.currfile.dirty) {
|
||||||
|
this.currfile.dirty = true;
|
||||||
|
this.currfile.text += "*";
|
||||||
|
return this.tabbar.update(undefined);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.on("changeCursor", () => {
|
||||||
|
if (this.onstatuschange)
|
||||||
|
this.onstatuschange(this.getEditorStatus());
|
||||||
|
});
|
||||||
|
|
||||||
|
this.tabbar.ontabselect = (e) => {
|
||||||
|
return this.selecteTab($(e.data.item).index());
|
||||||
|
};
|
||||||
|
this.tabbar.ontabclose = (e) => {
|
||||||
|
const it = e.data.item;
|
||||||
|
if (!it) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!it.data.dirty) {
|
||||||
|
return this.closeTab(it);
|
||||||
|
}
|
||||||
|
this.app.openDialog("YesNoDialog", {
|
||||||
|
title: __("Close tab"),
|
||||||
|
text: __("Close without saving ?"),
|
||||||
|
}).then((d) => {
|
||||||
|
if (d) {
|
||||||
|
return this.closeTab(it);
|
||||||
|
}
|
||||||
|
return this.focus();
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a tab on the tabbar corresponding to a file handle
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {EditorFileHandle} file then file handle to search
|
||||||
|
* @returns {number}
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
private findTabByFile(file: EditorFileHandle): number {
|
||||||
|
const lst = this.tabbar.items;
|
||||||
|
const its = (() => {
|
||||||
|
const result = [];
|
||||||
|
for (let i = 0; i < lst.length; i++) {
|
||||||
|
const d = lst[i];
|
||||||
|
if (d.hash() === file.hash()) {
|
||||||
|
result.push(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
})();
|
||||||
|
if (its.length === 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return its[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create new tab when opening a file
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {EditorFileHandle} file
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
private newTab(file: EditorFileHandle): void {
|
||||||
|
file.text = file.basename ? file.basename : file.path;
|
||||||
|
if (!file.cache) {
|
||||||
|
file.cache = "";
|
||||||
|
}
|
||||||
|
file.textModel = this.newTextModelFrom(file);
|
||||||
|
this.currfile.selected = false;
|
||||||
|
file.selected = true;
|
||||||
|
//console.log cnt
|
||||||
|
this.tabbar.push(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close a tab when a file is closed
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {GUI.tag.ListViewItemTag} it reference to the tab to close
|
||||||
|
* @returns {boolean}
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
private closeTab(it: GUI.tag.ListViewItemTag): boolean {
|
||||||
|
this.tabbar.delete(it);
|
||||||
|
const cnt = this.tabbar.items.length;
|
||||||
|
|
||||||
|
if (cnt === 0) {
|
||||||
|
this.openFile(
|
||||||
|
"Untitled".asFileHandle() as EditorFileHandle
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.tabbar.selected = cnt - 1;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select a tab by its index
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {number} i tab index
|
||||||
|
* @returns {void}
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
private selecteTab(i: number): void {
|
||||||
|
//return if i is @tabbar.get "selidx"
|
||||||
|
const file = this.tabbar.items[i] as EditorFileHandle;
|
||||||
|
if (!file) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//return if file is @currfile
|
||||||
|
if (this.currfile !== file) {
|
||||||
|
this.currfile.textModel = this.getTexModel();
|
||||||
|
this.currfile.selected = false;
|
||||||
|
this.currfile = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.editormux = true;
|
||||||
|
this.setTextModel(file.textModel);
|
||||||
|
if (this.onstatuschange)
|
||||||
|
this.onstatuschange(this.getEditorStatus());
|
||||||
|
this.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select an opened file, this will select the corresponding tab
|
||||||
|
*
|
||||||
|
* @param {(EditorFileHandle | string)} file
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
selectFile(file: EditorFileHandle | string): void {
|
||||||
|
const i = this.findTabByFile(
|
||||||
|
file.asFileHandle() as EditorFileHandle
|
||||||
|
);
|
||||||
|
if (i !== -1) {
|
||||||
|
this.tabbar.selected = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Open a file in new tab. If the file is already opened,
|
||||||
|
* the just select the tab
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param {EditorFileHandle} file file to open
|
||||||
|
* @returns {void}
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
openFile(file: EditorFileHandle): void {
|
||||||
|
//find tab
|
||||||
|
const i = this.findTabByFile(file);
|
||||||
|
if (i !== -1) {
|
||||||
|
this.tabbar.selected = i;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (file.path.toString() === "Untitled") {
|
||||||
|
this.newTab(file);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
file.read()
|
||||||
|
.then((d) => {
|
||||||
|
file.cache = d || "";
|
||||||
|
return this.newTab(file);
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
return this.app.error(
|
||||||
|
__("Unable to open: {0}", file.path),
|
||||||
|
e
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* write a file
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {EditorFileHandle} file
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
private write(file: EditorFileHandle): void {
|
||||||
|
this.currfile.cache = this.getValue();
|
||||||
|
file.write("text/plain")
|
||||||
|
.then((d) => {
|
||||||
|
file.dirty = false;
|
||||||
|
file.text = file.basename;
|
||||||
|
this.tabbar.update(undefined);
|
||||||
|
})
|
||||||
|
.catch((e) =>
|
||||||
|
this.app.error(__("Unable to save file: {0}", file.path), e)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the current opened file
|
||||||
|
*
|
||||||
|
* @return {*} {void}
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
save(): void {
|
||||||
|
this.currfile.cache = this.getValue();
|
||||||
|
if (this.currfile.basename) {
|
||||||
|
return this.write(this.currfile);
|
||||||
|
}
|
||||||
|
return this.saveAs();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the current file as another file
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
saveAs(): void {
|
||||||
|
this.app.openDialog("FileDialog", {
|
||||||
|
title: __("Save as"),
|
||||||
|
file: this.currfile,
|
||||||
|
}).then((f) => {
|
||||||
|
let d = f.file.path.asFileHandle();
|
||||||
|
if (f.file.type === "file") {
|
||||||
|
d = d.parent();
|
||||||
|
}
|
||||||
|
this.currfile.setPath(`${d.path}/${f.name}`);
|
||||||
|
this.write(this.currfile);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all dirty file handles in the editor
|
||||||
|
*
|
||||||
|
* @return {*} {EditorFileHandle[]}
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
dirties(): EditorFileHandle[] {
|
||||||
|
const result = [];
|
||||||
|
for (let v of Array.from(this.tabbar.items)) {
|
||||||
|
if (v.dirty) {
|
||||||
|
result.push(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context menu handle for the editor
|
||||||
|
*
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
set contextmenuHandle(cb: (e: any, m: any) => void) {
|
||||||
|
this.container.contextmenuHandle = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close all opened files
|
||||||
|
*
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
closeAll(): void {
|
||||||
|
this.tabbar.items = [];
|
||||||
|
this.resetEditor();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the editor is dirty
|
||||||
|
*
|
||||||
|
* @return {*} {boolean}
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
isDirty(): boolean {
|
||||||
|
return this.dirties().length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up the editor instance
|
||||||
|
* Should be implemented by subclass
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
* @abstract
|
||||||
|
* @param {HTMLElement} el
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
protected abstract editorSetup(el: HTMLElement): void;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listen to editor event
|
||||||
|
*
|
||||||
|
* Should be implemented by subclasses
|
||||||
|
*
|
||||||
|
* @abstract
|
||||||
|
* @param {string} evt_str
|
||||||
|
* @param {() => void} callback
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
abstract on(evt_str: string, callback: () => void): void;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resize the editor
|
||||||
|
*
|
||||||
|
* Should be implemented by subclasses
|
||||||
|
*
|
||||||
|
* @abstract
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
abstract resize(): void;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make the editor focused
|
||||||
|
*
|
||||||
|
* Should be implemented by subclasses
|
||||||
|
*
|
||||||
|
* @abstract
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
abstract focus(): void;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get language mode from file extension
|
||||||
|
*
|
||||||
|
* Should be implemented by subclasses
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
* @abstract
|
||||||
|
* @param {string} path
|
||||||
|
* @return {*} {GenericObject<any>}
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
protected abstract getModeForPath(path: string): GenericObject<any>;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query the editor status
|
||||||
|
*
|
||||||
|
* Should be implemented by subclasses
|
||||||
|
*
|
||||||
|
* @abstract
|
||||||
|
* @return {*} {GenericObject<any>}
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
abstract getEditorStatus(): GenericObject<any>;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the editor value
|
||||||
|
*
|
||||||
|
* Should be implemented by subclasses
|
||||||
|
*
|
||||||
|
* @abstract
|
||||||
|
* @return {*} {string}
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
abstract getValue(): string;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the editor value
|
||||||
|
*
|
||||||
|
* Should be implemented by subclasses
|
||||||
|
*
|
||||||
|
* @abstract
|
||||||
|
* @param {string} value
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
abstract setValue(value: string): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the editor language mode
|
||||||
|
*
|
||||||
|
* Should be implemented by subclasses
|
||||||
|
*
|
||||||
|
* @abstract
|
||||||
|
* @param {GenericObject<any>} m
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
abstract setMode(m: GenericObject<any>): void;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get textModel from the current editor session
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
* @abstract
|
||||||
|
* @return {*} {*}
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
protected abstract getTexModel(): any;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set text model to the current editor session
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
* @abstract
|
||||||
|
* @param {*} model
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
protected abstract setTextModel(model: any): void;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create new text model from the VFS file
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
* @abstract
|
||||||
|
* @param {EditorFileHandle} file
|
||||||
|
* @return {*} {*}
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
protected abstract newTextModelFrom(file: EditorFileHandle): any;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the editor
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
* @abstract
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
protected abstract resetEditor(): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the current editor theme
|
||||||
|
*
|
||||||
|
* Should be implemented by subclasses
|
||||||
|
*
|
||||||
|
* @abstract
|
||||||
|
* @param {string} theme
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
abstract setTheme(theme: string): void;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all language modes supported by the editor
|
||||||
|
*
|
||||||
|
* @abstract
|
||||||
|
* @return {*} {GenericObject<any>[]}
|
||||||
|
* @memberof BaseEditorModel
|
||||||
|
*/
|
||||||
|
abstract getModes(): GenericObject<any>[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the real editor model
|
||||||
|
*/
|
||||||
|
abstract getEditor(): any;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
472
Antedit/ts/EditorExtensionMaker.ts
Normal file
472
Antedit/ts/EditorExtensionMaker.ts
Normal file
@ -0,0 +1,472 @@
|
|||||||
|
|
||||||
|
namespace OS {
|
||||||
|
|
||||||
|
declare var JSZip: any;
|
||||||
|
|
||||||
|
export namespace application {
|
||||||
|
export type AnteditBaseExtension = typeof EditorBaseExtension;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @class EditorBaseExtension
|
||||||
|
*/
|
||||||
|
class EditorBaseExtension {
|
||||||
|
static dependencies: string[];
|
||||||
|
|
||||||
|
protected app: OS.application.Antedit;
|
||||||
|
protected name: string;
|
||||||
|
constructor(name:string, app: OS.application.Antedit) {
|
||||||
|
this.app = app;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @returns {Promise<any>}
|
||||||
|
* @memberof EditorBaseExtension
|
||||||
|
*/
|
||||||
|
preload(): Promise<any> {
|
||||||
|
return API.require(OS.application.Antedit.extensions[this.name].dependencies);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
* @returns {string}
|
||||||
|
* @memberof EditorBaseExtension
|
||||||
|
*/
|
||||||
|
protected basedir(): string {
|
||||||
|
return `${this.app.meta().path}/extensions/${this.name}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
* @param {(string | FormattedString)} m
|
||||||
|
* @returns {void}
|
||||||
|
* @memberof EditorBaseExtension
|
||||||
|
*/
|
||||||
|
protected notify(m: string | FormattedString): void {
|
||||||
|
return this.app.notify(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
* @param {(string | FormattedString)} m
|
||||||
|
* @param {Error} e
|
||||||
|
* @returns {void}
|
||||||
|
* @memberof EditorBaseExtension
|
||||||
|
*/
|
||||||
|
protected error(m: string | FormattedString, e: Error): void {
|
||||||
|
return this.app.error(m, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
* @return {AnteditLogger} editor logger
|
||||||
|
* @memberof EditorBaseExtension
|
||||||
|
*/
|
||||||
|
protected logger(): any {
|
||||||
|
if (!this.app.setting.showBottomBar) {
|
||||||
|
this.app.showOutput(true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.app.showOutput(false);
|
||||||
|
}
|
||||||
|
return this.app.logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
* @param {string} file
|
||||||
|
* @returns {Promise<GenericObject<any>>}
|
||||||
|
* @memberof EditorBaseExtension
|
||||||
|
*/
|
||||||
|
protected metadata(file: string): Promise<GenericObject<any>> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (!this.app.currdir) {
|
||||||
|
return reject(
|
||||||
|
API.throwe(__("Current folder is not found"))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
`${this.app.currdir.path}/${file}`
|
||||||
|
.asFileHandle()
|
||||||
|
.read("json")
|
||||||
|
.then((data) => {
|
||||||
|
if (!data.root && this.app.currdir) {
|
||||||
|
data.root = this.app.currdir.path;
|
||||||
|
}
|
||||||
|
resolve(data);
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
// try to ask user to select a folder
|
||||||
|
this.app.openDialog("FileDialog", {
|
||||||
|
title: __("Select build directory"),
|
||||||
|
root: this.app.currdir.path,
|
||||||
|
mimes: ["dir"]
|
||||||
|
})
|
||||||
|
.then((d) => {
|
||||||
|
`${d.file.path}/${file}`
|
||||||
|
.asFileHandle()
|
||||||
|
.read("json")
|
||||||
|
.then((data) => {
|
||||||
|
if (!data.root) {
|
||||||
|
data.root = d.file.path;
|
||||||
|
}
|
||||||
|
resolve(data);
|
||||||
|
})
|
||||||
|
.catch((e1) => reject(e1))
|
||||||
|
})
|
||||||
|
.catch(
|
||||||
|
(e1) => reject(API.throwe(__("Unable to read meta-data"))
|
||||||
|
))
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorBaseExtension.dependencies = [];
|
||||||
|
OS.application.Antedit.extensions = {};
|
||||||
|
OS.application.Antedit.EditorBaseExtension = EditorBaseExtension;
|
||||||
|
|
||||||
|
class EditorExtensionMaker extends EditorBaseExtension {
|
||||||
|
constructor(app: OS.application.Antedit) {
|
||||||
|
super("EditorExtensionMaker", app);
|
||||||
|
}
|
||||||
|
|
||||||
|
create(): void {
|
||||||
|
this.logger().clear();
|
||||||
|
this.app
|
||||||
|
.openDialog("FileDialog", {
|
||||||
|
title: "__(New CodePad extension at)",
|
||||||
|
file: { basename: __("ExtensionName") },
|
||||||
|
mimes: ["dir"],
|
||||||
|
})
|
||||||
|
.then((d) => {
|
||||||
|
return this.mktpl(d.file.path, d.name);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
build(callback?: () => void): void {
|
||||||
|
this.logger().clear();
|
||||||
|
this.metadata("extension.json")
|
||||||
|
.then(async (meta) => {
|
||||||
|
try {
|
||||||
|
const jsrc = await API.VFS.cat(meta.javascripts.map(v => `${meta.root}/${v}`),"");
|
||||||
|
|
||||||
|
await `${meta.root}/build/debug/main.js`
|
||||||
|
.asFileHandle()
|
||||||
|
.setCache(jsrc)
|
||||||
|
.write("text/plain");
|
||||||
|
|
||||||
|
await `${meta.root}/build/debug/extension.json`
|
||||||
|
.asFileHandle()
|
||||||
|
.setCache(meta.meta)
|
||||||
|
.write("object");
|
||||||
|
|
||||||
|
await API.VFS.copy( meta.copies.map(v => `${meta.root}/${v}`),`${meta.root}/build/debug`);
|
||||||
|
this.logger().info(__("Files generated in {0}", `${meta.root}/build/debug`));
|
||||||
|
if(callback)
|
||||||
|
callback();
|
||||||
|
} catch (e) {
|
||||||
|
return this.logger().error(__("Unable to build extension:{0}", e.stack));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((e) => this.logger().error(__("Unable to read meta-data:{0}", e.stack)));
|
||||||
|
}
|
||||||
|
|
||||||
|
run(): void {
|
||||||
|
this.logger().clear();
|
||||||
|
this.metadata("extension.json")
|
||||||
|
.then(async (meta) => {
|
||||||
|
if(!meta || !meta.meta || !meta.meta.name)
|
||||||
|
return this.logger().error(__("Invalid extension meta-data"));
|
||||||
|
try {
|
||||||
|
const path = `${meta.root}/build/debug/main.js`;
|
||||||
|
if (API.shared[path]) {
|
||||||
|
delete API.shared[path];
|
||||||
|
}
|
||||||
|
await API.requires(path);
|
||||||
|
if (this.app.extensions[meta.meta.name] && this.app.extensions[meta.meta.name].cleanup)
|
||||||
|
{
|
||||||
|
this.app.extensions[meta.meta.name].cleanup();
|
||||||
|
}
|
||||||
|
this.app.extensions[meta.meta.name] = new OS.application.Antedit.extensions[meta.meta.name](this.app);
|
||||||
|
for (let v of meta.meta.actions) {
|
||||||
|
this.app.eum.addAction(meta.meta, v, (e_name, a_name) => {
|
||||||
|
this.app.loadAndRunExtensionAction(e_name, a_name, `${meta.root}/build`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.app.eum.active.getEditor().trigger(meta.meta.name, 'editor.action.quickCommand');
|
||||||
|
} catch (e) {
|
||||||
|
return this.logger().error(__("Unable to run extension:{0}", e.stack));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((e) => this.logger().error(__("Unable to read meta-data:{0}", e.stack)));
|
||||||
|
}
|
||||||
|
|
||||||
|
release(): void {
|
||||||
|
this.logger().clear();
|
||||||
|
this.metadata("extension.json")
|
||||||
|
.then((meta) => {
|
||||||
|
this.build(async () => {
|
||||||
|
try {
|
||||||
|
API.VFS.mkar(
|
||||||
|
`${meta.root}/build/debug`,
|
||||||
|
`${meta.root}/build/release/${meta.meta.name}.zip`
|
||||||
|
);
|
||||||
|
this.logger().info(__("Archive created at {0}", `${meta.root}/build/release/${meta.meta.name}.zip`));
|
||||||
|
} catch (e) {
|
||||||
|
return this.logger().error(
|
||||||
|
__("Unable to create archive: {0}",
|
||||||
|
e.stack
|
||||||
|
));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((e) => this.logger().error(__("Unable to read meta-data: {0}", e.stack)));
|
||||||
|
}
|
||||||
|
|
||||||
|
install(): void {
|
||||||
|
this.logger().clear();
|
||||||
|
this.app
|
||||||
|
.openDialog("FileDialog", {
|
||||||
|
title: "__(Select extension archive)",
|
||||||
|
mimes: [".*/zip"],
|
||||||
|
})
|
||||||
|
.then(async (d) => {
|
||||||
|
try {
|
||||||
|
await this.installZip(d.file.path);
|
||||||
|
this.logger().info(__("Extension installed"));
|
||||||
|
return this.app.loadExtensionMetaData();
|
||||||
|
} catch (e) {
|
||||||
|
return this.logger().error(__("Unable to install extension: {0}", e.stack));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
installFromURL(): void
|
||||||
|
{
|
||||||
|
this.logger().clear();
|
||||||
|
this.app
|
||||||
|
.openDialog("PromptDialog", {
|
||||||
|
title: __("Enter URI"),
|
||||||
|
label: __("Please enter extension URI:")
|
||||||
|
})
|
||||||
|
.then(async (v) => {
|
||||||
|
if(!v) return;
|
||||||
|
try {
|
||||||
|
await this.installZip(v);
|
||||||
|
this.logger().info(__("Extension installed"));
|
||||||
|
return this.app.loadExtensionMetaData();
|
||||||
|
} catch (e) {
|
||||||
|
return this.app.error(__("Unable to install extension: {0}", v));
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {string} path
|
||||||
|
* @param {string} name
|
||||||
|
* @memberof EditorExtensionMaker
|
||||||
|
*/
|
||||||
|
private mktpl(path: string, name: string): void {
|
||||||
|
const rpath = `${path}/${name}`;
|
||||||
|
const dirs = [
|
||||||
|
rpath,
|
||||||
|
`${rpath}/build`,
|
||||||
|
`${rpath}/build/release`,
|
||||||
|
`${rpath}/build/debug`,
|
||||||
|
];
|
||||||
|
const files = [
|
||||||
|
["main.tpl", `${rpath}/${name}.js`],
|
||||||
|
["meta.tpl", `${rpath}/extension.json`],
|
||||||
|
];
|
||||||
|
API.VFS.mkdirAll(dirs)
|
||||||
|
.then(async () => {
|
||||||
|
try {
|
||||||
|
await API.VFS.mktpl(files, this.basedir(), (data)=>{
|
||||||
|
return data.format(name, `${path}/${name}`);
|
||||||
|
});
|
||||||
|
this.app.currdir = rpath.asFileHandle();
|
||||||
|
this.app.toggleSideBar();
|
||||||
|
return this.app.eum.active.openFile(
|
||||||
|
`${rpath}/${name}.js`.asFileHandle() as application.EditorFileHandle
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
return this.logger().error(
|
||||||
|
__("Unable to create extension template: {0}",
|
||||||
|
e.stack)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((e) =>
|
||||||
|
this.logger().error(__("Unable to create extension directories: {0}", e.stack))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {string} path
|
||||||
|
* @returns {Promise<any>}
|
||||||
|
* @memberof EditorExtensionMaker
|
||||||
|
*/
|
||||||
|
private installZip(path: string): Promise<void> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
API.requires("os://scripts/jszip.min.js")
|
||||||
|
.then(() => {
|
||||||
|
path.asFileHandle()
|
||||||
|
.read("binary")
|
||||||
|
.then((data) => {
|
||||||
|
JSZip.loadAsync(data)
|
||||||
|
.then((zip: any) => {
|
||||||
|
zip.file("extension.json").async("uint8array")
|
||||||
|
.then((d) =>{
|
||||||
|
const meta = JSON.parse(new TextDecoder("utf-8").decode(d));
|
||||||
|
const pth = this.ext_dir(meta.name);
|
||||||
|
const dir = [pth];
|
||||||
|
const files = [];
|
||||||
|
for (let name in zip.files) {
|
||||||
|
const file = zip.files[name];
|
||||||
|
if (file.dir) {
|
||||||
|
dir.push(pth + "/" + name);
|
||||||
|
} else if(name != "extension.json") {
|
||||||
|
files.push(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dir.length > 0) {
|
||||||
|
API.VFS.mkdirAll(dir)
|
||||||
|
.then(() => {
|
||||||
|
this.installFiles(files, zip, meta)
|
||||||
|
.then(() => resolve())
|
||||||
|
.catch((e) =>
|
||||||
|
reject(__e(e))
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.catch((e) => reject(__e(e)));
|
||||||
|
} else {
|
||||||
|
this.installFiles(files, zip, meta)
|
||||||
|
.then(() => resolve())
|
||||||
|
.catch((e) => reject(__e(e)));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(e => reject(__e(e)));
|
||||||
|
})
|
||||||
|
.catch((e: Error) => reject(__e(e)));
|
||||||
|
})
|
||||||
|
.catch((e) => reject(__e(e)));
|
||||||
|
})
|
||||||
|
.catch((e) => reject(__e(e)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private ext_dir(en: string): string
|
||||||
|
{
|
||||||
|
return `${this.app.meta().path}/extensions/${en}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {string[]} files
|
||||||
|
* @param {*} zip
|
||||||
|
* @param {GenericObject<any>} meta
|
||||||
|
* @returns {Promise<any>}
|
||||||
|
* @memberof EditorExtensionMaker
|
||||||
|
*/
|
||||||
|
private installFiles(
|
||||||
|
files: string[],
|
||||||
|
zip: any,
|
||||||
|
meta: GenericObject<any>
|
||||||
|
): Promise<void> {
|
||||||
|
if (files.length === 0) {
|
||||||
|
return this.installMeta(meta);
|
||||||
|
}
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const file = files.splice(0, 1)[0];
|
||||||
|
const path = `${this.ext_dir(meta.name)}/${file}`;
|
||||||
|
return zip
|
||||||
|
.file(file)
|
||||||
|
.async("uint8array")
|
||||||
|
.then((d: Uint8Array) => {
|
||||||
|
return path
|
||||||
|
.asFileHandle()
|
||||||
|
.setCache(new Blob([d], { type: "octet/stream" }))
|
||||||
|
.write("text/plain")
|
||||||
|
.then((r) => {
|
||||||
|
if (r.error) {
|
||||||
|
return reject(r.error);
|
||||||
|
}
|
||||||
|
return this.installFiles(files, zip, meta)
|
||||||
|
.then(() => resolve())
|
||||||
|
.catch((e) => reject(__e(e)));
|
||||||
|
})
|
||||||
|
.catch((e) => reject(__e(e)));
|
||||||
|
})
|
||||||
|
.catch((e: Error) => reject(__e(e)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {GenericObject<any>} meta
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
* @memberof EditorExtensionMaker
|
||||||
|
*/
|
||||||
|
private installMeta(meta: GenericObject<any>): Promise<void> {
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
const file = `${this.ext_dir("")}/extensions.json`.asFileHandle();
|
||||||
|
try {
|
||||||
|
const data = await file.read("json");
|
||||||
|
const names = [];
|
||||||
|
for (let v of data) {
|
||||||
|
names.push(v.name);
|
||||||
|
}
|
||||||
|
const idx = names.indexOf(meta.name);
|
||||||
|
if (idx >= 0) {
|
||||||
|
data.splice(idx, 1);
|
||||||
|
}
|
||||||
|
data.push(meta);
|
||||||
|
try {
|
||||||
|
await file.setCache(data).write("object");
|
||||||
|
return resolve();
|
||||||
|
} catch (e) {
|
||||||
|
return reject(__e(e));
|
||||||
|
}
|
||||||
|
} catch (e_1) {
|
||||||
|
// try to create new file
|
||||||
|
try {
|
||||||
|
await file.setCache([meta]).write("object");
|
||||||
|
return resolve();
|
||||||
|
} catch (e_2) {
|
||||||
|
return reject(__e(e_2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OS.application.Antedit.extensions.EditorExtensionMaker = EditorExtensionMaker;
|
||||||
|
}
|
271
Antedit/ts/MonacoEditorModel.ts
Normal file
271
Antedit/ts/MonacoEditorModel.ts
Normal file
@ -0,0 +1,271 @@
|
|||||||
|
namespace OS {
|
||||||
|
export namespace application {
|
||||||
|
/**
|
||||||
|
* Wrapper model for the ACE text editor
|
||||||
|
*
|
||||||
|
* @export
|
||||||
|
* @class MonacoEditorModel
|
||||||
|
* @extends {BaseEditorModel}
|
||||||
|
*/
|
||||||
|
export class MonacoEditorModel extends BaseEditorModel {
|
||||||
|
|
||||||
|
static modes: GenericObject<monaco.languages.ILanguageExtensionPoint>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance of MonacoEditorModel.
|
||||||
|
* @param {MonacoEditorModel} app MonacoEditorModel instance
|
||||||
|
* @param {GUI.tag.TabBarTag} tabbar tabbar element
|
||||||
|
* @param {HTMLElement} editorarea main editor container element
|
||||||
|
* @memberof MonacoEditorModel
|
||||||
|
*/
|
||||||
|
constructor(app: BaseApplication, tabbar: GUI.tag.TabBarTag, editorarea: HTMLElement) {
|
||||||
|
super(app, tabbar, editorarea);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the editor
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
* @memberof MonacoEditorModel
|
||||||
|
*/
|
||||||
|
protected resetEditor(): void {
|
||||||
|
this.setValue("");
|
||||||
|
// TODO create new textmodel
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a text model from the current editor session
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
* @return {*}
|
||||||
|
* @memberof MonacoEditorModel
|
||||||
|
*/
|
||||||
|
protected getTexModel() {
|
||||||
|
return {
|
||||||
|
model: this.editor.getModel(),
|
||||||
|
position: this.editor.getPosition()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set text model to current editor session
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
* @param {*} model
|
||||||
|
* @memberof MonacoEditorModel
|
||||||
|
*/
|
||||||
|
protected setTextModel(model: any): void {
|
||||||
|
this.editor.setModel(model.model);
|
||||||
|
if(model.position)
|
||||||
|
this.editor.setPosition(model.position);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create new editor model from file
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
* @param {EditorFileHandle} file
|
||||||
|
* @return {*} {*}
|
||||||
|
* @memberof MonacoEditorModel
|
||||||
|
*/
|
||||||
|
protected newTextModelFrom(file: EditorFileHandle): any {
|
||||||
|
if(file.path.toString() === "Untitled") {
|
||||||
|
return {
|
||||||
|
model: monaco.editor.createModel(file.cache, "textplain")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const uri = monaco.Uri.parse(file.path);
|
||||||
|
const model = monaco.editor.getModel(uri);
|
||||||
|
if(model)
|
||||||
|
{
|
||||||
|
return { model: model };
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
model: monaco.editor.createModel(file.cache, undefined, uri)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get language modes
|
||||||
|
*
|
||||||
|
* @return {*} {GenericObject<any>[]}
|
||||||
|
* @memberof MonacoEditorModel
|
||||||
|
*/
|
||||||
|
getModes(): GenericObject<any>[] {
|
||||||
|
//const list = [];
|
||||||
|
//return list;
|
||||||
|
return monaco.languages.getLanguages();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the editor theme
|
||||||
|
*
|
||||||
|
* @param {string} theme theme name
|
||||||
|
* @memberof MonacoEditorModel
|
||||||
|
*/
|
||||||
|
setTheme(theme: string): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set editor language mode
|
||||||
|
*
|
||||||
|
* The mode object should be in the following format:
|
||||||
|
* ```ts
|
||||||
|
* {
|
||||||
|
* text: string,
|
||||||
|
* mode: string
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @param {GenericObject<any>} m language mode object
|
||||||
|
* @memberof MonacoEditorModel
|
||||||
|
*/
|
||||||
|
setMode(m: GenericObject<any>): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reference to the editor instance
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @type {GenericObject<any>}
|
||||||
|
* @memberof MonacoEditorModel
|
||||||
|
*/
|
||||||
|
private editor: GenericObject<any>;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup the editor
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
* @param {HTMLElement} el editor container DOM
|
||||||
|
* @memberof MonacoEditorModel
|
||||||
|
*/
|
||||||
|
protected editorSetup(el: HTMLElement): void {
|
||||||
|
this.editor = monaco.editor.create(el, {
|
||||||
|
value: "",
|
||||||
|
language: 'textplain'
|
||||||
|
});
|
||||||
|
if(!MonacoEditorModel.modes)
|
||||||
|
{
|
||||||
|
MonacoEditorModel.modes = {};
|
||||||
|
monaco.languages.getLanguages().forEach((el) =>{
|
||||||
|
MonacoEditorModel.modes[el.id] = el;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register to editor event
|
||||||
|
*
|
||||||
|
* @param {string} evt_str event name
|
||||||
|
* @param {() => void} callback callback function
|
||||||
|
* @memberof MonacoEditorModel
|
||||||
|
*/
|
||||||
|
on(evt_str: string, callback: () => void): void {
|
||||||
|
switch (evt_str) {
|
||||||
|
case "input":
|
||||||
|
this.editor.onDidChangeModelContent(callback);
|
||||||
|
break;
|
||||||
|
case "focus":
|
||||||
|
this.editor.onDidFocusEditorText(callback);
|
||||||
|
break;
|
||||||
|
case "changeCursor":
|
||||||
|
this.editor.onDidChangeCursorPosition(callback);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resize the editor
|
||||||
|
*
|
||||||
|
* @memberof MonacoEditorModel
|
||||||
|
*/
|
||||||
|
resize(): void {
|
||||||
|
if(this.editor)
|
||||||
|
this.editor.layout();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Focus on the editor
|
||||||
|
*
|
||||||
|
* @memberof MonacoEditorModel
|
||||||
|
*/
|
||||||
|
focus(): void {
|
||||||
|
if(this.editor)
|
||||||
|
this.editor.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get language mode from path
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
* @param {string} path
|
||||||
|
* @return {*} {GenericObject<any>}
|
||||||
|
* @memberof MonacoEditorModel
|
||||||
|
*/
|
||||||
|
protected getModeForPath(path: string): GenericObject<any> {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the editor status
|
||||||
|
*
|
||||||
|
* @return {*} {GenericObject<any>}
|
||||||
|
* @memberof MonacoEditorModel
|
||||||
|
*/
|
||||||
|
getEditorStatus(): GenericObject<any> {
|
||||||
|
const pos = this.editor.getPosition();
|
||||||
|
const mode = MonacoEditorModel.modes[this.editor.getModel().getModeId()];
|
||||||
|
return {
|
||||||
|
row: pos.lineNumber,
|
||||||
|
column: pos.column,
|
||||||
|
line: this.editor.getModel().getLineCount(),
|
||||||
|
langmode: {
|
||||||
|
text: mode.aliases[0],
|
||||||
|
mode: mode
|
||||||
|
},
|
||||||
|
file: this.currfile.path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get editor value
|
||||||
|
*
|
||||||
|
* @return {*} {string}
|
||||||
|
* @memberof MonacoEditorModel
|
||||||
|
*/
|
||||||
|
getValue(): string {
|
||||||
|
return this.editor.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set editor value
|
||||||
|
*
|
||||||
|
* @param {string} value
|
||||||
|
* @memberof MonacoEditorModel
|
||||||
|
*/
|
||||||
|
setValue(value: string): void {
|
||||||
|
this.editor.setValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
getEditor(): any {
|
||||||
|
return this.editor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1104
Antedit/ts/main.ts
1104
Antedit/ts/main.ts
File diff suppressed because it is too large
Load Diff
7370
Antedit/ts/monaco.d.ts
vendored
Normal file
7370
Antedit/ts/monaco.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -19,6 +19,7 @@ class Blogger extends this.OS.application.BaseApplication
|
|||||||
constructor: (args) ->
|
constructor: (args) ->
|
||||||
super "Blogger", args
|
super "Blogger", args
|
||||||
|
|
||||||
|
|
||||||
main: () ->
|
main: () ->
|
||||||
@user = {}
|
@user = {}
|
||||||
@cvlist = @find "cv-list"
|
@cvlist = @find "cv-list"
|
||||||
|
15
libantosdk/README.md
Normal file
15
libantosdk/README.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# libantosdk
|
||||||
|
This is an example project, generated by AntOS Development Kit
|
||||||
|
|
||||||
|
## Howto
|
||||||
|
Use the CodePad command palette to access to the SDK functionalities:
|
||||||
|
|
||||||
|
1. Create new project
|
||||||
|
2. Init the project from the current folder located in side bar
|
||||||
|
3. Build and run the project
|
||||||
|
4. Release the project in zip package
|
||||||
|
|
||||||
|
## Set up build target
|
||||||
|
|
||||||
|
Open the `project.json` file from the current project tree and add/remove
|
||||||
|
build target entries. Save the file
|
70
libantosdk/build.json
Normal file
70
libantosdk/build.json
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
{
|
||||||
|
"targets":{
|
||||||
|
"clean": {
|
||||||
|
"jobs": [
|
||||||
|
{
|
||||||
|
"name": "vfs-rm",
|
||||||
|
"data": ["build/debug/scheme.html"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"build": {
|
||||||
|
"require": ["ts"],
|
||||||
|
"jobs":[
|
||||||
|
{
|
||||||
|
"name": "vfs-mkdir",
|
||||||
|
"data": ["build","build/debug","build/release"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ts-import",
|
||||||
|
"data": ["core/ts/core.d.ts", "core/ts/jquery.d.ts","core/ts/antos.d.ts"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ts-compile",
|
||||||
|
"data": {
|
||||||
|
"src": ["ts/main.ts"],
|
||||||
|
"dest": "build/debug/main.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"uglify": {
|
||||||
|
"require": ["terser"],
|
||||||
|
"jobs": [
|
||||||
|
{
|
||||||
|
"name":"terser-uglify",
|
||||||
|
"data": ["build/debug/main.js"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"copy": {
|
||||||
|
"jobs": [
|
||||||
|
{
|
||||||
|
"name": "vfs-cp",
|
||||||
|
"data": {
|
||||||
|
"src": [
|
||||||
|
"package.json",
|
||||||
|
"README.md",
|
||||||
|
"scheme.html",
|
||||||
|
"core"
|
||||||
|
],
|
||||||
|
"dest":"build/debug"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"release": {
|
||||||
|
"depend": ["clean","build","uglify", "copy"],
|
||||||
|
"require": ["zip"],
|
||||||
|
"jobs": [
|
||||||
|
{
|
||||||
|
"name": "zip-mk",
|
||||||
|
"data": {
|
||||||
|
"src":"build/debug",
|
||||||
|
"dest":"build/release/libantosdk.zip"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
15
libantosdk/build/debug/README.md
Normal file
15
libantosdk/build/debug/README.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# libantosdk
|
||||||
|
This is an example project, generated by AntOS Development Kit
|
||||||
|
|
||||||
|
## Howto
|
||||||
|
Use the CodePad command palette to access to the SDK functionalities:
|
||||||
|
|
||||||
|
1. Create new project
|
||||||
|
2. Init the project from the current folder located in side bar
|
||||||
|
3. Build and run the project
|
||||||
|
4. Release the project in zip package
|
||||||
|
|
||||||
|
## Set up build target
|
||||||
|
|
||||||
|
Open the `project.json` file from the current project tree and add/remove
|
||||||
|
build target entries. Save the file
|
52
libantosdk/build/debug/core/coffee.worker.js
Normal file
52
libantosdk/build/debug/core/coffee.worker.js
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
importScripts('coffeescript.js');
|
||||||
|
|
||||||
|
class CompileCoffeeJob extends AntOSDKBaseJob {
|
||||||
|
constructor(data)
|
||||||
|
{
|
||||||
|
super(data);
|
||||||
|
}
|
||||||
|
execute()
|
||||||
|
{
|
||||||
|
if(!CoffeeScript)
|
||||||
|
{
|
||||||
|
const e_msg = "CoffeeScript module is not loaded";
|
||||||
|
this.log_error(e_msg);
|
||||||
|
return this.error(e_msg);
|
||||||
|
}
|
||||||
|
// very files all data
|
||||||
|
this.read_files(this.job.data.src)
|
||||||
|
.then((contents) => {
|
||||||
|
const errors = [];
|
||||||
|
for(let i in contents)
|
||||||
|
{
|
||||||
|
const data = contents[i];
|
||||||
|
const file = this.job.data.src[i];
|
||||||
|
try {
|
||||||
|
CoffeeScript.nodes(data);
|
||||||
|
this.log_info(`File ${file} verified`);
|
||||||
|
} catch (ex) {
|
||||||
|
errors.push(ex);
|
||||||
|
this.log_error(`${file}: ${ex.toString()}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(errors.length > 0)
|
||||||
|
{
|
||||||
|
return this.error(errors);
|
||||||
|
}
|
||||||
|
const code = contents.join("\n");
|
||||||
|
const jsrc = CoffeeScript.compile(code);
|
||||||
|
// write to file
|
||||||
|
this.save_file(this.job.data.dest,jsrc)
|
||||||
|
.then(r => {
|
||||||
|
this.log_info(`File ${this.job.data.dest} generated`);
|
||||||
|
this.result(this.job.data.dest);
|
||||||
|
})
|
||||||
|
.catch(e1 => {
|
||||||
|
this.error(e1);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(e => this.error(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
API.jobhandle["coffee-compile"] = CompileCoffeeJob;
|
8
libantosdk/build/debug/core/coffeescript.js
Normal file
8
libantosdk/build/debug/core/coffeescript.js
Normal file
File diff suppressed because one or more lines are too long
2
libantosdk/build/debug/core/terser.min.js
vendored
Normal file
2
libantosdk/build/debug/core/terser.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
50
libantosdk/build/debug/core/terser.worker.js
Normal file
50
libantosdk/build/debug/core/terser.worker.js
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
importScripts('terser.min.js');
|
||||||
|
|
||||||
|
class UglifyCodeJob extends AntOSDKBaseJob {
|
||||||
|
constructor(data)
|
||||||
|
{
|
||||||
|
super(data);
|
||||||
|
}
|
||||||
|
execute() {
|
||||||
|
|
||||||
|
if(!Terser)
|
||||||
|
{
|
||||||
|
const e_msg = "Terser module is not loaded";
|
||||||
|
this.log_error(e_msg);
|
||||||
|
return this.error(e_m);
|
||||||
|
}
|
||||||
|
this.read_files(this.job.data)
|
||||||
|
.then((contents) => {
|
||||||
|
const promises = [];
|
||||||
|
const options = {
|
||||||
|
toplevel: false,
|
||||||
|
compress: {
|
||||||
|
passes: 3,
|
||||||
|
},
|
||||||
|
mangle: true,
|
||||||
|
output: {
|
||||||
|
//beautify: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
for(let i in contents)
|
||||||
|
{
|
||||||
|
|
||||||
|
const result = Terser.minify(contents[i], options);
|
||||||
|
if (result.error) {
|
||||||
|
this.log_error(`${this.job.data[i]}:${result.error}`);
|
||||||
|
promises.push(new Promise((r,e) => e(result.error)));
|
||||||
|
} else {
|
||||||
|
this.log_info(`File ${this.job.data[i]} uglified`);
|
||||||
|
promises.push(this.save_file(this.job.data[i],result.code));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
Promise.all(promises)
|
||||||
|
.then((r) => this.result(r))
|
||||||
|
.catch((e) => this.error(e));
|
||||||
|
})
|
||||||
|
.catch((e1) => this.error(e1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
API.jobhandle["terser-uglify"] = UglifyCodeJob;
|
131
libantosdk/build/debug/core/ts.worker.js
Normal file
131
libantosdk/build/debug/core/ts.worker.js
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
importScripts('typescript.min.js');
|
||||||
|
|
||||||
|
const tslib = {};
|
||||||
|
|
||||||
|
|
||||||
|
class TSJob extends AntOSDKBaseJob {
|
||||||
|
constructor(data)
|
||||||
|
{
|
||||||
|
super(data);
|
||||||
|
}
|
||||||
|
execute(){
|
||||||
|
if(!ts)
|
||||||
|
{
|
||||||
|
const e_msg = "typescript module is not loaded";
|
||||||
|
this.log_error(e_msg);
|
||||||
|
return this.error(e_msg);
|
||||||
|
}
|
||||||
|
switch (this.job.cmd) {
|
||||||
|
case 'ts-import':
|
||||||
|
this.importlib();
|
||||||
|
break;
|
||||||
|
case 'ts-compile':
|
||||||
|
this.compile();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
const err_msg = `Unkown job ${this.job.cmd}`;
|
||||||
|
this.log_error(err_msg);
|
||||||
|
return this.error(err_msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
importlib()
|
||||||
|
{
|
||||||
|
if(!ts)
|
||||||
|
{
|
||||||
|
const e_msg = "typescript module is not loaded";
|
||||||
|
this.log_error(e_msg);
|
||||||
|
return this.error(e_msg);
|
||||||
|
}
|
||||||
|
this.read_files(this.job.data)
|
||||||
|
.then((results) => {
|
||||||
|
for(let i in this.job.data)
|
||||||
|
{
|
||||||
|
const lib = this.job.data[i];
|
||||||
|
if(!tslib[lib])
|
||||||
|
{
|
||||||
|
tslib[lib] = ts.createSourceFile(lib, results[i], ts.ScriptTarget.Latest);
|
||||||
|
this.log_info(`Typescript library ${lib} loaded`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.result("Typescript libraries loaded");
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
this.log_error("Fail to load Typescript module");
|
||||||
|
this.error(e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
compile()
|
||||||
|
{
|
||||||
|
let files = [];
|
||||||
|
const src_files = {};
|
||||||
|
for(let i in tslib)
|
||||||
|
{
|
||||||
|
files.push(i);
|
||||||
|
src_files[i] = tslib[i];
|
||||||
|
}
|
||||||
|
files = files.concat(this.job.data.src);
|
||||||
|
this.read_files(this.job.data.src)
|
||||||
|
.then((contents) => {
|
||||||
|
for(let i in contents)
|
||||||
|
{
|
||||||
|
const m = this.job.data.src[i];
|
||||||
|
src_files[m] = ts.createSourceFile(m, contents[i], ts.ScriptTarget.Latest);
|
||||||
|
}
|
||||||
|
let js_code = "";
|
||||||
|
const host = {
|
||||||
|
fileExists: (path) => {
|
||||||
|
return src_files[path] !== undefined;
|
||||||
|
},
|
||||||
|
directoryExists: (path) => {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
getCurrentDirectory: () => "/",
|
||||||
|
getDirectories: () => [],
|
||||||
|
getCanonicalFileName: (path) => path,
|
||||||
|
getNewLine: () => "\n",
|
||||||
|
getDefaultLibFileName: () => "",
|
||||||
|
getSourceFile: (path) => src_files[path],
|
||||||
|
readFile: (path) => undefined,
|
||||||
|
useCaseSensitiveFileNames: () => true,
|
||||||
|
writeFile: (path, data) => js_code = `${js_code}\n${data}`
|
||||||
|
};
|
||||||
|
const program = ts.createProgram(files, {
|
||||||
|
"target": "es6",
|
||||||
|
"skipLibCheck": true,
|
||||||
|
}, host);
|
||||||
|
const result = program.emit();
|
||||||
|
const diagnostics = result.diagnostics.concat((ts.getPreEmitDiagnostics(program)));
|
||||||
|
const errors = [];
|
||||||
|
if (diagnostics.length > 0) {
|
||||||
|
diagnostics.forEach(diagnostic => {
|
||||||
|
let err_msg = "";
|
||||||
|
if (diagnostic.file) {
|
||||||
|
let { line, character } = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start);
|
||||||
|
let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
|
||||||
|
err_msg = `${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`;
|
||||||
|
} else {
|
||||||
|
err_msg = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
|
||||||
|
}
|
||||||
|
errors.push(err_msg);
|
||||||
|
this.log_error(err_msg);
|
||||||
|
});
|
||||||
|
return this.error(errors);
|
||||||
|
}
|
||||||
|
// write to file
|
||||||
|
this.save_file(this.job.data.dest,js_code)
|
||||||
|
.then(r => {
|
||||||
|
if(r.error)
|
||||||
|
{
|
||||||
|
this.log_error(error);
|
||||||
|
return this.error(r.error);
|
||||||
|
}
|
||||||
|
this.result(this.job.data.dest);
|
||||||
|
})
|
||||||
|
.catch(e1 => this.error(e1));
|
||||||
|
})
|
||||||
|
.catch(e => this.error(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
API.jobhandle["ts-import"] = TSJob;
|
||||||
|
API.jobhandle["ts-compile"] = TSJob;
|
10079
libantosdk/build/debug/core/ts/antos.d.ts
vendored
Normal file
10079
libantosdk/build/debug/core/ts/antos.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
27299
libantosdk/build/debug/core/ts/core.d.ts
vendored
Normal file
27299
libantosdk/build/debug/core/ts/core.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
33483
libantosdk/build/debug/core/ts/jquery.d.ts
vendored
Normal file
33483
libantosdk/build/debug/core/ts/jquery.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
15
libantosdk/build/debug/core/typescript.min.js
vendored
Normal file
15
libantosdk/build/debug/core/typescript.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
464
libantosdk/build/debug/core/worker.js
Normal file
464
libantosdk/build/debug/core/worker.js
Normal file
@ -0,0 +1,464 @@
|
|||||||
|
String.prototype.getlink = function(root)
|
||||||
|
{
|
||||||
|
return API.REST + "/VFS/get/" + this.abspath(root);
|
||||||
|
}
|
||||||
|
String.prototype.abspath = function(root)
|
||||||
|
{
|
||||||
|
const list = this.split("://");
|
||||||
|
if(list.length == 1)
|
||||||
|
{
|
||||||
|
return root + "/" + this;
|
||||||
|
}
|
||||||
|
const proto = list[0];
|
||||||
|
const arr = list[1].split("/");
|
||||||
|
if(proto === "pkg")
|
||||||
|
{
|
||||||
|
const pkg = arr.shift();
|
||||||
|
if(API.pkgs[pkg]) {
|
||||||
|
return API.pkgs[pkg].path + "/" + arr.join("/");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(proto === "sdk")
|
||||||
|
{
|
||||||
|
return `pkg://libantosdk/${arr.join("/")}`.abspath(root);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
const API = {
|
||||||
|
REST: "",
|
||||||
|
jobhandle: {},
|
||||||
|
modules: {},
|
||||||
|
pkgs:{}
|
||||||
|
};
|
||||||
|
|
||||||
|
class AntOSDKBaseJob {
|
||||||
|
|
||||||
|
constructor(data)
|
||||||
|
{
|
||||||
|
this.job = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
result(data) {
|
||||||
|
const result = {
|
||||||
|
id: this.job.id,
|
||||||
|
type: "result",
|
||||||
|
error: false,
|
||||||
|
result: data
|
||||||
|
};
|
||||||
|
postMessage(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
error(msg) {
|
||||||
|
const result = {
|
||||||
|
id: this.job.id,
|
||||||
|
type: "result",
|
||||||
|
error: msg,
|
||||||
|
result: false
|
||||||
|
};
|
||||||
|
postMessage(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
log_info(data) {
|
||||||
|
postMessage({
|
||||||
|
id: this.job.id,
|
||||||
|
type: "log",
|
||||||
|
error: false,
|
||||||
|
result: data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
log_error(data) {
|
||||||
|
postMessage({
|
||||||
|
id: this.job.id,
|
||||||
|
type: "log",
|
||||||
|
error: true,
|
||||||
|
result: data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get(url, type) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const req = new XMLHttpRequest();
|
||||||
|
req.open("GET", url, true);
|
||||||
|
|
||||||
|
if(type)
|
||||||
|
{
|
||||||
|
req.responseType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
req.onload = function() {
|
||||||
|
if (req.readyState === 4 && req.status === 200) {
|
||||||
|
resolve(req.response);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.log_error(req.statusText);
|
||||||
|
reject(req.statusText);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
req.send(null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
post(url, data, type) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const req = new XMLHttpRequest();
|
||||||
|
req.open("POST", url, true);
|
||||||
|
req.setRequestHeader("Content-Type", "application/json");
|
||||||
|
if(type)
|
||||||
|
{
|
||||||
|
req.responseType = type;
|
||||||
|
}
|
||||||
|
req.onload = function() {
|
||||||
|
if (req.readyState === 4 && req.status === 200) {
|
||||||
|
try {
|
||||||
|
const json = JSON.parse(req.response);
|
||||||
|
resolve(json);
|
||||||
|
} catch (e) {
|
||||||
|
resolve(req.response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.log_error(req.statusText);
|
||||||
|
reject(req.statusText);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
req.send(JSON.stringify(data));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
read_files(files)
|
||||||
|
{
|
||||||
|
return new Promise( async (resolve, reject) => {
|
||||||
|
try{
|
||||||
|
let promises = [];
|
||||||
|
for(let file of files)
|
||||||
|
{
|
||||||
|
promises.push(this.meta(file.abspath(this.job.root)));
|
||||||
|
}
|
||||||
|
await Promise.all(promises);
|
||||||
|
promises = [];
|
||||||
|
for(let file of files)
|
||||||
|
{
|
||||||
|
promises.push(this.get(file.getlink(this.job.root)));
|
||||||
|
}
|
||||||
|
const contents = await Promise.all(promises);
|
||||||
|
resolve(contents);
|
||||||
|
} catch (e)
|
||||||
|
{
|
||||||
|
this.log_error(e.toString());
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
cat(files, data)
|
||||||
|
{
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.read_files(files)
|
||||||
|
.then((results) => {
|
||||||
|
resolve(`${data}\n${results.join("\n")}`);
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
reject(e);
|
||||||
|
this.log_error(e.toString());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
save_file(file, data, t)
|
||||||
|
{
|
||||||
|
return new Promise((res,rej) => {
|
||||||
|
this.b64(t,data)
|
||||||
|
.then((enc) => {
|
||||||
|
this.post(API.REST+"/VFS/write", {
|
||||||
|
path: file.abspath(this.job.root),
|
||||||
|
data: enc
|
||||||
|
})
|
||||||
|
.then(d => {
|
||||||
|
if(d.error){
|
||||||
|
this.log_error(`Unable to saved to ${file}: ${d.error}`);
|
||||||
|
return rej(d.error);
|
||||||
|
}
|
||||||
|
this.log_info(`${file} saved`);
|
||||||
|
res(d);
|
||||||
|
})
|
||||||
|
.catch(e1 => {
|
||||||
|
this.log_error(`Unable to saved to ${file}: ${e1.toString()}`);
|
||||||
|
rej(e1);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
this.log_error(`Unable to saved to ${file}: ${e.toString()}`);
|
||||||
|
rej(e);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
b64(t, data) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if(t === "base64")
|
||||||
|
return resolve(data);
|
||||||
|
let m = t === "object" ? "text/plain" : t;
|
||||||
|
if(!t)
|
||||||
|
m = "text/plain";
|
||||||
|
if (t === "object" || typeof data === "string") {
|
||||||
|
let b64;
|
||||||
|
if (t === "object") {
|
||||||
|
b64 = btoa(JSON.stringify(data, undefined, 4));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
b64 = btoa(data);
|
||||||
|
}
|
||||||
|
b64 = `data:${m};base64,${b64}`;
|
||||||
|
return resolve(b64);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//blob
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.readAsDataURL(data);
|
||||||
|
reader.onload = () => resolve(reader.result);
|
||||||
|
return (reader.onerror = (e) => reject(e));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(files)
|
||||||
|
{
|
||||||
|
const promises = [];
|
||||||
|
for(const file of files)
|
||||||
|
{
|
||||||
|
promises.push(new Promise((resolve, reject) =>{
|
||||||
|
this.post(API.REST+"/VFS/delete", {path: file.abspath(this.job.root)})
|
||||||
|
.then(r => {
|
||||||
|
if(r.error)
|
||||||
|
{
|
||||||
|
this.log_error(`${file}:${r.error}`);
|
||||||
|
return reject(r.error);
|
||||||
|
}
|
||||||
|
this.log_info(`${file} deleted`);
|
||||||
|
return resolve(r.result);
|
||||||
|
})
|
||||||
|
.catch(e =>{
|
||||||
|
this.log_error(e.toString());
|
||||||
|
reject(e);
|
||||||
|
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return Promise.all(promises);
|
||||||
|
}
|
||||||
|
|
||||||
|
mkdir(list) {
|
||||||
|
return new Promise( async (resolve, reject) => {
|
||||||
|
try {
|
||||||
|
if (list.length === 0) {
|
||||||
|
return resolve(true);
|
||||||
|
}
|
||||||
|
const dir = list.splice(0, 1)[0];
|
||||||
|
const ret = await this.post(API.REST+"/VFS/mkdir", {path: dir.abspath(this.job.root)});
|
||||||
|
if(ret.error)
|
||||||
|
{
|
||||||
|
this.log_error(`${dir}: ${ret.error}`);
|
||||||
|
return reject(ret.error);
|
||||||
|
}
|
||||||
|
this.log_info(`${dir} created`);
|
||||||
|
await this.mkdir(list);
|
||||||
|
resolve(true);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
this.log_error(e.toString());
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(files, to) {
|
||||||
|
const promises = [];
|
||||||
|
|
||||||
|
for (const path of files.map(f =>f.abspath(this.job.root))) {
|
||||||
|
promises.push(new Promise(async (resolve, reject) => {
|
||||||
|
try {
|
||||||
|
const file = path.split("/").filter(s=>s!="").pop();
|
||||||
|
const tof = `${to}/${file}`;
|
||||||
|
const meta = await this.meta(path);
|
||||||
|
if (meta.type === "dir") {
|
||||||
|
await this.mkdir([tof]);
|
||||||
|
const dirs = await this.scandir(path);
|
||||||
|
const files = dirs.map((v) => v.path);
|
||||||
|
if (files.length > 0) {
|
||||||
|
await this.copy(files, tof);
|
||||||
|
}
|
||||||
|
resolve(undefined);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const ret = await this.read_files([path], "arraybuffer");
|
||||||
|
const blob = new Blob([ret[0]], {
|
||||||
|
type: meta.mime});
|
||||||
|
await this.save_file(tof, blob,"binary");
|
||||||
|
this.log_info(`COPIED: ${path} -> ${tof}`);
|
||||||
|
resolve(undefined);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.log_error(error.toString());
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return Promise.all(promises);
|
||||||
|
}
|
||||||
|
|
||||||
|
meta(path)
|
||||||
|
{
|
||||||
|
const file = path.abspath(this.job.root);
|
||||||
|
return new Promise((resolve,reject) =>{
|
||||||
|
this.post(API.REST+"/VFS/fileinfo", {path:file})
|
||||||
|
.then(json =>{
|
||||||
|
if(json.error)
|
||||||
|
{
|
||||||
|
this.log_error(`${file}: ${json.error}`);
|
||||||
|
return reject(json.error);
|
||||||
|
}
|
||||||
|
return resolve(json.result);
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
this.log_error(e.toString());
|
||||||
|
resolve(e);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
scandir(path)
|
||||||
|
{
|
||||||
|
return new Promise((resolve,reject) =>{
|
||||||
|
this.post(API.REST+"/VFS/scandir", {path:path.abspath(this.job.root)})
|
||||||
|
.then(json =>{
|
||||||
|
if(json.error)
|
||||||
|
return reject(json.error);
|
||||||
|
return resolve(json.result);
|
||||||
|
})
|
||||||
|
.catch(e =>{
|
||||||
|
this.log_error(e.toString());
|
||||||
|
resolve(e);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
execute() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UnknownJob extends AntOSDKBaseJob {
|
||||||
|
constructor(data)
|
||||||
|
{
|
||||||
|
super(data);
|
||||||
|
}
|
||||||
|
execute() {
|
||||||
|
this.log_error("Unknown job " + this.job.cmd);
|
||||||
|
this.error("Unknown job " + this.job.cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SDKSetup extends AntOSDKBaseJob {
|
||||||
|
constructor(data)
|
||||||
|
{
|
||||||
|
super(data);
|
||||||
|
}
|
||||||
|
execute() {
|
||||||
|
for(let k in this.job.data)
|
||||||
|
{
|
||||||
|
API[k] = this.job.data[k];
|
||||||
|
}
|
||||||
|
this.result("ANTOS Sdk set up");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoadScritpJob extends AntOSDKBaseJob {
|
||||||
|
constructor(data)
|
||||||
|
{
|
||||||
|
super(data);
|
||||||
|
}
|
||||||
|
execute() {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for(let lib of this.job.data)
|
||||||
|
{
|
||||||
|
if(!API.modules[lib])
|
||||||
|
{
|
||||||
|
this.log_info("Importing module:" + lib);
|
||||||
|
importScripts(lib);
|
||||||
|
API.modules[lib] = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
console.log("Module " + lib + " is already loaded");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.log_info("All Modules loaded" );
|
||||||
|
this.result(this.job.data);
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
this.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class VFSJob extends AntOSDKBaseJob {
|
||||||
|
constructor(data)
|
||||||
|
{
|
||||||
|
super(data);
|
||||||
|
}
|
||||||
|
execute() {
|
||||||
|
const arr = this.job.cmd.split("-");
|
||||||
|
if(arr.length > 1)
|
||||||
|
{
|
||||||
|
switch (arr[1]) {
|
||||||
|
case 'cat':
|
||||||
|
this.cat(this.job.data.src,"")
|
||||||
|
.then(data => {
|
||||||
|
this.save_file(this.job.data.dest, data)
|
||||||
|
.then(r => this.result(r))
|
||||||
|
.catch(e1 => this.error(e1));
|
||||||
|
})
|
||||||
|
.catch(e => this.error(e));
|
||||||
|
break;
|
||||||
|
case 'rm':
|
||||||
|
this.delete(this.job.data)
|
||||||
|
.then(d => this.result(d))
|
||||||
|
.catch(e => this.error(e));
|
||||||
|
break;
|
||||||
|
case 'mkdir':
|
||||||
|
this.mkdir(this.job.data)
|
||||||
|
.then(d => this.result(d))
|
||||||
|
.catch(e => this.error(e));
|
||||||
|
break;
|
||||||
|
case 'cp':
|
||||||
|
this.copy(this.job.data.src, this.job.data.dest)
|
||||||
|
.then(d => this.result(d))
|
||||||
|
.catch(e => this.error(e));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.error("Unknown command: " + this.job.cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.error("Unknown command: " + this.job.cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
API.jobhandle["sdk-import"] = LoadScritpJob;
|
||||||
|
API.jobhandle["sdk-setup"] = SDKSetup;
|
||||||
|
API.jobhandle["vfs-cat"] = VFSJob;
|
||||||
|
API.jobhandle["vfs-rm"] = VFSJob;
|
||||||
|
API.jobhandle["vfs-mkdir"] = VFSJob;
|
||||||
|
API.jobhandle["vfs-cp"] = VFSJob;
|
||||||
|
|
||||||
|
onmessage = (e) => {
|
||||||
|
if(API.jobhandle[e.data.cmd])
|
||||||
|
{
|
||||||
|
return (new API.jobhandle[e.data.cmd](e.data)).execute();
|
||||||
|
}
|
||||||
|
(new UnknownJob(e.data)).execute();
|
||||||
|
}
|
98
libantosdk/build/debug/core/zip.worker.js
Normal file
98
libantosdk/build/debug/core/zip.worker.js
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
importScripts("os://scripts/jszip.min.js".getlink());
|
||||||
|
|
||||||
|
|
||||||
|
class ZipJob extends AntOSDKBaseJob {
|
||||||
|
constructor(data)
|
||||||
|
{
|
||||||
|
super(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
execute()
|
||||||
|
{
|
||||||
|
if(!JSZip)
|
||||||
|
{
|
||||||
|
const e_msg = "JSZip module is not loaded";
|
||||||
|
this.log_error(e_msg);
|
||||||
|
return this.error(e_msg);
|
||||||
|
}
|
||||||
|
switch (this.job.cmd) {
|
||||||
|
case 'zip-mk':
|
||||||
|
this.mkar()
|
||||||
|
.then(d => this.result(d))
|
||||||
|
.catch(e => this.error(e));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
const err_msg = `Unkown job ${this.job.cmd}`;
|
||||||
|
this.log_error(err_msg);
|
||||||
|
return this.error(err_msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
aradd(list, zip, base)
|
||||||
|
{
|
||||||
|
const promises = [];
|
||||||
|
for (const file of list) {
|
||||||
|
promises.push(new Promise(async (resolve, reject) => {
|
||||||
|
try {
|
||||||
|
const basename = file.split("/").pop();
|
||||||
|
const meta = await this.meta(file);
|
||||||
|
if (meta.type == "dir") {
|
||||||
|
const ret = await this.scandir(file);
|
||||||
|
const dirs = ret.map(v => v.path);
|
||||||
|
if (dirs.length > 0) {
|
||||||
|
await this.aradd(dirs, zip, `${base}${basename}/`);
|
||||||
|
resolve(undefined);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resolve(undefined);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const ret = await this.read_files([file], "arraybuffer");
|
||||||
|
const u_data = ret[0];
|
||||||
|
const z_path = `${base}${basename}`.replace(
|
||||||
|
/^\/+|\/+$/g,
|
||||||
|
"");
|
||||||
|
zip.file(z_path, u_data, { binary: true });
|
||||||
|
this.log_info(`${file} added to zip`);
|
||||||
|
resolve(undefined);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.log_error(`${file}: ${error.toString()}`);
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return Promise.all(promises);
|
||||||
|
}
|
||||||
|
|
||||||
|
mkar()
|
||||||
|
{
|
||||||
|
const src = this.job.data.src;
|
||||||
|
const dest = this.job.data.dest;
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
try {
|
||||||
|
const zip = new JSZip();
|
||||||
|
const meta = await this.meta(this.job.data.src);
|
||||||
|
if(meta.type === "file")
|
||||||
|
{
|
||||||
|
await this.aradd([src], zip, "/");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const ret = await this.scandir(src);
|
||||||
|
await this.aradd(ret.map(v => v.path), zip, "/");
|
||||||
|
}
|
||||||
|
const z_data = await zip.generateAsync({ type: "base64" });
|
||||||
|
await this.save_file(dest, "data:application/zip;base64," + z_data, "base64");
|
||||||
|
this.log_info(`Zip archive saved in ${dest}`);
|
||||||
|
resolve(dest);
|
||||||
|
} catch (error) {
|
||||||
|
this.log_error(`Unable to commpress ${src} -> ${dest}: ${error.toString()}`);
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
API.jobhandle["zip-mk"] = ZipJob;
|
1
libantosdk/build/debug/main.js
Normal file
1
libantosdk/build/debug/main.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
var OS;!function(t){let e;!function(e){class r{constructor(e){this.worker=new Worker(e.asFileHandle().getlink()),this.jobs={},this.worker.onmessage=t=>{let e=t.data,r=this.jobs[e.id];r?"log"===e.type?r.logger&&(e.error?r.logger.error(e.result):r.logger.info(e.result)):(r.callback(e),delete this.jobs[e.id]):console.log("Unable to identify result of job",e.id,e)};const r={};for(const e in t.setting.system.packages){const o=t.setting.system.packages[e];r[e]={path:o.path,name:o.pkgname}}this.submit("sdk-setup",{REST:t.API.REST,pkgs:r})}newJobID(){return"job_"+Math.random().toString(36).replace(".","")}exectue_job(t,e,r,o,s){const i=this.newJobID(),n={id:i,cmd:t,data:e,root:r};this.jobs[i]={callback:o,logger:s},this.worker.postMessage(n)}submit(t,e,r,o){return new Promise((s,i)=>{this.exectue_job(t,e,r,t=>{if(t.error)return i(t.error);s(t.result)},o)})}terminate(){this.worker.terminate()}}class o{constructor(t,e){this.root=e,this.logger=t,o.worker||(o.worker=new r("pkg://libantosdk/core/worker.js"))}require(t){return this.run("sdk-import",t.map(t=>t+".worker.js"))}compile(t,e){return new Promise(async(r,o)=>{try{await this.require([t]),r(await this.run(t+"-compile",e))}catch(t){o(__e(t))}})}run(t,e){return o.worker.submit(t,e,this.root,this.logger)}batch(t,e){return e.root&&(this.root=e.root),new Promise(async(r,o)=>{try{e.targets||o("No target found");for(const r of t){const t=e.targets[r];if(!t)return o(__("No target: "+r));if(t.depend&&await this.batch(t.depend,e),t.require&&await this.require(t.require),this.logger&&this.logger.info(__(`### RUNNING STAGE: ${r}###`).__()),t.jobs)for(const e of t.jobs)await this.run(e.name,e.data)}r(void 0)}catch(t){o(t)}})}}let s;e.AntOSDKBuilder=o,function(t){class e extends t.RemoteFileHandle{constructor(t){super(t);const e="pkg://libantosdk/"+this.genealogy.join("/");this.setPath(e.asFileHandle().path)}}t.SDKFileHandle=e,t.register("^sdk$",e)}(s=e.VFS||(e.VFS={}))}(e=t.API||(t.API={}))}(OS||(OS={}));
|
15
libantosdk/build/debug/package.json
Normal file
15
libantosdk/build/debug/package.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"pkgname": "libantosdk",
|
||||||
|
"name":"AntOSDK",
|
||||||
|
"description":"AntOS Software Development Kit",
|
||||||
|
"info":{
|
||||||
|
"author": "Xuan Sang LE",
|
||||||
|
"email": "mrsang@iohub.dev"
|
||||||
|
},
|
||||||
|
"version":"0.0.2-a",
|
||||||
|
"category":"Other",
|
||||||
|
"iconclass":"fa fa-cog",
|
||||||
|
"mimes":["none"],
|
||||||
|
"dependencies":[],
|
||||||
|
"locale": {}
|
||||||
|
}
|
16
libantosdk/build/debug/scheme.html
Normal file
16
libantosdk/build/debug/scheme.html
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<afx-app-window apptitle="__(Test SDK)" width="450" height="500" data-id="TestSDK">
|
||||||
|
<afx-vbox >
|
||||||
|
<div data-height="10"></div>
|
||||||
|
<afx-hbox data-id="wrapper">
|
||||||
|
<div data-width="10"></div>
|
||||||
|
<div data-id="container"></div>
|
||||||
|
<div data-width="10"></div>
|
||||||
|
</afx-hbox>
|
||||||
|
<div data-height="5"></div>
|
||||||
|
<afx-hbox data-height="23" style="text-align: right;">
|
||||||
|
<afx-button data-id="btnsend" text="__(Send)"></afx-button>
|
||||||
|
<div data-width="5"></div>
|
||||||
|
</afx-hbox>
|
||||||
|
<div data-height="10"></div>
|
||||||
|
</afx-vbox>
|
||||||
|
</afx-app-window>
|
BIN
libantosdk/build/release/libantosdk.zip
Normal file
BIN
libantosdk/build/release/libantosdk.zip
Normal file
Binary file not shown.
52
libantosdk/core/coffee.worker.js
Normal file
52
libantosdk/core/coffee.worker.js
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
importScripts('coffeescript.js');
|
||||||
|
|
||||||
|
class CompileCoffeeJob extends AntOSDKBaseJob {
|
||||||
|
constructor(data)
|
||||||
|
{
|
||||||
|
super(data);
|
||||||
|
}
|
||||||
|
execute()
|
||||||
|
{
|
||||||
|
if(!CoffeeScript)
|
||||||
|
{
|
||||||
|
const e_msg = "CoffeeScript module is not loaded";
|
||||||
|
this.log_error(e_msg);
|
||||||
|
return this.error(e_msg);
|
||||||
|
}
|
||||||
|
// very files all data
|
||||||
|
this.read_files(this.job.data.src)
|
||||||
|
.then((contents) => {
|
||||||
|
const errors = [];
|
||||||
|
for(let i in contents)
|
||||||
|
{
|
||||||
|
const data = contents[i];
|
||||||
|
const file = this.job.data.src[i];
|
||||||
|
try {
|
||||||
|
CoffeeScript.nodes(data);
|
||||||
|
this.log_info(`File ${file} verified`);
|
||||||
|
} catch (ex) {
|
||||||
|
errors.push(ex);
|
||||||
|
this.log_error(`${file}: ${ex.toString()}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(errors.length > 0)
|
||||||
|
{
|
||||||
|
return this.error(errors);
|
||||||
|
}
|
||||||
|
const code = contents.join("\n");
|
||||||
|
const jsrc = CoffeeScript.compile(code);
|
||||||
|
// write to file
|
||||||
|
this.save_file(this.job.data.dest,jsrc)
|
||||||
|
.then(r => {
|
||||||
|
this.log_info(`File ${this.job.data.dest} generated`);
|
||||||
|
this.result(this.job.data.dest);
|
||||||
|
})
|
||||||
|
.catch(e1 => {
|
||||||
|
this.error(e1);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(e => this.error(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
API.jobhandle["coffee-compile"] = CompileCoffeeJob;
|
8
libantosdk/core/coffeescript.js
Normal file
8
libantosdk/core/coffeescript.js
Normal file
File diff suppressed because one or more lines are too long
2
libantosdk/core/terser.min.js
vendored
Normal file
2
libantosdk/core/terser.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
50
libantosdk/core/terser.worker.js
Normal file
50
libantosdk/core/terser.worker.js
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
importScripts('terser.min.js');
|
||||||
|
|
||||||
|
class UglifyCodeJob extends AntOSDKBaseJob {
|
||||||
|
constructor(data)
|
||||||
|
{
|
||||||
|
super(data);
|
||||||
|
}
|
||||||
|
execute() {
|
||||||
|
|
||||||
|
if(!Terser)
|
||||||
|
{
|
||||||
|
const e_msg = "Terser module is not loaded";
|
||||||
|
this.log_error(e_msg);
|
||||||
|
return this.error(e_m);
|
||||||
|
}
|
||||||
|
this.read_files(this.job.data)
|
||||||
|
.then((contents) => {
|
||||||
|
const promises = [];
|
||||||
|
const options = {
|
||||||
|
toplevel: false,
|
||||||
|
compress: {
|
||||||
|
passes: 3,
|
||||||
|
},
|
||||||
|
mangle: true,
|
||||||
|
output: {
|
||||||
|
//beautify: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
for(let i in contents)
|
||||||
|
{
|
||||||
|
|
||||||
|
const result = Terser.minify(contents[i], options);
|
||||||
|
if (result.error) {
|
||||||
|
this.log_error(`${this.job.data[i]}:${result.error}`);
|
||||||
|
promises.push(new Promise((r,e) => e(result.error)));
|
||||||
|
} else {
|
||||||
|
this.log_info(`File ${this.job.data[i]} uglified`);
|
||||||
|
promises.push(this.save_file(this.job.data[i],result.code));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
Promise.all(promises)
|
||||||
|
.then((r) => this.result(r))
|
||||||
|
.catch((e) => this.error(e));
|
||||||
|
})
|
||||||
|
.catch((e1) => this.error(e1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
API.jobhandle["terser-uglify"] = UglifyCodeJob;
|
131
libantosdk/core/ts.worker.js
Normal file
131
libantosdk/core/ts.worker.js
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
importScripts('typescript.min.js');
|
||||||
|
|
||||||
|
const tslib = {};
|
||||||
|
|
||||||
|
|
||||||
|
class TSJob extends AntOSDKBaseJob {
|
||||||
|
constructor(data)
|
||||||
|
{
|
||||||
|
super(data);
|
||||||
|
}
|
||||||
|
execute(){
|
||||||
|
if(!ts)
|
||||||
|
{
|
||||||
|
const e_msg = "typescript module is not loaded";
|
||||||
|
this.log_error(e_msg);
|
||||||
|
return this.error(e_msg);
|
||||||
|
}
|
||||||
|
switch (this.job.cmd) {
|
||||||
|
case 'ts-import':
|
||||||
|
this.importlib();
|
||||||
|
break;
|
||||||
|
case 'ts-compile':
|
||||||
|
this.compile();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
const err_msg = `Unkown job ${this.job.cmd}`;
|
||||||
|
this.log_error(err_msg);
|
||||||
|
return this.error(err_msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
importlib()
|
||||||
|
{
|
||||||
|
if(!ts)
|
||||||
|
{
|
||||||
|
const e_msg = "typescript module is not loaded";
|
||||||
|
this.log_error(e_msg);
|
||||||
|
return this.error(e_msg);
|
||||||
|
}
|
||||||
|
this.read_files(this.job.data)
|
||||||
|
.then((results) => {
|
||||||
|
for(let i in this.job.data)
|
||||||
|
{
|
||||||
|
const lib = this.job.data[i];
|
||||||
|
if(!tslib[lib])
|
||||||
|
{
|
||||||
|
tslib[lib] = ts.createSourceFile(lib, results[i], ts.ScriptTarget.Latest);
|
||||||
|
this.log_info(`Typescript library ${lib} loaded`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.result("Typescript libraries loaded");
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
this.log_error("Fail to load Typescript module");
|
||||||
|
this.error(e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
compile()
|
||||||
|
{
|
||||||
|
let files = [];
|
||||||
|
const src_files = {};
|
||||||
|
for(let i in tslib)
|
||||||
|
{
|
||||||
|
files.push(i);
|
||||||
|
src_files[i] = tslib[i];
|
||||||
|
}
|
||||||
|
files = files.concat(this.job.data.src);
|
||||||
|
this.read_files(this.job.data.src)
|
||||||
|
.then((contents) => {
|
||||||
|
for(let i in contents)
|
||||||
|
{
|
||||||
|
const m = this.job.data.src[i];
|
||||||
|
src_files[m] = ts.createSourceFile(m, contents[i], ts.ScriptTarget.Latest);
|
||||||
|
}
|
||||||
|
let js_code = "";
|
||||||
|
const host = {
|
||||||
|
fileExists: (path) => {
|
||||||
|
return src_files[path] !== undefined;
|
||||||
|
},
|
||||||
|
directoryExists: (path) => {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
getCurrentDirectory: () => "/",
|
||||||
|
getDirectories: () => [],
|
||||||
|
getCanonicalFileName: (path) => path,
|
||||||
|
getNewLine: () => "\n",
|
||||||
|
getDefaultLibFileName: () => "",
|
||||||
|
getSourceFile: (path) => src_files[path],
|
||||||
|
readFile: (path) => undefined,
|
||||||
|
useCaseSensitiveFileNames: () => true,
|
||||||
|
writeFile: (path, data) => js_code = `${js_code}\n${data}`
|
||||||
|
};
|
||||||
|
const program = ts.createProgram(files, {
|
||||||
|
"target": "es6",
|
||||||
|
"skipLibCheck": true,
|
||||||
|
}, host);
|
||||||
|
const result = program.emit();
|
||||||
|
const diagnostics = result.diagnostics.concat((ts.getPreEmitDiagnostics(program)));
|
||||||
|
const errors = [];
|
||||||
|
if (diagnostics.length > 0) {
|
||||||
|
diagnostics.forEach(diagnostic => {
|
||||||
|
let err_msg = "";
|
||||||
|
if (diagnostic.file) {
|
||||||
|
let { line, character } = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start);
|
||||||
|
let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
|
||||||
|
err_msg = `${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`;
|
||||||
|
} else {
|
||||||
|
err_msg = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
|
||||||
|
}
|
||||||
|
errors.push(err_msg);
|
||||||
|
this.log_error(err_msg);
|
||||||
|
});
|
||||||
|
return this.error(errors);
|
||||||
|
}
|
||||||
|
// write to file
|
||||||
|
this.save_file(this.job.data.dest,js_code)
|
||||||
|
.then(r => {
|
||||||
|
if(r.error)
|
||||||
|
{
|
||||||
|
this.log_error(error);
|
||||||
|
return this.error(r.error);
|
||||||
|
}
|
||||||
|
this.result(this.job.data.dest);
|
||||||
|
})
|
||||||
|
.catch(e1 => this.error(e1));
|
||||||
|
})
|
||||||
|
.catch(e => this.error(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
API.jobhandle["ts-import"] = TSJob;
|
||||||
|
API.jobhandle["ts-compile"] = TSJob;
|
10079
libantosdk/core/ts/antos.d.ts
vendored
Normal file
10079
libantosdk/core/ts/antos.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
27299
libantosdk/core/ts/core.d.ts
vendored
Normal file
27299
libantosdk/core/ts/core.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
33483
libantosdk/core/ts/jquery.d.ts
vendored
Normal file
33483
libantosdk/core/ts/jquery.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
15
libantosdk/core/typescript.min.js
vendored
Normal file
15
libantosdk/core/typescript.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
464
libantosdk/core/worker.js
Normal file
464
libantosdk/core/worker.js
Normal file
@ -0,0 +1,464 @@
|
|||||||
|
String.prototype.getlink = function(root)
|
||||||
|
{
|
||||||
|
return API.REST + "/VFS/get/" + this.abspath(root);
|
||||||
|
}
|
||||||
|
String.prototype.abspath = function(root)
|
||||||
|
{
|
||||||
|
const list = this.split("://");
|
||||||
|
if(list.length == 1)
|
||||||
|
{
|
||||||
|
return root + "/" + this;
|
||||||
|
}
|
||||||
|
const proto = list[0];
|
||||||
|
const arr = list[1].split("/");
|
||||||
|
if(proto === "pkg")
|
||||||
|
{
|
||||||
|
const pkg = arr.shift();
|
||||||
|
if(API.pkgs[pkg]) {
|
||||||
|
return API.pkgs[pkg].path + "/" + arr.join("/");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(proto === "sdk")
|
||||||
|
{
|
||||||
|
return `pkg://libantosdk/${arr.join("/")}`.abspath(root);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
const API = {
|
||||||
|
REST: "",
|
||||||
|
jobhandle: {},
|
||||||
|
modules: {},
|
||||||
|
pkgs:{}
|
||||||
|
};
|
||||||
|
|
||||||
|
class AntOSDKBaseJob {
|
||||||
|
|
||||||
|
constructor(data)
|
||||||
|
{
|
||||||
|
this.job = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
result(data) {
|
||||||
|
const result = {
|
||||||
|
id: this.job.id,
|
||||||
|
type: "result",
|
||||||
|
error: false,
|
||||||
|
result: data
|
||||||
|
};
|
||||||
|
postMessage(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
error(msg) {
|
||||||
|
const result = {
|
||||||
|
id: this.job.id,
|
||||||
|
type: "result",
|
||||||
|
error: msg,
|
||||||
|
result: false
|
||||||
|
};
|
||||||
|
postMessage(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
log_info(data) {
|
||||||
|
postMessage({
|
||||||
|
id: this.job.id,
|
||||||
|
type: "log",
|
||||||
|
error: false,
|
||||||
|
result: data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
log_error(data) {
|
||||||
|
postMessage({
|
||||||
|
id: this.job.id,
|
||||||
|
type: "log",
|
||||||
|
error: true,
|
||||||
|
result: data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get(url, type) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const req = new XMLHttpRequest();
|
||||||
|
req.open("GET", url, true);
|
||||||
|
|
||||||
|
if(type)
|
||||||
|
{
|
||||||
|
req.responseType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
req.onload = function() {
|
||||||
|
if (req.readyState === 4 && req.status === 200) {
|
||||||
|
resolve(req.response);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.log_error(req.statusText);
|
||||||
|
reject(req.statusText);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
req.send(null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
post(url, data, type) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const req = new XMLHttpRequest();
|
||||||
|
req.open("POST", url, true);
|
||||||
|
req.setRequestHeader("Content-Type", "application/json");
|
||||||
|
if(type)
|
||||||
|
{
|
||||||
|
req.responseType = type;
|
||||||
|
}
|
||||||
|
req.onload = function() {
|
||||||
|
if (req.readyState === 4 && req.status === 200) {
|
||||||
|
try {
|
||||||
|
const json = JSON.parse(req.response);
|
||||||
|
resolve(json);
|
||||||
|
} catch (e) {
|
||||||
|
resolve(req.response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.log_error(req.statusText);
|
||||||
|
reject(req.statusText);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
req.send(JSON.stringify(data));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
read_files(files)
|
||||||
|
{
|
||||||
|
return new Promise( async (resolve, reject) => {
|
||||||
|
try{
|
||||||
|
let promises = [];
|
||||||
|
for(let file of files)
|
||||||
|
{
|
||||||
|
promises.push(this.meta(file.abspath(this.job.root)));
|
||||||
|
}
|
||||||
|
await Promise.all(promises);
|
||||||
|
promises = [];
|
||||||
|
for(let file of files)
|
||||||
|
{
|
||||||
|
promises.push(this.get(file.getlink(this.job.root)));
|
||||||
|
}
|
||||||
|
const contents = await Promise.all(promises);
|
||||||
|
resolve(contents);
|
||||||
|
} catch (e)
|
||||||
|
{
|
||||||
|
this.log_error(e.toString());
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
cat(files, data)
|
||||||
|
{
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.read_files(files)
|
||||||
|
.then((results) => {
|
||||||
|
resolve(`${data}\n${results.join("\n")}`);
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
reject(e);
|
||||||
|
this.log_error(e.toString());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
save_file(file, data, t)
|
||||||
|
{
|
||||||
|
return new Promise((res,rej) => {
|
||||||
|
this.b64(t,data)
|
||||||
|
.then((enc) => {
|
||||||
|
this.post(API.REST+"/VFS/write", {
|
||||||
|
path: file.abspath(this.job.root),
|
||||||
|
data: enc
|
||||||
|
})
|
||||||
|
.then(d => {
|
||||||
|
if(d.error){
|
||||||
|
this.log_error(`Unable to saved to ${file}: ${d.error}`);
|
||||||
|
return rej(d.error);
|
||||||
|
}
|
||||||
|
this.log_info(`${file} saved`);
|
||||||
|
res(d);
|
||||||
|
})
|
||||||
|
.catch(e1 => {
|
||||||
|
this.log_error(`Unable to saved to ${file}: ${e1.toString()}`);
|
||||||
|
rej(e1);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
this.log_error(`Unable to saved to ${file}: ${e.toString()}`);
|
||||||
|
rej(e);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
b64(t, data) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if(t === "base64")
|
||||||
|
return resolve(data);
|
||||||
|
let m = t === "object" ? "text/plain" : t;
|
||||||
|
if(!t)
|
||||||
|
m = "text/plain";
|
||||||
|
if (t === "object" || typeof data === "string") {
|
||||||
|
let b64;
|
||||||
|
if (t === "object") {
|
||||||
|
b64 = btoa(JSON.stringify(data, undefined, 4));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
b64 = btoa(data);
|
||||||
|
}
|
||||||
|
b64 = `data:${m};base64,${b64}`;
|
||||||
|
return resolve(b64);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//blob
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.readAsDataURL(data);
|
||||||
|
reader.onload = () => resolve(reader.result);
|
||||||
|
return (reader.onerror = (e) => reject(e));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(files)
|
||||||
|
{
|
||||||
|
const promises = [];
|
||||||
|
for(const file of files)
|
||||||
|
{
|
||||||
|
promises.push(new Promise((resolve, reject) =>{
|
||||||
|
this.post(API.REST+"/VFS/delete", {path: file.abspath(this.job.root)})
|
||||||
|
.then(r => {
|
||||||
|
if(r.error)
|
||||||
|
{
|
||||||
|
this.log_error(`${file}:${r.error}`);
|
||||||
|
return reject(r.error);
|
||||||
|
}
|
||||||
|
this.log_info(`${file} deleted`);
|
||||||
|
return resolve(r.result);
|
||||||
|
})
|
||||||
|
.catch(e =>{
|
||||||
|
this.log_error(e.toString());
|
||||||
|
reject(e);
|
||||||
|
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return Promise.all(promises);
|
||||||
|
}
|
||||||
|
|
||||||
|
mkdir(list) {
|
||||||
|
return new Promise( async (resolve, reject) => {
|
||||||
|
try {
|
||||||
|
if (list.length === 0) {
|
||||||
|
return resolve(true);
|
||||||
|
}
|
||||||
|
const dir = list.splice(0, 1)[0];
|
||||||
|
const ret = await this.post(API.REST+"/VFS/mkdir", {path: dir.abspath(this.job.root)});
|
||||||
|
if(ret.error)
|
||||||
|
{
|
||||||
|
this.log_error(`${dir}: ${ret.error}`);
|
||||||
|
return reject(ret.error);
|
||||||
|
}
|
||||||
|
this.log_info(`${dir} created`);
|
||||||
|
await this.mkdir(list);
|
||||||
|
resolve(true);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
this.log_error(e.toString());
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(files, to) {
|
||||||
|
const promises = [];
|
||||||
|
|
||||||
|
for (const path of files.map(f =>f.abspath(this.job.root))) {
|
||||||
|
promises.push(new Promise(async (resolve, reject) => {
|
||||||
|
try {
|
||||||
|
const file = path.split("/").filter(s=>s!="").pop();
|
||||||
|
const tof = `${to}/${file}`;
|
||||||
|
const meta = await this.meta(path);
|
||||||
|
if (meta.type === "dir") {
|
||||||
|
await this.mkdir([tof]);
|
||||||
|
const dirs = await this.scandir(path);
|
||||||
|
const files = dirs.map((v) => v.path);
|
||||||
|
if (files.length > 0) {
|
||||||
|
await this.copy(files, tof);
|
||||||
|
}
|
||||||
|
resolve(undefined);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const ret = await this.read_files([path], "arraybuffer");
|
||||||
|
const blob = new Blob([ret[0]], {
|
||||||
|
type: meta.mime});
|
||||||
|
await this.save_file(tof, blob,"binary");
|
||||||
|
this.log_info(`COPIED: ${path} -> ${tof}`);
|
||||||
|
resolve(undefined);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.log_error(error.toString());
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return Promise.all(promises);
|
||||||
|
}
|
||||||
|
|
||||||
|
meta(path)
|
||||||
|
{
|
||||||
|
const file = path.abspath(this.job.root);
|
||||||
|
return new Promise((resolve,reject) =>{
|
||||||
|
this.post(API.REST+"/VFS/fileinfo", {path:file})
|
||||||
|
.then(json =>{
|
||||||
|
if(json.error)
|
||||||
|
{
|
||||||
|
this.log_error(`${file}: ${json.error}`);
|
||||||
|
return reject(json.error);
|
||||||
|
}
|
||||||
|
return resolve(json.result);
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
this.log_error(e.toString());
|
||||||
|
resolve(e);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
scandir(path)
|
||||||
|
{
|
||||||
|
return new Promise((resolve,reject) =>{
|
||||||
|
this.post(API.REST+"/VFS/scandir", {path:path.abspath(this.job.root)})
|
||||||
|
.then(json =>{
|
||||||
|
if(json.error)
|
||||||
|
return reject(json.error);
|
||||||
|
return resolve(json.result);
|
||||||
|
})
|
||||||
|
.catch(e =>{
|
||||||
|
this.log_error(e.toString());
|
||||||
|
resolve(e);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
execute() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UnknownJob extends AntOSDKBaseJob {
|
||||||
|
constructor(data)
|
||||||
|
{
|
||||||
|
super(data);
|
||||||
|
}
|
||||||
|
execute() {
|
||||||
|
this.log_error("Unknown job " + this.job.cmd);
|
||||||
|
this.error("Unknown job " + this.job.cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SDKSetup extends AntOSDKBaseJob {
|
||||||
|
constructor(data)
|
||||||
|
{
|
||||||
|
super(data);
|
||||||
|
}
|
||||||
|
execute() {
|
||||||
|
for(let k in this.job.data)
|
||||||
|
{
|
||||||
|
API[k] = this.job.data[k];
|
||||||
|
}
|
||||||
|
this.result("ANTOS Sdk set up");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoadScritpJob extends AntOSDKBaseJob {
|
||||||
|
constructor(data)
|
||||||
|
{
|
||||||
|
super(data);
|
||||||
|
}
|
||||||
|
execute() {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for(let lib of this.job.data)
|
||||||
|
{
|
||||||
|
if(!API.modules[lib])
|
||||||
|
{
|
||||||
|
this.log_info("Importing module:" + lib);
|
||||||
|
importScripts(lib);
|
||||||
|
API.modules[lib] = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
console.log("Module " + lib + " is already loaded");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.log_info("All Modules loaded" );
|
||||||
|
this.result(this.job.data);
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
this.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class VFSJob extends AntOSDKBaseJob {
|
||||||
|
constructor(data)
|
||||||
|
{
|
||||||
|
super(data);
|
||||||
|
}
|
||||||
|
execute() {
|
||||||
|
const arr = this.job.cmd.split("-");
|
||||||
|
if(arr.length > 1)
|
||||||
|
{
|
||||||
|
switch (arr[1]) {
|
||||||
|
case 'cat':
|
||||||
|
this.cat(this.job.data.src,"")
|
||||||
|
.then(data => {
|
||||||
|
this.save_file(this.job.data.dest, data)
|
||||||
|
.then(r => this.result(r))
|
||||||
|
.catch(e1 => this.error(e1));
|
||||||
|
})
|
||||||
|
.catch(e => this.error(e));
|
||||||
|
break;
|
||||||
|
case 'rm':
|
||||||
|
this.delete(this.job.data)
|
||||||
|
.then(d => this.result(d))
|
||||||
|
.catch(e => this.error(e));
|
||||||
|
break;
|
||||||
|
case 'mkdir':
|
||||||
|
this.mkdir(this.job.data)
|
||||||
|
.then(d => this.result(d))
|
||||||
|
.catch(e => this.error(e));
|
||||||
|
break;
|
||||||
|
case 'cp':
|
||||||
|
this.copy(this.job.data.src, this.job.data.dest)
|
||||||
|
.then(d => this.result(d))
|
||||||
|
.catch(e => this.error(e));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.error("Unknown command: " + this.job.cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.error("Unknown command: " + this.job.cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
API.jobhandle["sdk-import"] = LoadScritpJob;
|
||||||
|
API.jobhandle["sdk-setup"] = SDKSetup;
|
||||||
|
API.jobhandle["vfs-cat"] = VFSJob;
|
||||||
|
API.jobhandle["vfs-rm"] = VFSJob;
|
||||||
|
API.jobhandle["vfs-mkdir"] = VFSJob;
|
||||||
|
API.jobhandle["vfs-cp"] = VFSJob;
|
||||||
|
|
||||||
|
onmessage = (e) => {
|
||||||
|
if(API.jobhandle[e.data.cmd])
|
||||||
|
{
|
||||||
|
return (new API.jobhandle[e.data.cmd](e.data)).execute();
|
||||||
|
}
|
||||||
|
(new UnknownJob(e.data)).execute();
|
||||||
|
}
|
98
libantosdk/core/zip.worker.js
Normal file
98
libantosdk/core/zip.worker.js
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
importScripts("os://scripts/jszip.min.js".getlink());
|
||||||
|
|
||||||
|
|
||||||
|
class ZipJob extends AntOSDKBaseJob {
|
||||||
|
constructor(data)
|
||||||
|
{
|
||||||
|
super(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
execute()
|
||||||
|
{
|
||||||
|
if(!JSZip)
|
||||||
|
{
|
||||||
|
const e_msg = "JSZip module is not loaded";
|
||||||
|
this.log_error(e_msg);
|
||||||
|
return this.error(e_msg);
|
||||||
|
}
|
||||||
|
switch (this.job.cmd) {
|
||||||
|
case 'zip-mk':
|
||||||
|
this.mkar()
|
||||||
|
.then(d => this.result(d))
|
||||||
|
.catch(e => this.error(e));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
const err_msg = `Unkown job ${this.job.cmd}`;
|
||||||
|
this.log_error(err_msg);
|
||||||
|
return this.error(err_msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
aradd(list, zip, base)
|
||||||
|
{
|
||||||
|
const promises = [];
|
||||||
|
for (const file of list) {
|
||||||
|
promises.push(new Promise(async (resolve, reject) => {
|
||||||
|
try {
|
||||||
|
const basename = file.split("/").pop();
|
||||||
|
const meta = await this.meta(file);
|
||||||
|
if (meta.type == "dir") {
|
||||||
|
const ret = await this.scandir(file);
|
||||||
|
const dirs = ret.map(v => v.path);
|
||||||
|
if (dirs.length > 0) {
|
||||||
|
await this.aradd(dirs, zip, `${base}${basename}/`);
|
||||||
|
resolve(undefined);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resolve(undefined);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const ret = await this.read_files([file], "arraybuffer");
|
||||||
|
const u_data = ret[0];
|
||||||
|
const z_path = `${base}${basename}`.replace(
|
||||||
|
/^\/+|\/+$/g,
|
||||||
|
"");
|
||||||
|
zip.file(z_path, u_data, { binary: true });
|
||||||
|
this.log_info(`${file} added to zip`);
|
||||||
|
resolve(undefined);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.log_error(`${file}: ${error.toString()}`);
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return Promise.all(promises);
|
||||||
|
}
|
||||||
|
|
||||||
|
mkar()
|
||||||
|
{
|
||||||
|
const src = this.job.data.src;
|
||||||
|
const dest = this.job.data.dest;
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
try {
|
||||||
|
const zip = new JSZip();
|
||||||
|
const meta = await this.meta(this.job.data.src);
|
||||||
|
if(meta.type === "file")
|
||||||
|
{
|
||||||
|
await this.aradd([src], zip, "/");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const ret = await this.scandir(src);
|
||||||
|
await this.aradd(ret.map(v => v.path), zip, "/");
|
||||||
|
}
|
||||||
|
const z_data = await zip.generateAsync({ type: "base64" });
|
||||||
|
await this.save_file(dest, "data:application/zip;base64," + z_data, "base64");
|
||||||
|
this.log_info(`Zip archive saved in ${dest}`);
|
||||||
|
resolve(dest);
|
||||||
|
} catch (error) {
|
||||||
|
this.log_error(`Unable to commpress ${src} -> ${dest}: ${error.toString()}`);
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
API.jobhandle["zip-mk"] = ZipJob;
|
15
libantosdk/package.json
Normal file
15
libantosdk/package.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"pkgname": "libantosdk",
|
||||||
|
"name":"AntOSDK",
|
||||||
|
"description":"AntOS Software Development Kit",
|
||||||
|
"info":{
|
||||||
|
"author": "Xuan Sang LE",
|
||||||
|
"email": "mrsang@iohub.dev"
|
||||||
|
},
|
||||||
|
"version":"0.0.2-a",
|
||||||
|
"category":"Other",
|
||||||
|
"iconclass":"fa fa-cog",
|
||||||
|
"mimes":["none"],
|
||||||
|
"dependencies":[],
|
||||||
|
"locale": {}
|
||||||
|
}
|
8
libantosdk/project.json
Normal file
8
libantosdk/project.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"name": "libantosdk",
|
||||||
|
"css": [],
|
||||||
|
"javascripts": [],
|
||||||
|
"coffees": [],
|
||||||
|
"ts": ["ts/main.ts", "ts/test.ts"],
|
||||||
|
"copies": ["core","package.json", "scheme.html", "README.md"]
|
||||||
|
}
|
16
libantosdk/scheme.html
Normal file
16
libantosdk/scheme.html
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<afx-app-window apptitle="__(Test SDK)" width="450" height="500" data-id="TestSDK">
|
||||||
|
<afx-vbox >
|
||||||
|
<div data-height="10"></div>
|
||||||
|
<afx-hbox data-id="wrapper">
|
||||||
|
<div data-width="10"></div>
|
||||||
|
<div data-id="container"></div>
|
||||||
|
<div data-width="10"></div>
|
||||||
|
</afx-hbox>
|
||||||
|
<div data-height="5"></div>
|
||||||
|
<afx-hbox data-height="23" style="text-align: right;">
|
||||||
|
<afx-button data-id="btnsend" text="__(Send)"></afx-button>
|
||||||
|
<div data-width="5"></div>
|
||||||
|
</afx-hbox>
|
||||||
|
<div data-height="10"></div>
|
||||||
|
</afx-vbox>
|
||||||
|
</afx-app-window>
|
213
libantosdk/ts/main.ts
Normal file
213
libantosdk/ts/main.ts
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
|
||||||
|
namespace OS {
|
||||||
|
|
||||||
|
export namespace API {
|
||||||
|
interface TSLib {
|
||||||
|
file: string;
|
||||||
|
url?: string;
|
||||||
|
zip?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface AntOSDKWorkerResult {
|
||||||
|
id: string;
|
||||||
|
type: "result"|"log";
|
||||||
|
error?: any;
|
||||||
|
result?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AntOSDKWorkerJob {
|
||||||
|
id: string;
|
||||||
|
cmd: string;
|
||||||
|
data: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AntOSDKLogger {
|
||||||
|
info: (data: any) => void;
|
||||||
|
error: (data: any) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
class AntOSDKWorker {
|
||||||
|
private worker: any;
|
||||||
|
private jobs: GenericObject<any>;
|
||||||
|
constructor(path: string)
|
||||||
|
{
|
||||||
|
this.worker = new Worker(path.asFileHandle().getlink());
|
||||||
|
this.jobs = {};
|
||||||
|
this.worker.onmessage = (e) => {
|
||||||
|
let ret = e.data as AntOSDKWorkerResult;
|
||||||
|
let job = this.jobs[ret.id];
|
||||||
|
if(job)
|
||||||
|
{
|
||||||
|
if(ret.type ==="log")
|
||||||
|
{
|
||||||
|
if(job.logger){
|
||||||
|
if(ret.error)
|
||||||
|
job.logger.error(ret.result);
|
||||||
|
else
|
||||||
|
job.logger.info(ret.result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
job.callback(ret);
|
||||||
|
delete this.jobs[ret.id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
console.log("Unable to identify result of job", ret.id, ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const pkgs = {};
|
||||||
|
for(const k in OS.setting.system.packages)
|
||||||
|
{
|
||||||
|
const pkg = OS.setting.system.packages[k];
|
||||||
|
pkgs[k] = {
|
||||||
|
path: pkg.path,
|
||||||
|
name: pkg.pkgname
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.submit("sdk-setup", {
|
||||||
|
REST: OS.API.REST,
|
||||||
|
pkgs: pkgs
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private newJobID(): string {
|
||||||
|
return `job_${Math.random().toString(36).replace(".","")}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private exectue_job(cmd: string, data: any, root:string, callback: (AntOSDKWorkerResult) => void, logger?: AntOSDKLogger): void
|
||||||
|
{
|
||||||
|
const id = this.newJobID();
|
||||||
|
const job: AntOSDKWorkerJob = {
|
||||||
|
id: id,
|
||||||
|
cmd: cmd,
|
||||||
|
data: data,
|
||||||
|
root: root
|
||||||
|
} as AntOSDKWorkerJob;
|
||||||
|
this.jobs[id] = {
|
||||||
|
callback:callback,
|
||||||
|
logger: logger
|
||||||
|
};
|
||||||
|
this.worker.postMessage(job);
|
||||||
|
}
|
||||||
|
|
||||||
|
submit(cmd:string, data:any,root?:string, logger?: AntOSDKLogger): Promise<any>
|
||||||
|
{
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.exectue_job(cmd, data, root, (ret) =>{
|
||||||
|
if(ret.error)
|
||||||
|
{
|
||||||
|
return reject(ret.error);
|
||||||
|
}
|
||||||
|
resolve(ret.result);
|
||||||
|
}, logger)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
terminate(): void {
|
||||||
|
this.worker.terminate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AntOSDKBuilder {
|
||||||
|
|
||||||
|
static worker: AntOSDKWorker;
|
||||||
|
|
||||||
|
private root: string;
|
||||||
|
private logger:AntOSDKLogger;
|
||||||
|
|
||||||
|
constructor(logger?: AntOSDKLogger, root?: string)
|
||||||
|
{
|
||||||
|
this.root = root;
|
||||||
|
this.logger = logger;
|
||||||
|
if(! AntOSDKBuilder.worker)
|
||||||
|
{
|
||||||
|
AntOSDKBuilder.worker = new AntOSDKWorker("pkg://libantosdk/core/worker.js");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
require(mods:string[]): Promise<any>
|
||||||
|
{
|
||||||
|
return this.run("sdk-import", mods.map(m=> `${m}.worker.js`));
|
||||||
|
}
|
||||||
|
|
||||||
|
compile(type: string, opts: GenericObject<any>): Promise<string> {
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
try{
|
||||||
|
await this.require([type]);
|
||||||
|
const ret = await this.run(`${type}-compile`, opts);
|
||||||
|
resolve(ret);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
reject(__e(e));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
run(job: string, data: any): Promise<any>
|
||||||
|
{
|
||||||
|
return AntOSDKBuilder.worker.submit(job,data, this.root, this.logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
batch(targets: string[], options: GenericObject<any>): Promise<any>
|
||||||
|
{
|
||||||
|
if(options.root)
|
||||||
|
{
|
||||||
|
this.root = options.root;
|
||||||
|
}
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
try {
|
||||||
|
if(!options.targets)
|
||||||
|
{
|
||||||
|
reject("No target found");
|
||||||
|
}
|
||||||
|
for(const name of targets)
|
||||||
|
{
|
||||||
|
const target = options.targets[name];
|
||||||
|
if(!target)
|
||||||
|
return reject(__(`No target: ${name}`));
|
||||||
|
|
||||||
|
if(target.depend)
|
||||||
|
{
|
||||||
|
await this.batch(target.depend,options);
|
||||||
|
}
|
||||||
|
if(target.require)
|
||||||
|
{
|
||||||
|
await this.require(target.require);
|
||||||
|
}
|
||||||
|
if(this.logger)
|
||||||
|
this.logger.info(__(`### RUNNING STAGE: ${name}###`).__());
|
||||||
|
if(target.jobs)
|
||||||
|
for(const job of target.jobs)
|
||||||
|
{
|
||||||
|
await this.run(job.name, job.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resolve(undefined);
|
||||||
|
}
|
||||||
|
catch(e) {
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export namespace VFS {
|
||||||
|
export class SDKFileHandle extends VFS.RemoteFileHandle {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*Creates an instance of SDKFileHandle.
|
||||||
|
* @param {string} pkg_path package path in string
|
||||||
|
* @memberof SDKFileHandle
|
||||||
|
*/
|
||||||
|
constructor(pkg_path: string) {
|
||||||
|
super(pkg_path);
|
||||||
|
const path = `pkg://libantosdk/${this.genealogy.join("/")}`;
|
||||||
|
this.setPath(path.asFileHandle().path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
register("^sdk$", SDKFileHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
47
libantosdk/ts/test.ts
Normal file
47
libantosdk/ts/test.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
namespace OS {
|
||||||
|
export namespace application {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @class libantosdk
|
||||||
|
* @extends {BaseApplication}
|
||||||
|
*/
|
||||||
|
export class libantosdk extends BaseApplication {
|
||||||
|
private sdk: API.AntOSDKBuilder;
|
||||||
|
constructor(args: AppArgumentsType[]) {
|
||||||
|
super("libantosdk", args);
|
||||||
|
}
|
||||||
|
main(): void {
|
||||||
|
this.sdk = new API.AntOSDKBuilder(
|
||||||
|
{
|
||||||
|
info: (d) => console.log(d),
|
||||||
|
error: (d) => console.error(d)
|
||||||
|
},
|
||||||
|
"home://workspace/antosdk-apps/libantosdk");
|
||||||
|
(this.find("btnsend") as GUI.tag.ButtonTag).onbtclick = (e) => {
|
||||||
|
this.openDialog("PromptDialog", {
|
||||||
|
label: "Stages",
|
||||||
|
value: "build,uglify,copy"
|
||||||
|
}).then(v => {
|
||||||
|
this.load(this.compile(v.split(",")));
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compile(stages): Promise<string> {
|
||||||
|
return new Promise( async (resolve, reject) => {
|
||||||
|
try {
|
||||||
|
const options = await "home://workspace/antosdk-apps/libantosdk/build.json".asFileHandle().read("json");
|
||||||
|
await this.sdk.batch(stages,options);
|
||||||
|
resolve("OK");
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
reject(__e(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
@ -29,6 +29,16 @@
|
|||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/ActivityMonitor/build/release/ActivityMonitor.zip"
|
"download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/ActivityMonitor/build/release/ActivityMonitor.zip"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"pkgname": "Antedit",
|
||||||
|
"name": "Antos Editor",
|
||||||
|
"description": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/Antedit/README.md",
|
||||||
|
"category": "Development",
|
||||||
|
"author": "Xuan Sang LE",
|
||||||
|
"version": "0.1.0-a",
|
||||||
|
"dependencies": ["MonacoCore@0.23.0-r"],
|
||||||
|
"download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/Antedit/build/release/Antedit.zip"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"pkgname": "Antunnel",
|
"pkgname": "Antunnel",
|
||||||
"name": "Antunnel",
|
"name": "Antunnel",
|
||||||
@ -159,6 +169,16 @@
|
|||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/Katex/build/release/Katex.zip"
|
"download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/Katex/build/release/Katex.zip"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"pkgname": "libantosdk",
|
||||||
|
"name": "AntOSDK",
|
||||||
|
"description": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/libantosdk/README.md",
|
||||||
|
"category": "Other",
|
||||||
|
"author": "Xuan Sang LE",
|
||||||
|
"version": "0.0.2-a",
|
||||||
|
"dependencies": [],
|
||||||
|
"download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/libantosdk/build/release/libantosdk.zip"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"pkgname": "libfabric",
|
"pkgname": "libfabric",
|
||||||
"name": "Fabric.js library",
|
"name": "Fabric.js library",
|
||||||
|
Loading…
Reference in New Issue
Block a user