2020-05-19 20:00:56 +02:00

217 lines
8.9 KiB
CoffeeScript

# import the CodePad application module
App = this.OS.APP.CodePad
# define the extension
class App.extensions.ExtensionMaker extends App.BaseExtension
constructor: (app) ->
super app
# public functions
create: () ->
@app.openDialog("FileDialog", {
title: "__(New CodePad extension at)",
file: { basename: __("ExtensionName") },
mimes: ["dir"]
}).then (d) =>
@mktpl d.file.path, d.name
buildnrun: () ->
@metadata("extension.json").then (meta) =>
@build(meta).then () =>
@run(meta).catch (e) => @error __("Unable to run extension"), e
.catch (e) =>
@error __("Unable to build extension"), e
.catch (e) => @error __("Unable to read meta-data"), e
release: () ->
@metadata("extension.json").then (meta) =>
@build(meta).then () =>
@mkar("#{meta.root}/build/debug",
"#{meta.root}/build/release/#{meta.meta.name}.zip")
.then () ->
.catch (e) => @error __("Unable to create archive"), e
.catch (e) =>
@error __("Unable to build extension"), e
.catch (e) => @error __("Unable to read meta-data"), e
install: () ->
@app.openDialog("FileDialog", {
title: "__(Select extension archive)",
mimes: [".*/zip"]
}).then (d) =>
@installZip d.file.path
.then () =>
@notify __("Extension installed")
@app.loadExtensionMetaData()
.catch (e) => @error __("Unable to install extension"), e
# private functions
mktpl: (path, name) ->
rpath = "#{path}/#{name}"
dirs = [
rpath,
"#{rpath}/build",
"#{rpath}/build/release",
"#{rpath}/build/debug"
]
files = [
["templates/ext-main.tpl", "#{rpath}/#{name}.coffee"],
["templates/ext-extension.tpl", "#{rpath}/extension.json"],
]
@mkdirAll dirs
.then () =>
@mkfileAll(files, path, name)
.then () =>
@app.currdir = rpath.asFileHandle()
@app.initSideBar()
@app.openFile "#{rpath}/#{name}.coffee".asFileHandle()
.catch (e) => @error __("Unable to create extension template"), e
.catch (e) => @error __("Unable to create extension directories"), e
verify: (list) ->
new Promise (resolve, reject) =>
return resolve() if list.length is 0
file = (list.splice 0, 1)[0].asFileHandle()
@notify __("Verifying: {0}", file.path)
file.read().then (data) =>
try
CoffeeScript.nodes data
@verify list
.then () -> resolve()
.catch (e) -> reject e
catch ex
reject ex
.catch (e) -> reject e
compile: (meta) ->
new Promise (resolve, reject) =>
@import("#{@basedir()}/coffeescript.js").then () =>
list = ("#{meta.root}/#{v}" for v in meta.coffees)
@verify((f for f in list)).then () =>
@cat(list).then (code) =>
jsrc = CoffeeScript.compile code
@notify __("Compiled successful")
resolve jsrc
.catch (e) -> reject e
.catch (e) -> reject e
.catch (e) -> reject e
build: (meta) ->
new Promise (resolve, reject) =>
@compile(meta).then (src) =>
@cat ("#{meta.root}/#{v}" for v in meta.javascripts), src
.then (jsrc) ->
new Promise (r, e) ->
"#{meta.root}/build/debug/#{meta.meta.name}.js"
.asFileHandle()
.setCache jsrc
.write("text/plain")
.then (d) ->
r()
.catch (ex) -> e ex
.then () ->
new Promise (r, e) ->
"#{meta.root}/build/debug/extension.json"
.asFileHandle()
.setCache meta.meta
.write("object")
.then (data) ->
r data
.catch (ex) -> e ex
.then () =>
@copy ("#{meta.root}/#{v}" for v in meta.copies), "#{meta.root}/build/debug"
.then () -> resolve()
.catch (e) -> reject e
.catch (e) -> reject e
run: (meta) ->
new Promise (resolve, reject) =>
path = "#{meta.root}/build/debug/#{meta.meta.name}.js"
delete @app._api.shared[path] if @app._api.shared[path]
@app._api.requires path
.then () =>
if @app.extensions[meta.meta.name]
@app.extensions[meta.meta.name].child = []
@app.extensions[meta.meta.name].addAction v for v in meta.meta.actions
else
@app.extensions[meta.meta.name] = new App.CMDMenu meta.meta.text
@app.extensions[meta.meta.name].name = meta.meta.name
@app.extensions[meta.meta.name].addAction v for v in meta.meta.actions
@app.spotlight.addAction @app.extensions[meta.meta.name]
@app.extensions[meta.meta.name].onchildselect (e) =>
@app.loadAndRunExtensionAction e.data.item.get "data"
@app.spotlight.run @app
resolve()
.catch (e) -> reject e
installExtension: (files, zip) ->
new Promise (resolve, reject) =>
idx = files.indexOf "extension.json"
reject(@app._api.throwe __("No meta-data found")) if idx < 0
metafile = (files.splice idx, 1)[0]
# read the meta file
zip.file(metafile).async("uint8array").then (d) =>
meta = JSON.parse(new TextDecoder("utf-8").decode(d))
@installFiles files, zip, meta
.then () -> resolve()
.catch (e) -> reject e
.catch (e) -> reject e
installFiles: (files, zip, meta) ->
return @installMeta(meta) if files.length is 0
new Promise (resolve, reject) =>
file = (files.splice 0, 1)[0]
path = "#{@basedir()}/#{file}"
zip.file(file).async("uint8array").then (d) =>
path.asFileHandle()
.setCache(new Blob [d], { type: "octet/stream" })
.write("text/plain").then (r) =>
return reject r.error if r.error
@installFiles files, zip, meta
.then () -> resolve()
.catch (e) -> reject e
.catch (e) -> reject e
.catch (e) -> reject e
installMeta: (meta) ->
new Promise (resolve, reject) =>
file = "#{@app.meta().path}/extensions.json".asFileHandle()
file.read("json").then (data) ->
names = (v.name) for v in data
idx = name.indexOf meta.name
data.splice idx, 1 if idx >= 0
data.push meta
file.setCache data
.write("object")
.then () -> resolve()
.catch (e) -> reject e
.catch (e) -> reject e
installZip: (path) ->
new Promise (resolve, reject) =>
@import("os://scripts/jszip.min.js").then () =>
path.asFileHandle().read("binary").then (data) =>
JSZip.loadAsync(data).then (zip) =>
pth = @basedir()
dir = []
files = []
for name, file of zip.files
if file.dir
dir.push(pth + "/" + name)
else
files.push name
if dir.length > 0
@mkdirAll dir
.then () =>
@installExtension files, zip
.then () -> resolve()
.catch(e) -> reject(e)
.catch (e) -> reject e
else
@installExtension files, zip
.then () -> resolve()
.catch (e) -> reject(e)
.catch (e) -> reject e
.catch (e) -> reject e
.catch (e) -> reject e