From 1d55e8225929eecdfcad9e51734bc837d0430e5f Mon Sep 17 00:00:00 2001 From: lxsang Date: Tue, 11 May 2021 15:05:28 +0200 Subject: [PATCH] enable downlevelIteration build option in typescript --- Antedit/build/debug/main.js | 2 +- Antedit/build/debug/package.json | 85 +++++++- Antedit/build/release/Antedit.zip | Bin 10126 -> 10838 bytes libantosdk/README.md | 1 + libantosdk/build.json | 4 +- libantosdk/build/debug/README.md | 1 + libantosdk/build/debug/core/linux.worker.js | 70 +++++++ libantosdk/build/debug/core/lua/api.lua | 31 +++ libantosdk/build/debug/core/ts.worker.js | 1 + libantosdk/build/debug/main.css | 32 +++ libantosdk/build/debug/package.json | 2 +- libantosdk/build/debug/scheme.html | 30 +++ libantosdk/build/release/libantosdk.zip | Bin 1272811 -> 1272859 bytes libantosdk/core/linux.worker.js | 70 +++++++ libantosdk/core/lua/api.lua | 31 +++ libantosdk/core/ts.worker.js | 1 + libantosdk/main.css | 32 +++ libantosdk/package.json | 2 +- libantosdk/ts/app.ts | 213 ++++++++++++++++++++ packages.json | 2 +- 20 files changed, 594 insertions(+), 16 deletions(-) create mode 100644 libantosdk/build/debug/core/linux.worker.js create mode 100644 libantosdk/build/debug/core/lua/api.lua create mode 100644 libantosdk/build/debug/main.css create mode 100644 libantosdk/build/debug/scheme.html create mode 100644 libantosdk/core/linux.worker.js create mode 100644 libantosdk/core/lua/api.lua create mode 100644 libantosdk/main.css create mode 100644 libantosdk/ts/app.ts diff --git a/Antedit/build/debug/main.js b/Antedit/build/debug/main.js index 9174fc1..73fa7d6 100644 --- a/Antedit/build/debug/main.js +++ b/Antedit/build/debug/main.js @@ -1 +1 @@ -var OS;!function(t){let e;!function(t){t.BaseEditorModel=class{constructor(t,e,i){this.container=i,this.currfile="Untitled".asFileHandle(),this.tabbar=e,this.editorSetup(i),this.app=t,this.editormux=!1,this.onstatuschange=void 0,this.on("focus",()=>{this.onstatuschange&&this.onstatuschange(this.getEditorStatus())}),this.on("input",()=>this.editormux?(this.editormux=!1,!1):this.currfile.dirty?void 0:(this.currfile.dirty=!0,this.currfile.text+="*",this.tabbar.update(void 0))),this.on("changeCursor",()=>{this.onstatuschange&&this.onstatuschange(this.getEditorStatus())}),this.tabbar.ontabselect=t=>this.selecteTab($(t.data.item).index()),this.tabbar.ontabclose=t=>{const e=t.data.item;return!!e&&(e.data.dirty?(this.app.openDialog("YesNoDialog",{title:__("Close tab"),text:__("Close without saving ?")}).then(t=>t?this.closeTab(e):this.focus()),!1):this.closeTab(e))}}findTabByFile(t){const e=this.tabbar.items,i=(()=>{const i=[];for(let a=0;a(t.cache=e||"",this.newTab(t))).catch(e=>this.app.error(__("Unable to open: {0}",t.path),e)):this.newTab(t):this.tabbar.selected=e}write(t){this.currfile.cache=this.getValue(),t.write("text/plain").then(e=>{t.dirty=!1,t.text=t.basename,this.tabbar.update(void 0)}).catch(e=>this.app.error(__("Unable to save file: {0}",t.path),e))}save(){return this.currfile.cache=this.getValue(),this.currfile.basename?this.write(this.currfile):this.saveAs()}saveAs(){this.app.openDialog("FileDialog",{title:__("Save as"),file:this.currfile}).then(t=>{let e=t.file.path.asFileHandle();"file"===t.file.type&&(e=e.parent()),this.currfile.setPath(`${e.path}/${t.name}`),this.write(this.currfile)})}dirties(){const t=[];for(let e of Array.from(this.tabbar.items))e.dirty&&t.push(e);return t}set contextmenuHandle(t){this.container.contextmenuHandle=t}closeAll(){this.tabbar.items=[],this.resetEditor()}isDirty(){return this.dirties().length>0}}}(e=t.application||(t.application={}))}(OS||(OS={})),function(t){let e;!function(e){class i extends t.application.BaseEditorModel{constructor(t,e,i){super(t,e,i)}resetEditor(){this.setValue("")}getTexModel(){return{model:this.editor.getModel(),position:this.editor.getPosition()}}setTextModel(t){this.editor.setModel(t.model),t.position&&(this.editor.setPosition(t.position),this.editor.revealLineInCenter(t.position.lineNumber))}newTextModelFrom(t){if("Untitled"===t.path.toString())return{model:monaco.editor.createModel(t.cache,"textplain")};const e=monaco.Uri.parse(t.path),i=monaco.editor.getModel(e);return i?(i.setValue(t.cache),{model:i}):{model:monaco.editor.createModel(t.cache,void 0,e)}}getModes(){return monaco.languages.getLanguages().map(t=>(t.text=t.aliases[0],t))}setTheme(t){}setMode(t){monaco.editor.setModelLanguage(this.editor.getModel(),t.id),this.onstatuschange&&this.onstatuschange(this.getEditorStatus())}editorSetup(t){this.editor=monaco.editor.create(t,{value:"",language:"textplain"}),i.modes||(i.modes={},monaco.languages.getLanguages().forEach(t=>{i.modes[t.id]=t}))}on(t,e){switch(t){case"input":this.editor.onDidChangeModelContent(e);break;case"focus":this.editor.onDidFocusEditorText(e);break;case"changeCursor":this.editor.onDidChangeCursorPosition(e)}}resize(){this.editor&&this.editor.layout()}focus(){this.editor&&this.editor.focus()}getModeForPath(t){return{}}getEditorStatus(){const t=this.editor.getPosition(),e=i.modes[this.editor.getModel().getModeId()];return{row:t.lineNumber,column:t.column,line:this.editor.getModel().getLineCount(),langmode:{text:e.aliases[0],mode:e},file:this.currfile.path}}getValue(){return this.editor.getValue()}setValue(t){this.editor.setValue(t)}getEditor(){return this.editor}}e.MonacoEditorModel=i}(e=t.application||(t.application={}))}(OS||(OS={})),function(t){let e;!function(e){class i extends e.BaseApplication{constructor(t){super("Antedit",t),this.currdir=void 0}main(){this.extensions={},this.eum=new a,this.fileview=this.find("fileview"),this.sidebar=this.find("sidebar"),this.bottombar=this.find("bottombar"),this.langstat=this.find("langstat"),this.editorstat=this.find("editorstat"),this.filestat=this.find("current-file-lbl"),this.logger=new s(this.find("output-tab")),this.split_mode=!0,this.fileview.fetch=t=>new Promise((async function(e,i){let a;a="string"==typeof t?t.asFileHandle():t;try{const t=await a.read();return t.error?i(t.error):e(t.result)}catch(t){return i(__e(t))}}));let e="Untitled".asFileHandle();this.args&&this.args.length>0&&(this.addRecent(this.args[0].path),"dir"===this.args[0].type?this.currdir=this.args[0].path.asFileHandle():(e=this.args[0].path.asFileHandle(),this.currdir=e.parent())),this.setting.recent||(this.setting.recent=[]);const i=this.find("wrapper");$(i).css("visibility","hidden"),monaco.editor.setTheme("vs-dark"),this.eum.add(new t.application.MonacoEditorModel(this,this.find("left-tabbar"),this.find("left-editorarea"))).add(new t.application.MonacoEditorModel(this,this.find("right-tabbar"),this.find("right-editorarea"))),this.eum.onstatuschange=t=>this.updateStatus(t),$(i).css("visibility","visible"),this.setup(),this.eum.active.openFile(e)}setup(){this.fileview.onfileopen=t=>{if(t.data&&t.data.path&&"dir"!==t.data.type)return this.addRecent(t.data.path),this.eum.active.openFile(t.data.path.asFileHandle())},this.fileview.onfileselect=t=>{t.data&&t.data.path&&"dir"!==t.data.type&&this.eum.active.selectFile(t.data.path)},this.on("resize",()=>this.eum.resize()),this.on("focus",()=>this.eum.active.focus()),this.fileview.contextmenuHandle=(t,e)=>(e.items=[{text:"__(New file)",id:"new"},{text:"__(New folder)",id:"newdir"},{text:"__(Rename)",id:"rename"},{text:"__(Delete)",id:"delete"}],e.onmenuselect=t=>this.ctxFileMenuHandle(t),e.show(t)),this.bindKey("ALT-N",()=>this.menuAction("new")),this.bindKey("ALT-O",()=>this.menuAction("open")),this.bindKey("ALT-F",()=>this.menuAction("opendir")),this.bindKey("CTRL-S",()=>this.menuAction("save")),this.bindKey("ALT-W",()=>this.menuAction("saveas")),this.fileview.ondragndrop=t=>{const e=t.data.from.data.path.asFileHandle(),i=t.data.to.data.path;return e.move(`${i}/${e.basename}`).then((function(a){const s=i,n=e.parent().path;s.lengththis.error(__("Unable to move file/folder"),t))},this.on("filechange",t=>{let{path:e}=t.file;return"file"===t.type&&({path:e}=t.file.parent()),this.fileview.update(e)}),this.find("logger-clear").onbtclick=()=>{this.logger.clear()},void 0===this.setting.showBottomBar&&(this.setting.showBottomBar=!1);const t={name:"Editor",text:__("Editor")},e={name:"langmode",text:__("Change language mode"),shortcut:"CTRL-K"};this.eum.addAction(t,e,async t=>{try{const t=await this.openDialog("SelectionDialog",{title:__("Select language"),data:this.eum.active.getModes()});this.eum.active.setMode(t)}catch(t){}}),this.loadExtensionMetaData(),this.toggleSideBar(),this.toggleSplitMode(),this.applyAllSetting()}updateStatus(t){t||(t=this.eum.active.getEditorStatus()),this.editorstat.text=__("Row {0}, col {1}, lines: {2}",t.row,t.column,t.line),t.langmode&&(this.langstat.text=t.langmode.text),this.filestat.text=t.file;let e=this.scheme;e.apptitle!=t.file&&(e.apptitle=t.file)}toggleSideBar(){this.currdir?($(this.sidebar).show(),this.fileview.path=this.currdir.path):$(this.sidebar).hide(),this.trigger("resize")}showOutput(t=!1){t&&this.showBottomBar(!0),this.bottombar.selectedIndex=0}applySetting(t){"showBottomBar"==t&&this.showBottomBar(this.setting.showBottomBar)}showBottomBar(t){this.setting.showBottomBar=t,t?$(this.bottombar).show():$(this.bottombar).hide(),this.trigger("resize")}toggleBottomBar(){this.showBottomBar(!this.setting.showBottomBar)}toggleSplitMode(){const t=this.find("right-panel"),e=this.eum.editors[1],i=this.eum.editors[0];if(this.split_mode){if(e.isDirty())return void this.notify(__("Unable to disable split view: Please save changes of modified files on the right panel"));e.closeAll(),$(t).hide(),this.split_mode=!1,i.focus()}else $(t).show(),this.split_mode=!0,e.openFile("Untitled".asFileHandle()),e.focus();this.trigger("resize")}fileMenu(){const t=this.setting.recent.map(t=>({text:t}));return{text:__("File"),nodes:[{text:__("New"),dataid:"new",shortcut:"A-N"},{text:__("Open Recent"),dataid:"recent",nodes:t,onchildselect:(t,e)=>{const i=t.data.item.data.text.asFileHandle();i.onready().then(t=>{t&&("dir"==t.type?(this.currdir=i,this.toggleSideBar()):this.eum.active.openFile(i))})}},{text:__("Open"),dataid:"open",shortcut:"A-O"},{text:__("Open Folder"),dataid:"opendir",shortcut:"A-F"},{text:__("Save"),dataid:"save",shortcut:"C-S"},{text:__("Save as"),dataid:"saveas",shortcut:"A-W"}],onchildselect:(t,e)=>this.menuAction(t.data.item.data.dataid,e)}}ctxFileMenuHandle(t){const e=t.data.item;if(!e)return;const i=e.data;if(!i)return;let a=this.fileview.selectedFile,s=this.currdir;switch(a&&"dir"===a.type&&(s=a.path.asFileHandle()),a&&"file"===a.type&&(s=a.path.asFileHandle().parent()),i.id){case"new":if(!s)return;this.openDialog("PromptDialog",{title:"__(New file)",label:"__(File name)"}).then(async t=>{const e=`${s.path}/${t}`.asFileHandle();try{return await e.write("text/plain"),this.fileview.update(s.path)}catch(t){return this.error(__("Fail to create: {0}",t.stack),t)}});break;case"newdir":if(!s)return;this.openDialog("PromptDialog",{title:"__(New folder)",label:"__(Folder name)"}).then(async t=>{try{return await s.mk(t),this.fileview.update(s.path)}catch(t){return this.error(__("Fail to create: {0}",s.path),t)}});break;case"rename":if(!a)return;this.openDialog("PromptDialog",{title:"__(Rename)",label:"__(File name)",value:a.filename}).then(async t=>{if(t!==a.filename){a=a.path.asFileHandle(),s=a.parent();try{return await a.move(`${s.path}/${t}`),this.fileview.update(s.path)}catch(t){return this.error(__("Fail to rename: {0}",a.path),t)}}});break;case"delete":if(!a)return;this.openDialog("YesNoDialog",{title:"__(Delete)",iconclass:"fa fa-question-circle",text:__("Do you really want to delete: {0}?",a.filename)}).then(async t=>{if(t){a=a.path.asFileHandle(),s=a.parent();try{return await a.remove(),this.fileview.update(s.path)}catch(t){return this.error(__("Fail to delete: {0}",a.path),t)}}})}}addRecent(t){this.setting.recent||(this.setting.recent=[]),this.setting.recent.includes(t)||(this.setting.recent.push(t),this.setting.recent.length>10&&(this.setting.recent=this.setting.recent.slice(0,10)))}menuAction(t,e){let i=this;switch(e&&(i=e),t){case"new":return i.eum.active.openFile("Untitled".asFileHandle());case"open":return i.openDialog("FileDialog",{title:__("Open file"),mimes:Array.from(i.meta().mimes).filter(t=>"dir"!==t)}).then(t=>{this.addRecent(t.file.path),i.eum.active.openFile(t.file.path.asFileHandle())});case"opendir":return i.openDialog("FileDialog",{title:__("Open folder"),mimes:["dir"]}).then((function(t){return i.addRecent(t.file.path),i.currdir=t.file.path.asFileHandle(),i.toggleSideBar()}));case"save":return i.eum.active.save();case"saveas":return i.eum.active.saveAs();default:return console.log(t)}}cleanup(t){let e;const i=this.eum.dirties();if(0!==i.length)t.preventDefault(),this.openDialog("YesNoDialog",{title:"__(Quit)",text:__("Ignore all unsaved files: {0} ?",(()=>{const t=[];for(e of Array.from(i))t.push(e.filename);return t})().join(", "))}).then(t=>{if(t){for(e of Array.from(i))e.dirty=!1;return this.quit(!1)}});else for(let t in this.extensions)this.extensions[t]&&this.extensions[t].cleanup&&this.extensions[t].cleanup()}menu(){return[this.fileMenu(),{text:"__(View)",nodes:[{text:"__(Toggle bottom bar)",dataid:"bottombar"},{text:"__(Toggle split view)",dataid:"splitview"}],onchildselect:(t,e)=>{switch(t.data.item.data.dataid){case"bottombar":return this.toggleBottomBar();case"splitview":return this.toggleSplitMode()}}}]}loadExtensionMetaData(){this.loadExtensionMetaFromFile(this.meta().path+"/extensions/extensions.json").catch(t=>this.error(__("Cannot load extension meta data"),t))}loadExtensionMetaFromFile(t){return new Promise((e,i)=>{t.asFileHandle().read("json").then(t=>{for(let e of t)for(let t of e.actions)this.eum.addAction(e,t,(t,i)=>{this.loadAndRunExtensionAction(t,i,e.root)});e()}).catch(t=>{i(__e(t))})})}loadAndRunExtensionAction(t,e,a){if(i.extensions[t])this.runExtensionAction(t,e);else{let i=`${this.meta().path}/extensions/${t}/main.js`;a&&(i=a+"/main.js"),this._api.requires(i,!0).then(()=>this.runExtensionAction(t,e)).catch(e=>this.error(__("unable to load extension: {0}",t),e))}}runExtensionAction(t,e){if(!this.extensions[t]){if(!i.extensions[t])return this.error(__("Unable to find extension: {0}",t));this.extensions[t]=new i.extensions[t](this)}if(!this.extensions[t][e])return this.error(__("Unable to find action: {0}",e));this.extensions[t].preload().then(()=>this.extensions[t][e]()).catch(t=>this.error(__("Unable to preload extension"),t))}}e.Antedit=i;class a{constructor(){this.active_editor=void 0,this.models=[]}get editors(){return this.models}set contextmenuHandle(t){for(let e of this.models)e.contextmenuHandle=t}get active(){return this.active_editor}add(t){return this.models.push(t),this.active_editor||(this.active_editor=t),t.on("focus",()=>{this.active_editor=t}),this}addAction(t,e,i){const a={id:`${t.name}:${e.name}`,label:`${t.text.__()}: ${e.text.__()}`,keybindings:[],precondition:null,keybindingContext:null,contextMenuGroupId:t.name,run:()=>i(t.name,e.name)};if(e.shortcut){const t=e.shortcut.split("-");let i=0;for(const e of t)switch(e){case"CTRL":i|=monaco.KeyMod.CtrlCmd;break;case"ALT":i|=monaco.KeyMod.Alt;break;case"SHIFT":i|=monaco.KeyMod.Shift;break;case"SUPPER":i|=monaco.KeyMod.WinCtrl;break;default:const t="KEY_"+e;monaco.KeyCode[t]?i|=monaco.KeyCode[t]:i=0}0!=i&&a.keybindings.push(i)}for(let t of this.models){const e=t.getEditor();e.getAction(a.id)||e.addAction(a)}}set onstatuschange(t){for(let e of this.models)e.onstatuschange=t}dirties(){let t=[];for(let e of this.models)t=t.concat(e.dirties());return t}resize(){for(let t of this.models)t.resize()}}class s{constructor(t){this.target=t}info(t){this.log("info",t,!0)}warn(t){this.log("warn",t,!0)}error(t){this.log("error",t,!0)}log(t,e,i){let a=$("
").attr("class","code-pad-log-"+t);if(i){let t=new Date,i=t.getDate()+"/"+(t.getMonth()+1)+"/"+t.getFullYear()+" "+t.getHours()+":"+t.getMinutes()+":"+t.getSeconds();a.text(`[${i}]: ${e.__()}`)}else a.text(e.__());$(this.target).append(a),$(this.target).scrollTop($(this.target)[0].scrollHeight)}print(t){this.log("info",t,!1)}clear(){$(this.target).empty()}}i.Logger=s,i.dependencies=["pkg://MonacoCore/path.js","pkg://MonacoCore/bundle/app.bundle.js"]}(e=t.application||(t.application={}))}(OS||(OS={})),function(t){class e{constructor(t,e){this.app=e,this.name=t}preload(){return t.API.require(t.application.Antedit.extensions[this.name].dependencies)}basedir(){return`${this.app.meta().path}/extensions/${this.name}`}notify(t){return this.app.notify(t)}error(t,e){return this.app.error(t,e)}logger(){return this.app.setting.showBottomBar?this.app.showOutput(!1):this.app.showOutput(!0),this.app.logger}metadata(e){return new Promise((i,a)=>{if(!this.app.currdir)return a(t.API.throwe(__("Current folder is not found")));`${this.app.currdir.path}/${e}`.asFileHandle().read("json").then(t=>{!t.root&&this.app.currdir&&(t.root=this.app.currdir.path),i(t)}).catch(s=>{this.app.openDialog("FileDialog",{title:__("Select build directory"),root:this.app.currdir.path,mimes:["dir"]}).then(t=>{`${t.file.path}/${e}`.asFileHandle().read("json").then(e=>{e.root||(e.root=t.file.path),i(e)}).catch(t=>a(t))}).catch(e=>a(t.API.throwe(__("Unable to read meta-data"))))})})}}e.dependencies=[],t.application.Antedit.extensions={},t.application.Antedit.EditorBaseExtension=e,t.application.Antedit.extensions.EditorExtensionMaker=class extends e{constructor(t){super("EditorExtensionMaker",t)}create(){this.logger().clear(),this.app.openDialog("FileDialog",{title:"__(New CodePad extension at)",file:{basename:__("ExtensionName")},mimes:["dir"]}).then(t=>this.mktpl(t.file.path,t.name))}build(e){this.logger().clear(),this.metadata("extension.json").then(async i=>{try{const a=await t.API.VFS.cat(i.javascripts.map(t=>`${i.root}/${t}`),"");await(i.root+"/build/debug/main.js").asFileHandle().setCache(a).write("text/plain"),await(i.root+"/build/debug/extension.json").asFileHandle().setCache(i.meta).write("object"),await t.API.VFS.copy(i.copies.map(t=>`${i.root}/${t}`),i.root+"/build/debug"),this.logger().info(__("Files generated in {0}",i.root+"/build/debug")),e&&e()}catch(t){return this.logger().error(__("Unable to build extension:{0}",t.stack))}}).catch(t=>this.logger().error(__("Unable to read meta-data:{0}",t.stack)))}run(){this.logger().clear(),this.metadata("extension.json").then(async e=>{if(!e||!e.meta||!e.meta.name)return this.logger().error(__("Invalid extension meta-data"));try{const i=e.root+"/build/debug/main.js";t.API.shared[i]&&delete t.API.shared[i],await t.API.requires(i),this.app.extensions[e.meta.name]&&this.app.extensions[e.meta.name].cleanup&&this.app.extensions[e.meta.name].cleanup(),this.app.extensions[e.meta.name]=new t.application.Antedit.extensions[e.meta.name](this.app);for(let t of e.meta.actions)this.app.eum.addAction(e.meta,t,(t,i)=>{this.app.loadAndRunExtensionAction(t,i,e.root+"/build")});this.app.eum.active.getEditor().trigger(e.meta.name,"editor.action.quickCommand")}catch(t){return this.logger().error(__("Unable to run extension:{0}",t.stack))}}).catch(t=>this.logger().error(__("Unable to read meta-data:{0}",t.stack)))}release(){this.logger().clear(),this.metadata("extension.json").then(async e=>{this.build(async()=>{try{await t.API.VFS.mkar(e.root+"/build/debug",`${e.root}/build/release/${e.meta.name}.zip`),this.logger().info(__("Archive created at {0}",`${e.root}/build/release/${e.meta.name}.zip`))}catch(t){return this.logger().error(__("Unable to create archive: {0}",t.stack))}})}).catch(t=>this.logger().error(__("Unable to read meta-data: {0}",t.stack)))}install(){this.logger().clear(),this.app.openDialog("FileDialog",{title:"__(Select extension archive)",mimes:[".*/zip"]}).then(async t=>{try{return await this.installZip(t.file.path),this.logger().info(__("Extension installed")),this.app.loadExtensionMetaData()}catch(t){return this.logger().error(__("Unable to install extension: {0}",t.stack))}})}installFromURL(){this.logger().clear(),this.app.openDialog("PromptDialog",{title:__("Enter URI"),label:__("Please enter extension URI:")}).then(async t=>{if(t)try{return await this.installZip(t),this.logger().info(__("Extension installed")),this.app.loadExtensionMetaData()}catch(e){return this.app.error(__("Unable to install extension: {0}",t))}})}mktpl(e,i){const a=`${e}/${i}`,s=[a,a+"/build",a+"/build/release",a+"/build/debug"],n=[["main.tpl",`${a}/${i}.js`],["meta.tpl",a+"/extension.json"]];t.API.VFS.mkdirAll(s,!0).then(async()=>{try{return await t.API.VFS.mktpl(n,this.basedir(),t=>t.format(i,`${e}/${i}`)),this.app.currdir=a.asFileHandle(),this.app.toggleSideBar(),this.app.eum.active.openFile(`${a}/${i}.js`.asFileHandle())}catch(t){return this.logger().error(__("Unable to create extension template: {0}",t.stack))}}).catch(t=>this.logger().error(__("Unable to create extension directories: {0}",t.stack)))}installZip(e){return new Promise(async(i,a)=>{try{await t.API.requires("os://scripts/jszip.min.js");const a=await e.asFileHandle().read("binary"),s=await JSZip.loadAsync(a),n=await s.file("extension.json").async("uint8array"),o=JSON.parse(new TextDecoder("utf-8").decode(n)),r=this.ext_dir(o.name),l=[r],h=[];for(let t in s.files)s.files[t].dir?l.push(r+"/"+t):"extension.json"!=t&&h.push(t);l.length>0?(await t.API.VFS.mkdirAll(l,!0),await this.installFiles(h,s,o)):await this.installFiles(h,s,o),i()}catch(t){a(__e(t))}})}ext_dir(t){return`${this.app.meta().path}/extensions/${t}`}installFiles(t,e,i){return 0===t.length?this.installMeta(i):new Promise(async(a,s)=>{try{const n=t.splice(0,1)[0],o=`${this.ext_dir(i.name)}/${n}`,r=await e.file(n).async("uint8array"),l=await o.asFileHandle().setCache(new Blob([r],{type:"octet/stream"})).write("text/plain");if(l.error)return s(l.error);await this.installFiles(t,e,i),a()}catch(t){s(__e(t))}})}installMeta(t){return new Promise(async(e,i)=>{const a=(this.ext_dir("")+"/extensions.json").asFileHandle();try{const s=await a.read("json"),n=[];for(let t of s)n.push(t.name);const o=n.indexOf(t.name);o>=0&&s.splice(o,1),s.push(t);try{return await a.setCache(s).write("object"),e()}catch(t){return i(__e(t))}}catch(s){try{return await a.setCache([t]).write("object"),e()}catch(t){return i(__e(t))}}})}}}(OS||(OS={}));
\ No newline at end of file
+var OS;!function(t){let e;!function(t){t.BaseEditorModel=class{constructor(t,e,i){this.container=i,this.currfile="Untitled".asFileHandle(),this.tabbar=e,this.editorSetup(i),this.app=t,this.editormux=!1,this.onstatuschange=void 0,this.on("focus",()=>{this.onstatuschange&&this.onstatuschange(this.getEditorStatus())}),this.on("input",()=>this.editormux?(this.editormux=!1,!1):this.currfile.dirty?void 0:(this.currfile.dirty=!0,this.currfile.text+="*",this.tabbar.update(void 0))),this.on("changeCursor",()=>{this.onstatuschange&&this.onstatuschange(this.getEditorStatus())}),this.tabbar.ontabselect=t=>this.selecteTab($(t.data.item).index()),this.tabbar.ontabclose=t=>{const e=t.data.item;return!!e&&(e.data.dirty?(this.app.openDialog("YesNoDialog",{title:__("Close tab"),text:__("Close without saving ?")}).then(t=>t?this.closeTab(e):this.focus()),!1):this.closeTab(e))}}findTabByFile(t){const e=this.tabbar.items,i=(()=>{const i=[];for(let a=0;a(t.cache=e||"",this.newTab(t))).catch(e=>this.app.error(__("Unable to open: {0}",t.path),e)):this.newTab(t):this.tabbar.selected=e}write(t){this.currfile.cache=this.getValue(),t.write("text/plain").then(e=>{t.dirty=!1,t.text=t.basename,this.tabbar.update(void 0)}).catch(e=>this.app.error(__("Unable to save file: {0}",t.path),e))}save(){return this.currfile.cache=this.getValue(),this.currfile.basename?this.write(this.currfile):this.saveAs()}saveAs(){this.app.openDialog("FileDialog",{title:__("Save as"),file:this.currfile}).then(t=>{let e=t.file.path.asFileHandle();"file"===t.file.type&&(e=e.parent()),this.currfile.setPath(`${e.path}/${t.name}`),this.write(this.currfile)})}dirties(){const t=[];for(let e of Array.from(this.tabbar.items))e.dirty&&t.push(e);return t}set contextmenuHandle(t){this.container.contextmenuHandle=t}closeAll(){this.tabbar.items=[],this.resetEditor()}isDirty(){return this.dirties().length>0}}}(e=t.application||(t.application={}))}(OS||(OS={})),function(t){let e;!function(e){class i extends t.application.BaseEditorModel{constructor(t,e,i){super(t,e,i)}resetEditor(){this.setValue("")}getTexModel(){return{model:this.editor.getModel(),position:this.editor.getPosition()}}setTextModel(t){this.editor.setModel(t.model),t.position&&(this.editor.setPosition(t.position),this.editor.revealLineInCenter(t.position.lineNumber))}newTextModelFrom(t){if("Untitled"===t.path.toString())return{model:monaco.editor.createModel(t.cache,"textplain")};const e=monaco.Uri.parse(t.path),i=monaco.editor.getModel(e);return i?(i.setValue(t.cache),{model:i}):{model:monaco.editor.createModel(t.cache,void 0,e)}}getModes(){return monaco.languages.getLanguages().map(t=>(t.text=t.aliases[0],t))}setTheme(t){}setMode(t){monaco.editor.setModelLanguage(this.editor.getModel(),t.id),this.onstatuschange&&this.onstatuschange(this.getEditorStatus())}editorSetup(t){this.editor=monaco.editor.create(t,{value:"",language:"textplain"}),i.modes||(i.modes={},monaco.languages.getLanguages().forEach(t=>{i.modes[t.id]=t}))}on(t,e){switch(t){case"input":this.editor.onDidChangeModelContent(e);break;case"focus":this.editor.onDidFocusEditorText(e);break;case"changeCursor":this.editor.onDidChangeCursorPosition(e)}}resize(){this.editor&&this.editor.layout()}focus(){this.editor&&this.editor.focus()}getModeForPath(t){return{}}getEditorStatus(){const t=this.editor.getPosition(),e=i.modes[this.editor.getModel().getModeId()];return{row:t.lineNumber,column:t.column,line:this.editor.getModel().getLineCount(),langmode:{text:e.aliases[0],mode:e},file:this.currfile.path}}getValue(){return this.editor.getValue()}setValue(t){this.editor.setValue(t)}getEditor(){return this.editor}}e.MonacoEditorModel=i}(e=t.application||(t.application={}))}(OS||(OS={})),function(t){let e;!function(e){class i extends e.BaseApplication{constructor(t){super("Antedit",t),this.currdir=void 0}main(){this.extensions={},this.eum=new a,this.fileview=this.find("fileview"),this.sidebar=this.find("sidebar"),this.bottombar=this.find("bottombar"),this.langstat=this.find("langstat"),this.editorstat=this.find("editorstat"),this.filestat=this.find("current-file-lbl"),this.logger=new s(this.find("output-tab")),this.split_mode=!0,this.fileview.fetch=t=>new Promise((async function(e,i){let a;a="string"==typeof t?t.asFileHandle():t;try{const t=await a.read();return t.error?i(t.error):e(t.result)}catch(t){return i(__e(t))}}));let e="Untitled".asFileHandle();this.args&&this.args.length>0&&(this.addRecent(this.args[0].path),"dir"===this.args[0].type?this.currdir=this.args[0].path.asFileHandle():(e=this.args[0].path.asFileHandle(),this.currdir=e.parent())),this.setting.recent||(this.setting.recent=[]);const i=this.find("wrapper");$(i).css("visibility","hidden"),monaco.editor.setTheme("vs-dark"),this.eum.add(new t.application.MonacoEditorModel(this,this.find("left-tabbar"),this.find("left-editorarea"))).add(new t.application.MonacoEditorModel(this,this.find("right-tabbar"),this.find("right-editorarea"))),this.eum.onstatuschange=t=>this.updateStatus(t),$(i).css("visibility","visible"),this.setup(),this.eum.active.openFile(e)}setup(){this.fileview.onfileopen=t=>{if(t.data&&t.data.path&&"dir"!==t.data.type)return this.addRecent(t.data.path),this.eum.active.openFile(t.data.path.asFileHandle())},this.fileview.onfileselect=t=>{t.data&&t.data.path&&"dir"!==t.data.type&&this.eum.active.selectFile(t.data.path)},this.on("resize",()=>this.eum.resize()),this.on("focus",()=>this.eum.active.focus()),this.fileview.contextmenuHandle=(t,e)=>(e.items=[{text:"__(New file)",id:"new"},{text:"__(New folder)",id:"newdir"},{text:"__(Rename)",id:"rename"},{text:"__(Delete)",id:"delete"}],e.onmenuselect=t=>this.ctxFileMenuHandle(t),e.show(t)),this.bindKey("ALT-N",()=>this.menuAction("new")),this.bindKey("ALT-O",()=>this.menuAction("open")),this.bindKey("ALT-F",()=>this.menuAction("opendir")),this.bindKey("CTRL-S",()=>this.menuAction("save")),this.bindKey("ALT-W",()=>this.menuAction("saveas")),this.fileview.ondragndrop=t=>{const e=t.data.from.data.path.asFileHandle(),i=t.data.to.data.path;return e.move(`${i}/${e.basename}`).then((function(a){const s=i,n=e.parent().path;s.lengththis.error(__("Unable to move file/folder"),t))},this.on("filechange",t=>{let{path:e}=t.file;return"file"===t.type&&({path:e}=t.file.parent()),this.fileview.update(e)}),this.find("logger-clear").onbtclick=()=>{this.logger.clear()},void 0===this.setting.showBottomBar&&(this.setting.showBottomBar=!1);const t={name:"Editor",text:__("Editor")},e={name:"langmode",text:__("Change language mode"),shortcut:"CTRL-K"};this.eum.addAction(t,e,async t=>{try{const t=await this.openDialog("SelectionDialog",{title:__("Select language"),data:this.eum.active.getModes()});this.eum.active.setMode(t)}catch(t){}}),this.loadExtensionMetaData(),this.toggleSideBar(),this.toggleSplitMode(),this.applyAllSetting()}updateStatus(t){t||(t=this.eum.active.getEditorStatus()),this.editorstat.text=__("Row {0}, col {1}, lines: {2}",t.row,t.column,t.line),t.langmode&&(this.langstat.text=t.langmode.text),this.filestat.text=t.file;let e=this.scheme;e.apptitle!=t.file&&(e.apptitle=t.file)}toggleSideBar(){this.currdir?($(this.sidebar).show(),this.fileview.path=this.currdir.path):$(this.sidebar).hide(),this.trigger("resize")}showOutput(t=!1){t&&this.showBottomBar(!0),this.bottombar.selectedIndex=0}applySetting(t){"showBottomBar"==t&&this.showBottomBar(this.setting.showBottomBar)}showBottomBar(t){this.setting.showBottomBar=t,t?$(this.bottombar).show():$(this.bottombar).hide(),this.trigger("resize")}toggleBottomBar(){this.showBottomBar(!this.setting.showBottomBar)}toggleSplitMode(){const t=this.find("right-panel"),e=this.eum.editors[1],i=this.eum.editors[0];if(this.split_mode){if(e.isDirty())return void this.notify(__("Unable to disable split view: Please save changes of modified files on the right panel"));e.closeAll(),$(t).hide(),this.split_mode=!1,i.focus()}else $(t).show(),this.split_mode=!0,e.openFile("Untitled".asFileHandle()),e.focus();this.trigger("resize")}fileMenu(){const t=this.setting.recent.map(t=>({text:t}));return{text:__("File"),nodes:[{text:__("New"),dataid:"new",shortcut:"A-N"},{text:__("Open Recent"),dataid:"recent",nodes:t,onchildselect:(t,e)=>{const i=t.data.item.data.text.asFileHandle();i.onready().then(t=>{t&&("dir"==t.type?(this.currdir=i,this.toggleSideBar()):this.eum.active.openFile(i))})}},{text:__("Open"),dataid:"open",shortcut:"A-O"},{text:__("Open Folder"),dataid:"opendir",shortcut:"A-F"},{text:__("Save"),dataid:"save",shortcut:"C-S"},{text:__("Save as"),dataid:"saveas",shortcut:"A-W"}],onchildselect:(t,e)=>this.menuAction(t.data.item.data.dataid,e)}}ctxFileMenuHandle(t){const e=t.data.item;if(!e)return;const i=e.data;if(!i)return;let a=this.fileview.selectedFile,s=this.currdir;switch(a&&"dir"===a.type&&(s=a.path.asFileHandle()),a&&"file"===a.type&&(s=a.path.asFileHandle().parent()),i.id){case"new":if(!s)return;this.openDialog("PromptDialog",{title:"__(New file)",label:"__(File name)"}).then(async t=>{const e=`${s.path}/${t}`.asFileHandle();try{return await e.write("text/plain"),this.fileview.update(s.path)}catch(t){return this.error(__("Fail to create: {0}",t.stack),t)}});break;case"newdir":if(!s)return;this.openDialog("PromptDialog",{title:"__(New folder)",label:"__(Folder name)"}).then(async t=>{try{return await s.mk(t),this.fileview.update(s.path)}catch(t){return this.error(__("Fail to create: {0}",s.path),t)}});break;case"rename":if(!a)return;this.openDialog("PromptDialog",{title:"__(Rename)",label:"__(File name)",value:a.filename}).then(async t=>{if(t!==a.filename){a=a.path.asFileHandle(),s=a.parent();try{return await a.move(`${s.path}/${t}`),this.fileview.update(s.path)}catch(t){return this.error(__("Fail to rename: {0}",a.path),t)}}});break;case"delete":if(!a)return;this.openDialog("YesNoDialog",{title:"__(Delete)",iconclass:"fa fa-question-circle",text:__("Do you really want to delete: {0}?",a.filename)}).then(async t=>{if(t){a=a.path.asFileHandle(),s=a.parent();try{return await a.remove(),this.fileview.update(s.path)}catch(t){return this.error(__("Fail to delete: {0}",a.path),t)}}})}}addRecent(t){this.setting.recent||(this.setting.recent=[]),this.setting.recent.includes(t)||(this.setting.recent.push(t),this.setting.recent.length>10&&(this.setting.recent=this.setting.recent.slice(0,10)))}menuAction(t,e){let i=this;switch(e&&(i=e),t){case"new":return i.eum.active.openFile("Untitled".asFileHandle());case"open":return i.openDialog("FileDialog",{title:__("Open file"),mimes:Array.from(i.meta().mimes).filter(t=>"dir"!==t)}).then(t=>{this.addRecent(t.file.path),i.eum.active.openFile(t.file.path.asFileHandle())});case"opendir":return i.openDialog("FileDialog",{title:__("Open folder"),mimes:["dir"]}).then((function(t){return i.addRecent(t.file.path),i.currdir=t.file.path.asFileHandle(),i.toggleSideBar()}));case"save":return i.eum.active.save();case"saveas":return i.eum.active.saveAs();default:return console.log(t)}}cleanup(t){let e;const i=this.eum.dirties();if(0!==i.length)t.preventDefault(),this.openDialog("YesNoDialog",{title:"__(Quit)",text:__("Ignore all unsaved files: {0} ?",(()=>{const t=[];for(e of Array.from(i))t.push(e.filename);return t})().join(", "))}).then(t=>{if(t){for(e of Array.from(i))e.dirty=!1;return this.quit(!1)}});else for(let t in this.extensions)this.extensions[t]&&this.extensions[t].cleanup&&this.extensions[t].cleanup()}menu(){return[this.fileMenu(),{text:"__(View)",nodes:[{text:"__(Toggle bottom bar)",dataid:"bottombar"},{text:"__(Toggle split view)",dataid:"splitview"}],onchildselect:(t,e)=>{switch(t.data.item.data.dataid){case"bottombar":return this.toggleBottomBar();case"splitview":return this.toggleSplitMode()}}}]}loadExtensionMetaData(){this.loadExtensionMetaFromFile(this.meta().path+"/extensions/extensions.json").catch(t=>this.error(__("Cannot load extension meta data"),t))}loadExtensionMetaFromFile(t){return new Promise((e,i)=>{t.asFileHandle().read("json").then(t=>{for(let e of t)for(let t of e.actions)this.eum.addAction(e,t,(t,i)=>{this.loadAndRunExtensionAction(t,i,e.root)});e()}).catch(t=>{i(__e(t))})})}loadAndRunExtensionAction(t,e,a){if(i.extensions[t])this.runExtensionAction(t,e);else{let i=`${this.meta().path}/extensions/${t}/main.js`;a&&(i=a+"/main.js"),this._api.requires(i,!0).then(()=>this.runExtensionAction(t,e)).catch(e=>this.error(__("unable to load extension: {0}",t),e))}}runExtensionAction(t,e){if(!this.extensions[t]){if(!i.extensions[t])return this.error(__("Unable to find extension: {0}",t));this.extensions[t]=new i.extensions[t](this)}if(!this.extensions[t][e])return this.error(__("Unable to find action: {0}",e));this.extensions[t].preload().then(()=>this.extensions[t][e]()).catch(t=>this.error(__("Unable to preload extension"),t))}}e.Antedit=i;class a{constructor(){this.active_editor=void 0,this.models=[]}get editors(){return this.models}set contextmenuHandle(t){for(let e of this.models)e.contextmenuHandle=t}get active(){return this.active_editor}add(t){return this.models.push(t),this.active_editor||(this.active_editor=t),t.on("focus",()=>{this.active_editor=t}),this}addAction(t,e,i){const a={id:`${t.name}:${e.name}`,label:`${t.text.__()}: ${e.text.__()}`,keybindings:[],precondition:null,keybindingContext:null,contextMenuGroupId:t.name,run:()=>i(t.name,e.name)};if(e.shortcut){const t=e.shortcut.split("-");let i=0;for(const e of t)switch(e){case"CTRL":i|=monaco.KeyMod.CtrlCmd;break;case"ALT":i|=monaco.KeyMod.Alt;break;case"SHIFT":i|=monaco.KeyMod.Shift;break;case"SUPPER":i|=monaco.KeyMod.WinCtrl;break;default:const t="KEY_"+e;monaco.KeyCode[t]?i|=monaco.KeyCode[t]:i=0}0!=i&&a.keybindings.push(i)}for(let t of this.models){const e=t.getEditor();e.getAction(a.id)||e.addAction(a)}}set onstatuschange(t){for(let e of this.models)e.onstatuschange=t}dirties(){let t=[];for(let e of this.models)t=t.concat(e.dirties());return t}resize(){for(let t of this.models)t.resize()}}class s{constructor(t){this.target=t}info(t){this.log("info",t,!0)}warn(t){this.log("warn",t,!0)}error(t){this.log("error",t,!0)}log(t,e,i){let a=$("
").attr("class","code-pad-log-"+t);if(i){let t=new Date,i=t.getDate()+"/"+(t.getMonth()+1)+"/"+t.getFullYear()+" "+t.getHours()+":"+t.getMinutes()+":"+t.getSeconds();a.text(`[${i}]: ${e.__()}`)}else a.text(e.__());$(this.target).append(a),$(this.target).scrollTop($(this.target)[0].scrollHeight)}print(t){this.log("info",t,!1)}clear(){$(this.target).empty()}}i.Logger=s,i.dependencies=["pkg://MonacoCore/path.js","pkg://MonacoCore/bundle/app.bundle.js"]}(e=t.application||(t.application={}))}(OS||(OS={})),function(t){class e{constructor(t,e){this.app=e,this.name=t}preload(){return t.API.require(t.application.Antedit.extensions[this.name].dependencies)}basedir(){return`${this.app.meta().path}/extensions/${this.name}`}notify(t){return this.app.notify(t)}error(t,e){return this.app.error(t,e)}logger(){return this.app.setting.showBottomBar?this.app.showOutput(!1):this.app.showOutput(!0),this.app.logger}metadata(e){return new Promise((i,a)=>{if(!this.app.currdir)return a(t.API.throwe(__("Current folder is not found")));`${this.app.currdir.path}/${e}`.asFileHandle().read("json").then(t=>{!t.root&&this.app.currdir&&(t.root=this.app.currdir.path),i(t)}).catch(s=>{this.app.openDialog("FileDialog",{title:__("Select build directory"),root:this.app.currdir.path,mimes:["dir"]}).then(t=>{`${t.file.path}/${e}`.asFileHandle().read("json").then(e=>{e.root||(e.root=t.file.path),i(e)}).catch(t=>a(t))}).catch(e=>a(t.API.throwe(__("Unable to read meta-data"))))})})}}e.dependencies=[],t.application.Antedit.extensions={},t.application.Antedit.EditorBaseExtension=e,t.application.Antedit.extensions.EditorExtensionMaker=class extends e{constructor(t){super("EditorExtensionMaker",t)}create(){this.logger().clear(),this.app.openDialog("FileDialog",{title:"__(New extension at)",file:{basename:__("ExtensionName")},mimes:["dir"]}).then(t=>this.mktpl(t.file.path,t.name))}build(e){this.logger().clear(),this.metadata("extension.json").then(async i=>{try{const a=await t.API.VFS.cat(i.javascripts.map(t=>`${i.root}/${t}`),"");await(i.root+"/build/debug/main.js").asFileHandle().setCache(a).write("text/plain"),await(i.root+"/build/debug/extension.json").asFileHandle().setCache(i.meta).write("object"),await t.API.VFS.copy(i.copies.map(t=>`${i.root}/${t}`),i.root+"/build/debug"),this.logger().info(__("Files generated in {0}",i.root+"/build/debug")),e&&e()}catch(t){return this.logger().error(__("Unable to build extension:{0}",t.stack))}}).catch(t=>this.logger().error(__("Unable to read meta-data:{0}",t.stack)))}run(){this.logger().clear(),this.metadata("extension.json").then(async e=>{if(!e||!e.meta||!e.meta.name)return this.logger().error(__("Invalid extension meta-data"));try{const i=e.root+"/build/debug/main.js";t.API.shared[i]&&delete t.API.shared[i],await t.API.requires(i),this.app.extensions[e.meta.name]&&this.app.extensions[e.meta.name].cleanup&&this.app.extensions[e.meta.name].cleanup(),this.app.extensions[e.meta.name]=new t.application.Antedit.extensions[e.meta.name](this.app);for(let t of e.meta.actions)this.app.eum.addAction(e.meta,t,(t,i)=>{this.app.loadAndRunExtensionAction(t,i,e.root+"/build")});this.app.eum.active.getEditor().trigger(e.meta.name,"editor.action.quickCommand")}catch(t){return this.logger().error(__("Unable to run extension:{0}",t.stack))}}).catch(t=>this.logger().error(__("Unable to read meta-data:{0}",t.stack)))}release(){this.logger().clear(),this.metadata("extension.json").then(async e=>{this.build(async()=>{try{await t.API.VFS.mkar(e.root+"/build/debug",`${e.root}/build/release/${e.meta.name}.zip`),this.logger().info(__("Archive created at {0}",`${e.root}/build/release/${e.meta.name}.zip`))}catch(t){return this.logger().error(__("Unable to create archive: {0}",t.stack))}})}).catch(t=>this.logger().error(__("Unable to read meta-data: {0}",t.stack)))}install(){this.logger().clear(),this.app.openDialog("FileDialog",{title:"__(Select extension archive)",mimes:[".*/zip"]}).then(async t=>{try{return await this.installZip(t.file.path),this.logger().info(__("Extension installed")),this.app.loadExtensionMetaData()}catch(t){return this.logger().error(__("Unable to install extension: {0}",t.stack))}})}installFromURL(){this.logger().clear(),this.app.openDialog("PromptDialog",{title:__("Enter URI"),label:__("Please enter extension URI:")}).then(async t=>{if(t)try{return await this.installZip(t),this.logger().info(__("Extension installed")),this.app.loadExtensionMetaData()}catch(e){return this.app.error(__("Unable to install extension: {0}",t))}})}mktpl(e,i){const a=`${e}/${i}`,s=[a,a+"/build",a+"/build/release",a+"/build/debug"],n=[["main.tpl",`${a}/${i}.js`],["meta.tpl",a+"/extension.json"]];t.API.VFS.mkdirAll(s,!0).then(async()=>{try{return await t.API.VFS.mktpl(n,this.basedir(),t=>t.format(i,`${e}/${i}`)),this.app.currdir=a.asFileHandle(),this.app.toggleSideBar(),this.app.eum.active.openFile(`${a}/${i}.js`.asFileHandle())}catch(t){return this.logger().error(__("Unable to create extension template: {0}",t.stack))}}).catch(t=>this.logger().error(__("Unable to create extension directories: {0}",t.stack)))}installZip(e){return new Promise(async(i,a)=>{try{await t.API.requires("os://scripts/jszip.min.js");const a=await e.asFileHandle().read("binary"),s=await JSZip.loadAsync(a),n=await s.file("extension.json").async("uint8array"),o=JSON.parse(new TextDecoder("utf-8").decode(n)),r=this.ext_dir(o.name),l=[r],h=[];for(let t in s.files)s.files[t].dir?l.push(r+"/"+t):"extension.json"!=t&&h.push(t);l.length>0?(await t.API.VFS.mkdirAll(l,!0),await this.installFiles(h,s,o)):await this.installFiles(h,s,o),i()}catch(t){a(__e(t))}})}ext_dir(t){return`${this.app.meta().path}/extensions/${t}`}installFiles(t,e,i){return 0===t.length?this.installMeta(i):new Promise(async(a,s)=>{try{const n=t.splice(0,1)[0],o=`${this.ext_dir(i.name)}/${n}`,r=await e.file(n).async("uint8array"),l=await o.asFileHandle().setCache(new Blob([r],{type:"octet/stream"})).write("text/plain");if(l.error)return s(l.error);await this.installFiles(t,e,i),a()}catch(t){s(__e(t))}})}installMeta(t){return new Promise(async(e,i)=>{const a=(this.ext_dir("")+"/extensions.json").asFileHandle();try{const s=await a.read("json"),n=[];for(let t of s)n.push(t.name);const o=n.indexOf(t.name);o>=0&&s.splice(o,1),s.push(t);try{return await a.setCache(s).write("object"),e()}catch(t){return i(__e(t))}}catch(s){try{return await a.setCache([t]).write("object"),e()}catch(t){return i(__e(t))}}})}}}(OS||(OS={}));
\ No newline at end of file
diff --git a/Antedit/build/debug/package.json b/Antedit/build/debug/package.json
index e01e187..5e061a2 100644
--- a/Antedit/build/debug/package.json
+++ b/Antedit/build/debug/package.json
@@ -1,24 +1,89 @@
 {
     "pkgname": "Antedit",
-    "app":"Antedit",
-    "name":"Antos Editor",
-    "description":"Antos text/code editor",
-    "info":{
+    "app": "Antedit",
+    "name": "Antos Editor",
+    "description": "Antos text/code editor",
+    "info": {
         "author": "Xuan Sang LE",
         "email": "mrsang@iohub.dev"
     },
-    "version":"0.1.8-a",
-    "category":"Development",
-    "iconclass":"bi bi-journal-code",
-    "mimes":[
+    "version": "0.1.8-a",
+    "category": "Development",
+    "iconclass": "bi bi-journal-code",
+    "mimes": [
         "text/.*",
         "[^/]*/json.*",
         "[^/]*/.*ml",
         "[^/]*/javascript",
         "dir"
     ],
-    "dependencies":[
+    "dependencies": [
         "MonacoCore@0.23.0-r"
     ],
-    "locale": {}
+    "locale": {
+        "en_GB": {
+            "Output": "Output",
+            "Close tab": "Close tab",
+            "Close without saving ?": "Close without saving ?",
+            "Unable to open: {0}": "Unable to open: {0}",
+            "Unable to save file: {0}": "Unable to save file: {0}",
+            "Save as": "Save as",
+            "New extension at": "New extension at",
+            "Select extension archive": "Select extension archive",
+            "Current folder is not found": "Current folder is not found",
+            "Select build directory": "Select build directory",
+            "Unable to read meta-data": "Unable to read meta-data",
+            "ExtensionName": "ExtensionName",
+            "Files generated in {0}": "Files generated in {0}",
+            "Unable to build extension:{0}": "Unable to build extension:{0}",
+            "Unable to read meta-data:{0}": "Unable to read meta-data:{0}",
+            "Invalid extension meta-data": "Invalid extension meta-data",
+            "Unable to run extension:{0}": "Unable to run extension:{0}",
+            "Archive created at {0}": "Archive created at {0}",
+            "Unable to read meta-data: {0}": "Unable to read meta-data: {0}",
+            "Extension installed": "Extension installed",
+            "Unable to install extension: {0}": "Unable to install extension: {0}",
+            "Enter URI": "Enter URI",
+            "Please enter extension URI:": "Please enter extension URI:",
+            "Unable to create extension directories: {0}": "Unable to create extension directories: {0}",
+            "New file": "New file",
+            "New folder": "New folder",
+            "Rename": "Rename",
+            "Delete": "Delete",
+            "File name": "File name",
+            "Folder name": "Folder name",
+            "Quit": "Quit",
+            "View": "View",
+            "Toggle bottom bar": "Toggle bottom bar",
+            "Toggle split view": "Toggle split view",
+            "Unable to move file/folder": "Unable to move file/folder",
+            "Editor": "Editor",
+            "Change language mode": "Change language mode",
+            "Select language": "Select language",
+            "Unable to disable split view: Please save changes of modified files on the right panel": "Unable to disable split view: Please save changes of modified files on the right panel",
+            "File": "File",
+            "New": "New",
+            "Open Recent": "Open Recent",
+            "Open": "Open",
+            "Open Folder": "Open Folder",
+            "Save": "Save",
+            "Fail to create: {0}": "Fail to create: {0}",
+            "Fail to rename: {0}": "Fail to rename: {0}",
+            "Fail to delete: {0}": "Fail to delete: {0}",
+            "Open file": "Open file",
+            "Open folder": "Open folder",
+            "Cannot load extension meta data": "Cannot load extension meta data",
+            "unable to load extension: {0}": "unable to load extension: {0}",
+            "Unable to find extension: {0}": "Unable to find extension: {0}",
+            "Unable to find action: {0}": "Unable to find action: {0}",
+            "Unable to preload extension": "Unable to preload extension",
+            "Example action": "Example action",
+            "New Extension": "New Extension",
+            "Build": "Build",
+            "Run": "Run",
+            "Build release": "Build release",
+            "Install extension from file": "Install extension from file",
+            "Install extension from URL": "Install extension from URL"
+        }
+    }
 }
\ No newline at end of file
diff --git a/Antedit/build/release/Antedit.zip b/Antedit/build/release/Antedit.zip
index 77218f9b20688819826b60c2f4af91b461610a32..a5f2c278b6cf3feede115e90d1646c3d2ccd61df 100644
GIT binary patch
delta 2691
zcmZ9Oc|26>AIA?P+t5^&Xk_2A4JKvDlE^X`WJ#_XG1;0Kj3wKg##T2XOSVL~B3*o5zU@83H;x=~iOPjwAqYFYxDW?!bOdL=J?yUVa|$>3gYgu2LKw-P(tL?9Y1
zm{C;gplypgJF~s)+$!@6m&h;7P2>b&Qt?T*<{7Fs@Z7E;z1PotKDm&X+OaG!Y!wdf
z)^@l&+|5YZC3iGR5v~f=8YpBn)e(d!f0AIJwFxKeEXrzSD=cYYG5@34ATLb0UCieK
zZrYE3LMKn^Jndbbg6_tBLB{2}$N4to)>V4p=5x>C`i{`e60m+!NaH-l=fY&{(+%Wg_QDpnFH
z4-L1120l+-QuW5P4Q@U4VHcf97rrr=o!)fe?vDH(+K*#&c$JTJjd@8bvO|7*ObFAi
z!oE>{xBvCF|GvbKeTE0q`-1zI{e{xUzzLE_H{{c!MZvg<#`MeUXR^tZ)aB*fZ-mxm
z%yX9d@aGWp1uz~(w&2Zv+p;ca0F^hLtQ8w(1y5sV+PH<*iueeuFw0HW)JYE6*
zIbddq2uZ<}zkAyv8fmoY9v>(M8eV>TCu@4o?`WdA29q5*yD2tD41cj+7SasSZikz7
zf$}m_tt896zLhG%swR?*Xoc
z;tZ2`t>{)NW!$mR=hR~TqkBibS_zRbnPlRI7@HD&s=2;rj~L+h{y53%Ewnj4qfu2-
zU=Wg9*=^~e>y5H+;Ocb6I~B=#WiS?51i#CdZ9HBU-%2%e&UJN~`h7Uyx`j1MEEus{
zIa8ftAP0l96uf+}ECN!fqG3Tiq&(dDNA(8W9
zba{gPux+035CUS|wPms2+XRYhI~%ExQa*U0FgGKtu?w|EU~8}&NuIMIl{ZfEv{-44
zbaRW`Q-#VJq>xTwB&q8S{=>Yj<%HXHxDw1>A>6@JwmTjT?g<i|!7p6}leKmec*
z1^{d{j=9@AxY;{l}5a;x6i6fa>b!3KA4wy1CDH
zdQ=Jy?)Q%TzT!UL4^cn69yl4PKC>LT(Fb|fsJlg!upvh%$@KowociQdE2BLYFM~$1YfT{I&eiN%`D|BKvB1IuYEgQ6*rH4sc*gTt0ok@;O
z##myP+3&I6*fXt2Fp?=`O0xo&=w&~-H6p)!nscuHP&^q$h>8L&4BP+A&(hWznQuzr
zIa-qXt-bk)T)$WsAGW1$FPqWz5tw?#Tj>2*!O0de#~fu~XG
zpy(L0t(<%&KZg7;nj0%8@KYXB_saHJtDei1qe&6NI^5TE$;rItUX@>%d`n`l@(f>d
zGqf9#ipgTUPPXu|dP6k2Uj^68ZEsC2AWtjAENr({0`+sg*;P-&uvCr*r4
z;evRf^y^U7B32(svw<+Mmy807SVU`P+AHKnz8UzpF>kDbt}?+)mDgWGI07kC%Be(m
zf9s0W6?ayqgx(Z}(8x-HLsw+94}A?GFeg#rvObpeDGr--EGha2R?uW2E1Qj)h8JsQ
z@x3%|*1Gmyy6PVO1Z4v1XffA6z5C%f5x4ev>JON4HCa5Hy^%jv%1#(
z(1FhyqiThO-m#udXa6qQgvjmXxt&r9*IiJ%!?7#ssFYna!=6L8a;eAesm~;^)4e=&
za{-P?AH?fL5aJc`?y?i{=rE7MJWgs;hLR?iIJ(vpcTaV}K|Lg#ceJi{Xk2n$B*5Q5
zh?sQ?l>_U+~sX1+703Et{y|wi4>+CWA!gggd`8dEqhtYNVet&5K|a--hFMJGG&I
z;;VdOYejqT-Ce52kW4;rs9mlP_q;@o9?Sd#o#&G*;)L=kEMRN=c+%-BU!W#x*t*z>
z&88elx$kI7d^|p`Eti
zVNkjP08ED-+M6luY&d%tJPk_!HT?%)QvdKxoc=e>{$q`k6@&AS2>}4n!5NFg$~k-C
zZXcHX-3&HyxSFXb0ATNUVev#40-lICEcrX$CF9^0U9?@LX$(E}kKF;lPc*Jah%b&L
z&i1R355?j10b+4|!lJZGlJ(b=f&`qt=3q)V&Rv4_AKg6Y?-;FqTKv~fga|XYDe4I0
R!SbxM@rWJ(C=v%>e*tFHwH5#X

delta 1976
zcmZWqc|6ql8~=`Latsra47ra%auvDH*c@q)(n@Zl8DTJrZI)$7IciwvV2~|WG>#6_
z*imZ3vMFP-?KsOwqfzS`%nq;m^|Sl=ygsk@>-jv-`}sVd=a1(-;*)zE;^ihNBnAM$
zE?_T$)CzGH667O!Ry9Tdw|#}chtTT4AOPUT)ZP=>f>-@mn<$W;IxkDzk{*k5UpLpq4WeePS?x2mklmFe#*V5(%
z;;PE<;IQhh--PD;4SJubOa4IkMSn+?GD1-S>pVoDTQ+
zQ?ne=Wo9=CiPSrLQk!Bnl-f!hPjQV$CeaJ(X(yL{=fq>K+Dr>!5*qf4nRmW~#`bM$
zUynfj5%(bP(bdF=8$BN@kNZt}%5*nt5*h#Wbb
z%pGhR!2%LIumqKR+p$QLD((6)&;`isYm+nm99ftc#;w_$7oW55@p%y
zDum3u0q(}SVDk+sZ4;)*swJ@0i&fsZfHUE?X>)Hk3c!mo>_Mn@2Qhak-P2aJEPrDTawM2>0?p1qQi=>#g`bxvRLt{lMyYI+Mb_X|PlQR1$Sep5}4S}gWS
z=a|Rh$tw@ILrapVp(+W4mk-Ar*V{#Gyt9l8R+3Z1dJSYp
z*5dXq-v7Wcqgi>$tx6iRHn^jt(VC(uOHK7
z!IJU>fWx`i1Z%5ni#%vGw)f|}$E~#HIMbhG^^R#@vaF``cXJ~4k?R>7rfTn{;IE7Z
zp07`;X-$bG6WUDLl}9}4_Vtsph7~_u#f2Ordi)|2=$M*(?ZB-Zy_$531CJ@4P^RzP
z$q1RxQ=QV%REzL|A_k7W1lXMs$3}68^b{#QR!(P-@G0$x;3pAQ=Ghk
zWJcY*#4XMDn=M_-f8i*n?5U$;!D@7%ub*0mHE4mR_CGdwFC_b3k|vtqnH
z&J%trq?KL_yKlY%ZY&=LE=v}$7Q8`oGI!71>>6!+c5n{a@tI8X`9No?)vobcBQumC
zvbywuhV^g@_Sr-!?m|(WhzWcim)W8HU7%RoimZ;!=|KAvNjLP#S`9DaQ+O#_DVl>_
zQt4+t1+V5H+n4S_Bwt(%T~J;zMkBO0o4od>F|FAcSYN4WR#e~jdrte%W#0y*Hoi@K
z``TeIYW$d{4(0VC%*gFXzfuOiK2fA1iSo`lp-^SDa};Zt+fXvS*mAx50j@#bRs@!H
z$w>9=Y+lpOKmxMB|Kx%|)i&9tmg&GOU4;Mu6A~GQ4l{_1N29#lc7*;%
zM)*qdWl=;3mvt0y{1UzmPHzAJfAw!8n{T3nkkNeE`FG|RDE!m}KM2JaDA66HA5{PV
z;cV~Z;cS2o{YKmVHsb#y#Q^~F#fI`ROO?RU*|+^O2plHRs!Gs>>!|R1u!F=;{$*`(
z$ZCXcxSG_rS9Sqg&0OX4Ia@Auf{Hd+|6gtd>8H~_Px9Hd{MvQCrrXADbv{X7R#;@q
P665cD0RWiQ*s}fsjcP|_

diff --git a/libantosdk/README.md b/libantosdk/README.md
index 30964c2..2a16a6f 100644
--- a/libantosdk/README.md
+++ b/libantosdk/README.md
@@ -2,6 +2,7 @@
 AntOSDK: development API for AntOS based applications/projects
 
 ## Change logs
+- 0.0.7: enable typescript downlevelIteration compile option
 - 0.0.6: add GUI application for building a JSON build file
 - 0.0.5: add API that supports running Linux commands on server
 - 0.0.4: support automatic locale generation
\ No newline at end of file
diff --git a/libantosdk/build.json b/libantosdk/build.json
index b7cf028..a3d6bd2 100644
--- a/libantosdk/build.json
+++ b/libantosdk/build.json
@@ -91,8 +91,8 @@
                 {
                     "name": "linux-exec",
                     "data": {
-                        "cmd": "ls -al .",
-                        "pwd": "home://"
+                        "cmd": "tree .",
+                        "pwd": "home://workspace/antosdk-apps/libantosdk"
                     }
                 }
             ]
diff --git a/libantosdk/build/debug/README.md b/libantosdk/build/debug/README.md
index 30964c2..2a16a6f 100644
--- a/libantosdk/build/debug/README.md
+++ b/libantosdk/build/debug/README.md
@@ -2,6 +2,7 @@
 AntOSDK: development API for AntOS based applications/projects
 
 ## Change logs
+- 0.0.7: enable typescript downlevelIteration compile option
 - 0.0.6: add GUI application for building a JSON build file
 - 0.0.5: add API that supports running Linux commands on server
 - 0.0.4: support automatic locale generation
\ No newline at end of file
diff --git a/libantosdk/build/debug/core/linux.worker.js b/libantosdk/build/debug/core/linux.worker.js
new file mode 100644
index 0000000..4e2c20c
--- /dev/null
+++ b/libantosdk/build/debug/core/linux.worker.js
@@ -0,0 +1,70 @@
+class LinuxJob extends AntOSDKBaseJob {
+    constructor(data)
+    {
+        super(data);
+    }
+    execute()
+    {
+        switch (this.job.cmd) {
+            case 'linux-exec':
+                /**
+                 * Execute a linux command with the
+                 * help of a server side lua API
+                 * script
+                 */
+                this.exec();
+                break;
+            default:
+                const err_msg = `Unkown job ${this.job.cmd}`;
+                this.log_error(err_msg);
+                return this.error(err_msg);
+        }
+    }
+
+    exec()
+    {
+        const path = "pkg://libantosdk/core/lua/api.lua".abspath(this.job.root);
+        const url = API.REST.replace("http","ws") + "/system/apigateway?ws=1";
+        try{
+            const socket = new WebSocket(url);
+            socket.onerror = (e)=> {
+                this.log_error(e.toString());
+                this.error(e);
+                socket.close();
+            };
+            socket.onclose = (e) => {
+                this.log_info("Connection closed");
+                this.result("Done");
+            };
+            socket.onopen = (e) => {
+                // send the command
+                const cmd = {
+                    path: path,
+                    parameters: {
+                        action: "exec",
+                        args: this.job.data
+                    }
+                };
+                socket.send(JSON.stringify(cmd));
+            };
+            socket.onmessage = (e) => {
+                const json = JSON.parse(e.data);
+                if(json.error)
+                {
+                    this.log_error(json.error);
+                }
+                else
+                {
+                    this.log_print(json.result);
+                }
+            }
+        }
+        catch(error)
+        {
+            this.log_error(error.toString());
+            return this.error(error);
+        }
+    }
+}
+
+API.jobhandle["linux-exec"] = LinuxJob;
\ No newline at end of file
diff --git a/libantosdk/build/debug/core/lua/api.lua b/libantosdk/build/debug/core/lua/api.lua
new file mode 100644
index 0000000..d7d1c44
--- /dev/null
+++ b/libantosdk/build/debug/core/lua/api.lua
@@ -0,0 +1,31 @@
+local args=...
+
+local result = function(data)
+    return { error = false, result = data }
+end
+
+local error = function(msg)
+    return {error = msg, result = false}
+end
+
+local handle = {}
+
+handle.exec = function(data)
+    local cmd = data.cmd
+    if data.pwd then
+        cmd = "cd "..require("vfs").ospath(data.pwd).. " && "..cmd
+    end
+    cmd = cmd.." 2>&1"
+    local pipe = io.popen(cmd)
+    for line in pipe:lines() do
+        echo(JSON.encode(result(line)))
+    end
+    pipe:close()
+    return result("Done: ["..cmd.."]")
+end
+
+if args.action and handle[args.action] then
+    return handle[args.action](args.args)
+else
+    return error("Invalid action parameter")
+end
\ No newline at end of file
diff --git a/libantosdk/build/debug/core/ts.worker.js b/libantosdk/build/debug/core/ts.worker.js
index f43295c..3b27bcb 100644
--- a/libantosdk/build/debug/core/ts.worker.js
+++ b/libantosdk/build/debug/core/ts.worker.js
@@ -92,6 +92,7 @@ class TSJob extends AntOSDKBaseJob {
                 const program = ts.createProgram(files, {
                     "target": "es6",
                     "skipLibCheck": true,
+                    "downlevelIteration": true
                 }, host);
                 const result = program.emit();
                 const diagnostics = result.diagnostics.concat((ts.getPreEmitDiagnostics(program)));
diff --git a/libantosdk/build/debug/main.css b/libantosdk/build/debug/main.css
new file mode 100644
index 0000000..1dc60b8
--- /dev/null
+++ b/libantosdk/build/debug/main.css
@@ -0,0 +1,32 @@
+afx-app-window[data-id = "SDKBuilder"] afx-resizer {
+    border-left: 1px solid #656565;
+    background-color:transparent;
+}
+
+afx-app-window[data-id = "SDKBuilder"] div[data-id="container"] {
+    overflow-y: auto;
+    overflow-x: hidden;
+    user-select: text;
+}
+
+afx-app-window[data-id = "SDKBuilder"] div[data-id="container"] 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 = "SDKBuilder"] div[data-id="container"] pre.sdk-log-error {
+    color: red;
+}
+
+afx-app-window[data-id = "SDKBuilder"] div[data-id="container"] pre.sdk-log-warn {
+    color: orange;
+}
+
+afx-app-window[data-id = "SDKBuilder"] div[data-id="container"] pre.sdk-log-info {
+    color: green;
+}
\ No newline at end of file
diff --git a/libantosdk/build/debug/package.json b/libantosdk/build/debug/package.json
index 2d83386..3338b90 100644
--- a/libantosdk/build/debug/package.json
+++ b/libantosdk/build/debug/package.json
@@ -7,7 +7,7 @@
         "author": "Xuan Sang LE",
         "email": "mrsang@iohub.dev"
     },
-    "version": "0.0.6-a",
+    "version": "0.0.7-a",
     "category": "Development",
     "iconclass": "fa fa-cog",
     "mimes": [
diff --git a/libantosdk/build/debug/scheme.html b/libantosdk/build/debug/scheme.html
new file mode 100644
index 0000000..938ddbc
--- /dev/null
+++ b/libantosdk/build/debug/scheme.html
@@ -0,0 +1,30 @@
+
+    
+        
+            
+ +
+ + + + +
+
+
+
+ + +
+ +
+
+
+
+ + +
+
+
+
+
+
\ No newline at end of file diff --git a/libantosdk/build/release/libantosdk.zip b/libantosdk/build/release/libantosdk.zip index 83e9b95b484122aecceb887c63f9b499cf345779..a44175d70a17fcef9ed2349d7ff2d9fe87e0496b 100644 GIT binary patch delta 3186 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 delta 3050 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 diff --git a/libantosdk/core/linux.worker.js b/libantosdk/core/linux.worker.js new file mode 100644 index 0000000..4e2c20c --- /dev/null +++ b/libantosdk/core/linux.worker.js @@ -0,0 +1,70 @@ +class LinuxJob extends AntOSDKBaseJob { + constructor(data) + { + super(data); + } + execute() + { + switch (this.job.cmd) { + case 'linux-exec': + /** + * Execute a linux command with the + * help of a server side lua API + * script + */ + this.exec(); + break; + default: + const err_msg = `Unkown job ${this.job.cmd}`; + this.log_error(err_msg); + return this.error(err_msg); + } + } + + exec() + { + const path = "pkg://libantosdk/core/lua/api.lua".abspath(this.job.root); + const url = API.REST.replace("http","ws") + "/system/apigateway?ws=1"; + try{ + const socket = new WebSocket(url); + socket.onerror = (e)=> { + this.log_error(e.toString()); + this.error(e); + socket.close(); + }; + socket.onclose = (e) => { + this.log_info("Connection closed"); + this.result("Done"); + }; + socket.onopen = (e) => { + // send the command + const cmd = { + path: path, + parameters: { + action: "exec", + args: this.job.data + } + }; + socket.send(JSON.stringify(cmd)); + }; + socket.onmessage = (e) => { + const json = JSON.parse(e.data); + if(json.error) + { + this.log_error(json.error); + } + else + { + this.log_print(json.result); + } + } + } + catch(error) + { + this.log_error(error.toString()); + return this.error(error); + } + } +} + +API.jobhandle["linux-exec"] = LinuxJob; \ No newline at end of file diff --git a/libantosdk/core/lua/api.lua b/libantosdk/core/lua/api.lua new file mode 100644 index 0000000..d7d1c44 --- /dev/null +++ b/libantosdk/core/lua/api.lua @@ -0,0 +1,31 @@ +local args=... + +local result = function(data) + return { error = false, result = data } +end + +local error = function(msg) + return {error = msg, result = false} +end + +local handle = {} + +handle.exec = function(data) + local cmd = data.cmd + if data.pwd then + cmd = "cd "..require("vfs").ospath(data.pwd).. " && "..cmd + end + cmd = cmd.." 2>&1" + local pipe = io.popen(cmd) + for line in pipe:lines() do + echo(JSON.encode(result(line))) + end + pipe:close() + return result("Done: ["..cmd.."]") +end + +if args.action and handle[args.action] then + return handle[args.action](args.args) +else + return error("Invalid action parameter") +end \ No newline at end of file diff --git a/libantosdk/core/ts.worker.js b/libantosdk/core/ts.worker.js index f43295c..3b27bcb 100644 --- a/libantosdk/core/ts.worker.js +++ b/libantosdk/core/ts.worker.js @@ -92,6 +92,7 @@ class TSJob extends AntOSDKBaseJob { const program = ts.createProgram(files, { "target": "es6", "skipLibCheck": true, + "downlevelIteration": true }, host); const result = program.emit(); const diagnostics = result.diagnostics.concat((ts.getPreEmitDiagnostics(program))); diff --git a/libantosdk/main.css b/libantosdk/main.css new file mode 100644 index 0000000..1dc60b8 --- /dev/null +++ b/libantosdk/main.css @@ -0,0 +1,32 @@ +afx-app-window[data-id = "SDKBuilder"] afx-resizer { + border-left: 1px solid #656565; + background-color:transparent; +} + +afx-app-window[data-id = "SDKBuilder"] div[data-id="container"] { + overflow-y: auto; + overflow-x: hidden; + user-select: text; +} + +afx-app-window[data-id = "SDKBuilder"] div[data-id="container"] 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 = "SDKBuilder"] div[data-id="container"] pre.sdk-log-error { + color: red; +} + +afx-app-window[data-id = "SDKBuilder"] div[data-id="container"] pre.sdk-log-warn { + color: orange; +} + +afx-app-window[data-id = "SDKBuilder"] div[data-id="container"] pre.sdk-log-info { + color: green; +} \ No newline at end of file diff --git a/libantosdk/package.json b/libantosdk/package.json index 2d83386..3338b90 100644 --- a/libantosdk/package.json +++ b/libantosdk/package.json @@ -7,7 +7,7 @@ "author": "Xuan Sang LE", "email": "mrsang@iohub.dev" }, - "version": "0.0.6-a", + "version": "0.0.7-a", "category": "Development", "iconclass": "fa fa-cog", "mimes": [ diff --git a/libantosdk/ts/app.ts b/libantosdk/ts/app.ts new file mode 100644 index 0000000..e644d40 --- /dev/null +++ b/libantosdk/ts/app.ts @@ -0,0 +1,213 @@ +namespace OS { + declare var $: any; + export namespace application { + class Logger { + + /** + * Referent to the log container + * + * @private + * @type {HTMLElement} + * @memberof Logger + */ + private target: HTMLElement; + + + /** + * Creates an instance of Logger. + * @param {HTMLElement} el target container + * @memberof Logger + */ + constructor(el: HTMLElement) { + this.target = el; + } + + /** + * Log level info + * + * @param {string|FormattedString} s + * @memberof Logger + */ + info(s: string | FormattedString): void { + this.log("info", s, true); + } + + /** + * Log level warning + * + * @param {string|FormattedString} s + * @memberof Logger + */ + warn(s: string | FormattedString): void { + this.log("warn", s, true); + } + + /** + * Log level error + * + * @param {string|FormattedString} s + * @memberof Logger + */ + error(s: string | FormattedString): void { + this.log("error", s, true); + } + + + /** + * Log a string to target container + * + * @private + * @param {string} c class name of the appended log element + * @param {string|FormattedString} s log string + * @param {boolean} showtime define whether the logger should insert datetime prefix + * in the log string + * @memberof Logger + */ + private log(c: string, s: string | FormattedString, showtime: boolean): void { + let el = $("
")
+                    .attr("class", `sdk-log-${c}`);
+                if (showtime) {
+                    let date = new Date();
+                    let prefix = date.getDate() + "/"
+                        + (date.getMonth() + 1) + "/"
+                        + date.getFullYear() + " "
+                        + date.getHours() + ":"
+                        + date.getMinutes() + ":"
+                        + date.getSeconds();
+                    el.text(`[${prefix}]: ${s.__()}`);
+                }
+                else {
+                    el.text(s.__());
+                }
+                $(this.target).append(el);
+                $(this.target).scrollTop($(this.target)[0].scrollHeight);
+            }
+
+            /**
+             * Print a log message without prefix
+             *
+             * @param {string|FormattedString} s text to print
+             * @memberof Logger
+             */
+            print(s: string | FormattedString): void {
+                if(s.match(/warn/i))
+                {
+                    this.log("warn", s, false);
+                }
+                else if(s.match(/error/i))
+                {
+                    this.log("error", s, false);
+                }
+                else
+                {
+                    this.log("info", s, false);
+                }
+            }
+
+            /**
+             * Empty the log container
+             *
+             * @memberof Logger
+             */
+            clear(): void {
+                $(this.target).empty();
+            }
+        }
+        /**
+         *
+         * @class libantosdk
+         * @extends {BaseApplication}
+         */
+        export class libantosdk extends BaseApplication {
+            private sdk: API.AntOSDKBuilder;
+            private logger: Logger;
+            private filehandle: OS.API.VFS.BaseFileHandle;
+            private options: GenericObject;
+            private targets: OS.GUI.tag.ListViewTag;
+            constructor(args: AppArgumentsType[]) {
+                super("libantosdk", args);
+            }
+            main(): void {
+                this.logger = new Logger(this.find("container"));
+                this.sdk = new API.AntOSDKBuilder(this.logger,"");
+                this.filehandle = undefined;
+                this.options = undefined;
+                this.targets = this.find("target-list") as OS.GUI.tag.ListViewTag;
+                if(this.args && this.args.length > 0)
+                    this.filehandle = this.args[0].path.asFileHandle();
+
+                (this.find("btnbuild") as GUI.tag.ButtonTag).onbtclick = (e) => {
+                    const selected = this.targets.selectedItem;
+                    if(!selected)
+                        return;
+                    this.load(this.compile([selected.data.text]));
+                }
+
+                (this.find("btnclear") as GUI.tag.ButtonTag).onbtclick = (e) => {
+                    this.logger.clear();
+                }
+
+                (this.find("btnrefresh") as GUI.tag.ButtonTag).onbtclick = (e) => {
+                    this.open();
+                }
+                (this.find("btnopen") as GUI.tag.ButtonTag).onbtclick = async (e) => {
+                    try{
+                        const d = await this.openDialog("FileDialog", {
+                            title: __("Select build file"),
+                            mimes: this.meta().mimes
+                        });
+                        this.filehandle = d.file.path.asFileHandle();
+                        this.open();
+                    }
+                    catch(error)
+                    {
+                        this.logger.error(error.toString());
+                    }
+                }
+                this.open();
+            }
+            
+            private open(): void {
+                if(this.filehandle === undefined)
+                {
+                    return;
+                }
+                this.filehandle
+                    .read("json")
+                    .then((data) => {
+                        if(! data.targets)
+                        {
+                            return this.logger.error(
+                                __("Invalid build file: {0}", this.filehandle.path)
+                            );
+                        }
+                        const targets = Object.keys(data.targets).map(e =>{
+                            return {text: e};
+                        } );
+                        (this.scheme as GUI.tag.WindowTag).apptitle = this.filehandle.path;
+                        this.options = data;
+                        this.options.root = this.filehandle.parent().path;
+                        this.targets.data = targets;
+                        this.logger.info(__("Loaded: {0}", this.filehandle.path));
+                    })
+                    .catch((e) => this.logger.error(
+                        __("Unable to load build file: {0}: {1}", this.filehandle.path, e.toString())));
+            }
+
+            private compile(stages: string[]): Promise {
+                return new Promise( async (resolve, reject) => {
+                    try {
+                        this.logger.clear();
+                        await this.sdk.batch(stages,this.options);
+                        resolve("OK");
+                    }
+                    catch(e)
+                    {
+                        reject(__e(e));
+                    }
+                    
+                })
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages.json b/packages.json
index b590f1b..4b63f8e 100644
--- a/packages.json
+++ b/packages.json
@@ -195,7 +195,7 @@
 		"description": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/libantosdk/README.md",
 		"category": "Development",
 		"author": "Xuan Sang LE",
-		"version": "0.0.6-a",
+		"version": "0.0.7-a",
 		"dependencies": [],
 		"download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/libantosdk/build/release/libantosdk.zip"
 	},