()
211 |
212 | for (const element of Deno.readDirSync(root)) {
213 | const folder: FileExplorer = {
214 | id: btoa(path.join(root, element.name)),
215 | isFile: element.isFile,
216 | name: element.name,
217 | size: ""
218 | }
219 | folders.push(folder)
220 | }
221 |
222 | folders = sortByName(folders)
223 | folders = sortByType(folders)
224 | return folders
225 | }
226 |
--------------------------------------------------------------------------------
/src/utils_test.ts:
--------------------------------------------------------------------------------
1 | import * as utils from "./utils.ts"
2 | import { assert } from "./test_deps.ts"
3 |
4 | Deno.test("test_utils_getOs", function () {
5 | assert(utils.getOsInfo().os.length > 2)
6 | })
7 |
8 | Deno.test("test_utils_getDirInfo", function () {
9 | assert(utils.getDenoDir().includes("deno"))
10 | })
11 |
12 | Deno.test("test_utils_getTypeScriptCacheDirLocal", function () {
13 | assert(utils.getTypeScriptCacheDirLocal().includes("gen"))
14 | })
15 |
--------------------------------------------------------------------------------
/src/views/_shared/_layout.css.ts:
--------------------------------------------------------------------------------
1 | export const css = `
2 | body {
3 | -webkit-font-smoothing: antialiased;
4 | -moz-font-smoothing: grayscale;
5 | }
6 | #container {
7 | margin-top:18px;
8 | }
9 | #sidebar {
10 | position: fixed;
11 | height: 100vh;
12 | background-color: #f5f5f5;
13 | padding-top: 68px;
14 | padding-left: 0;
15 | padding-right: 0;
16 | }
17 |
18 | #sidebar .ui.menu > a.item {
19 | padding: 10px 20px;
20 | line-height: 20px;
21 | color: #337ab7;
22 | border-radius: 0 !important;
23 | margin-top: 0;
24 | margin-bottom: 0;
25 | }
26 |
27 | #sidebar .ui.menu > a.item.active {
28 | background-color: #337ab7;
29 | color: white;
30 | border: none !important;
31 | }
32 |
33 | #sidebar .ui.menu > a.item:hover {
34 | background-color: #eee;
35 | color: #23527c;
36 | }
37 |
38 | #content {
39 | padding-top: 56px;
40 | padding-left: 20px;
41 | padding-right: 20px;
42 | }
43 |
44 | #content h1 {
45 | font-size: 36px;
46 | }
47 |
48 | #content .ui.dividing.header {
49 | width: 100%;
50 | }
51 |
52 | .ui.centered.small.circular.image {
53 | margin-top: 14px;
54 | margin-bottom: 14px;
55 | }
56 |
57 | .ui.borderless.menu {
58 | box-shadow: none;
59 | flex-wrap: wrap;
60 | border: none;
61 | padding-left: 0;
62 | padding-right: 0;
63 | }
64 |
65 | .ui.mobile.only.grid .ui.menu .ui.vertical.menu {
66 | display: none;
67 | }
68 |
69 | @media only screen and (min-width: 992px) {
70 | .ui.column.grid>[class*="thirteen wide computer"].column, .ui.grid>.column.row>[class*="thirteen wide computer"].column, .ui.grid>.row>[class*="thirteen wide computer"].column, .ui.grid>[class*="thirteen wide computer"].column {
71 | width: 87.00%!important;
72 | }
73 | }
74 | `
75 |
--------------------------------------------------------------------------------
/src/views/_shared/_layout.ts:
--------------------------------------------------------------------------------
1 | export const _layout_template = `
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Deno GUI
12 |
13 |
15 |
16 |
19 |
20 |
21 |
22 |
23 |
Loading
24 |
25 |
26 |
27 |
30 |
31 |
32 |
52 |
53 |
54 |
55 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
Deno GUI
71 |
Loading ...
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
82 |
84 |
85 |
86 |
87 |
190 |
191 |
192 |
193 | `
194 |
--------------------------------------------------------------------------------
/src/views/components/about.ts:
--------------------------------------------------------------------------------
1 | export const title = "About Deno GUI"
2 | export const body = `
3 | Deno GUI
4 | A Web interface for Deno
5 |
6 | Credits
7 |
8 |
9 |
10 |
11 |
12 |
Deno : A secure runtime for JavaScript and TypeScript
13 |
14 |
15 |
16 |
17 |
18 |
19 |
oak : A middleware framework for Deno's net server
20 |
21 |
22 |
23 |
24 |
25 |
26 |
lodash : A modern JavaScript utility library delivering modularity, performance & extras.
27 |
28 |
29 |
30 |
31 |
32 |
33 |
Semantic UI : UI component framework based around useful principles from natural language.
34 |
35 |
36 |
37 |
38 |
39 |
40 |
Monaco Editor : The Monaco Editor is the code editor that powers VS Code.
41 |
42 |
43 |
44 |
45 |
46 |
47 |
Xterm.js : A terminal for the web.
48 |
49 |
50 |
51 |
52 |
53 |
54 |
jQuery : write less, do more.
55 |
56 |
57 |
58 |
59 |
60 |
61 |
axios : Promise based HTTP client for the browser and node.js
62 |
63 |
64 |
65 |
66 |
67 |
68 |
ink : Terminal string color for Deno
69 |
70 |
71 |
72 |
73 |
74 |
75 |
cowsay : Configurable talking cow for Deno
76 |
77 |
78 |
79 |
80 |
81 | Author
82 |
83 |
84 |
85 |
86 |
93 |
94 |
95 |
96 |
97 |
98 | s.fakoua@gmail.com
99 |
100 |
101 |
107 |
108 |
109 | `
110 | export const onBeforeRender = ``
111 | export const onAfterRender = `
112 | inlineScript = function () {
113 | $('.special.cards .image').dimmer({
114 | on: 'hover'
115 | });
116 | }
117 | `
118 |
--------------------------------------------------------------------------------
/src/views/components/console.ts:
--------------------------------------------------------------------------------
1 | export const title = "Web REPL"
2 | export const body = `
3 |
4 |
5 |
6 |
7 | Run
8 |
9 |
10 |
11 | Examples
12 |
63 |
64 |
65 |
66 |
67 | // Text To Speech
68 | import * as swissKnife from "https://deno.land/x/swissKnife/mod.ts"
69 | await swissKnife.speak("Hello from Deno", {rate: 1, volume: 100})
70 | console.log("Done.")
71 |
72 |
73 | // Play Beep
74 | import * as swissKnife from "https://deno.land/x/swissKnife/mod.ts"
75 | await swissKnife.beep(500, 1000) //play 500 hz for 1 sec.
76 |
77 |
78 |
79 | // Show Windows Notification
80 | import * as swissKnife from "https://deno.land/x/swissKnife/mod.ts"
81 | await swissKnife.notification("My Title", "Hello Notification", 77, 2000)
82 |
83 |
84 |
85 | // Question box. NB
86 | // NB: The message box may appear in the background.
87 | import * as swissKnife from "https://deno.land/x/swissKnife/mod.ts"
88 |
89 | let res = await swissKnife.questionBox("A Question", "Do you want to quite smoking?")
90 | if (res) {
91 | console.log("Great, keep trying!")
92 | } else {
93 | console.log("Not Great, but keep trying!")
94 | }
95 |
96 |
97 |
98 | // ByteSize
99 | import "https://deno.land/x/humanizer/byteSize.ts"
100 |
101 | let fileSize = (10).kilobytes()
102 | console.log(fileSize.bits) // 81920
103 | console.log(fileSize.bytes) // 10240
104 | console.log(fileSize.kilobytes) // 10
105 | console.log(fileSize.megabytes) // 0.009765625
106 | console.log(fileSize.gigabytes) // 0.0000095367431640625
107 | console.log(fileSize.terabytes) // 9.313225746154785e-9
108 |
109 |
110 |
111 | // ByteSize
112 | import "https://deno.land/x/humanizer/byteSize.ts"
113 |
114 | let f = (4).gigabytes().add((22).megabytes()).subtract((980).kilobytes()).addGigabytes(1)
115 | console.log(f.toString()) // - 5.020549774169922 GB
116 |
117 |
118 |
119 | import "https://deno.land/x/humanizer/vocabularies.ts"
120 |
121 | console.log("Man".pluralize())
122 | console.log("string".pluralize())
123 |
124 | //Singularize
125 |
126 | console.log("Men".singularize())
127 | console.log("strings".singularize())
128 |
129 |
130 |
131 | import "https://deno.land/x/humanizer/ordinalize.ts"
132 |
133 | console.log((1).ordinalize())
134 | console.log((5).ordinalize())
135 |
136 |
137 |
138 | import { ShowQuantityAs } from "https://deno.land/x/humanizer/toQuantity.ts"
139 |
140 | console.log("case".toQuantity(0))
141 | console.log("case".toQuantity(1))
142 | console.log("case".toQuantity(5))
143 | console.log("man".toQuantity(0))
144 | console.log("man".toQuantity(1))
145 | console.log("man".toQuantity(2))
146 |
147 | //ToQuantity can figure out whether the input word is singular or plural and will singularize or pluralize as necessary:
148 |
149 | console.log("men".toQuantity(2))
150 | console.log("process".toQuantity(2))
151 | console.log("process".toQuantity(1))
152 | console.log("processes".toQuantity(2))
153 | console.log("processes".toQuantity(1))
154 |
155 | /*
156 | You can also pass a second argument, ShowQuantityAs, to toQuantity to specify how you want the provided quantity
157 | to be outputted. The default value is ShowQuantityAs.Numeric which is what we saw above. The other two values are
158 | ShowQuantityAs.Words and ShowQuantityAs.None.
159 | */
160 |
161 | console.log("case".toQuantity(5, ShowQuantityAs.Words))
162 | console.log("case".toQuantity(5, ShowQuantityAs.None))
163 |
164 |
165 |
166 | import "https://deno.land/x/humanizer/numberToNumbers.ts"
167 |
168 | console.log((1.25).billions())
169 | console.log((3).hundreds().thousands())
170 |
171 |
172 |
173 | import "https://deno.land/x/humanizer/numberToWords.ts"
174 |
175 | console.log((1).toWords())
176 | console.log((10).toWords())
177 | console.log((11).toWords())
178 | console.log((122).toWords())
179 | console.log((3501).toWords())
180 |
181 |
182 |
183 | import "https://deno.land/x/humanizer/numberToWords.ts"
184 |
185 | console.log((0).toOrdinalWords())
186 | console.log((1).toOrdinalWords())
187 | console.log((2).toOrdinalWords())
188 | console.log((8).toOrdinalWords())
189 | console.log((10).toOrdinalWords())
190 | console.log((11).toOrdinalWords())
191 | console.log((12).toOrdinalWords())
192 | console.log((20).toOrdinalWords())
193 | console.log((21).toOrdinalWords())
194 | console.log((121).toOrdinalWords())
195 |
196 |
197 |
198 | import "https://deno.land/x/humanizer/romanNumerals.ts"
199 |
200 | console.log((1).toRoman())
201 | console.log((2).toRoman())
202 | console.log((3).toRoman())
203 | console.log((4).toRoman())
204 | console.log((5).toRoman())
205 | console.log((6).toRoman())
206 | console.log((7).toRoman())
207 | console.log((8).toRoman())
208 | console.log((9).toRoman())
209 | console.log((10).toRoman())
210 |
211 | //Also the reverse operation using the fromRoman extension.
212 |
213 | console.log("I".fromRoman())
214 | console.log("II".fromRoman())
215 | console.log("III".fromRoman())
216 | console.log("IV".fromRoman())
217 | console.log("V".fromRoman())
218 |
219 |
220 |
221 | import "https://deno.land/x/humanizer/metricNumerals.ts"
222 |
223 | console.log((1).toMetric())
224 | console.log((1230).toMetric())
225 | console.log((0.1).toMetric())
226 |
227 | //Also the reverse operation using the fromMetric extension.
228 |
229 | console.log("1.23k".fromMetric())
230 | console.log("100m".fromMetric())
231 |
232 |
233 |
234 | // Capture web url
235 | // Make sure the folder MyFolder exists
236 | // May take log time at first run to download chromium.
237 |
238 | import { Capture } from 'https://deno.land/x/deno_shot/mod.ts'
239 |
240 | let res = await Capture({
241 | url: 'https://www.github.com',
242 | image: 'C:/MyFolder/image.png',
243 | maximized: false,
244 | windowSize: {
245 | width: 1000,
246 | height: 890
247 | }
248 | });
249 |
250 | if (res.success) {
251 | console.log(res.image)
252 | }
253 |
254 |
255 |
256 | import { soxa } from 'https://deno.land/x/soxa/mod.ts'
257 |
258 | // Make a request for todos
259 | soxa.get('https://jsonplaceholder.typicode.com/todos/1')
260 | .then(function (response) {
261 | // handle success
262 | console.log(response.data);
263 | })
264 | .catch(function (error) {
265 | // handle error
266 | console.log(error);
267 | })
268 | .finally(function () {
269 | console.log("Done")
270 | });
271 |
272 |
273 |
274 | import { soxa } from 'https://deno.land/x/soxa/mod.ts'
275 |
276 | let body = await soxa.get('https://github.com/denoland/deno/releases/latest');
277 | const regVer = new RegExp(/title\=\"v(.*)?\"/)
278 | let res = regVer.exec(body.data)
279 | //@ts-ignore
280 | console.log("Deno live version: ", res[1])
281 |
282 |
283 |
284 | import * as o from 'https://deno.land/x/cowsay/mod.ts'
285 |
286 | let m = o.say({
287 | text: 'hello every one'
288 | })
289 | console.log(m)
290 |
291 |
292 |
293 | import * as ink from 'https://deno.land/x/ink/mod.ts'
294 |
295 | let text = ink.colorize('Hello World ')
296 | console.log(text)
297 |
298 | //You can use nested style:
299 |
300 | text = ink.colorize('Hello World ')
301 |
302 | console.log(text)
303 |
304 |
305 |
306 | import * as ink from 'https://deno.land/x/ink/mod.ts'
307 |
308 | ink.terminal.log('Hello %s', 'World ')
309 |
310 |
311 |
312 | import * as ink from 'https://deno.land/x/ink/mod.ts'
313 |
314 | let html = ' ' +
315 | '' +
316 | ' Im Red, background Green, underlined and bold!' +
317 | ' ' +
318 | ' My BG is black again, but Im italic :(' +
319 | ' ' +
320 | ' My BG is Green Again!' +
321 | ' ' +
322 | 'No Format here';
323 |
324 | let result = ink.html(html)
325 | console.log(result);
326 |
327 |
328 |
329 |
330 |
331 |
332 | `
333 | export const onBeforeRender = ``
334 | export const onAfterRender = `
335 | inlineScript = function() {
336 | $('.ui.dropdown').dropdown({
337 | action: 'hide',
338 | onChange: function() {
339 | let index = $(arguments[2]).data("index");
340 | let code = $('div[data-example="' + index + '"]').html();
341 | editor.setValue(code);
342 | }
343 | });
344 | let data ='';
345 | term = new Terminal({
346 | cursorBlink: false,
347 | disableStdin: true,
348 | rows: 20
349 | });
350 | term.open(document.getElementById('terminal'));
351 | term.prompt = () => {
352 | term.write('\\r\\ndeno> ');
353 | };
354 | term.writeln('Welcome to Deno Terminal');
355 | term.prompt(term);
356 | }
357 | `
358 |
--------------------------------------------------------------------------------
/src/views/components/dashboard.ts:
--------------------------------------------------------------------------------
1 | export const title = "Dashboard"
2 | export const body = `
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
<%=osInfo.hostname%>
12 |
13 |
14 |
15 |
16 |
17 |
18 |
<%=osInfo.os%>
19 |
20 |
21 |
22 |
23 |
24 |
25 |
<%=osInfo.arch%>
26 |
27 |
28 |
29 |
30 |
31 |
32 |
<%=osInfo.currentPath%>
33 |
34 |
35 |
36 |
37 |
38 |
39 |
<%=osInfo.homeDir%>
40 |
41 |
42 |
43 |
44 |
45 |
46 |
<%=osInfo.denoPath%>
47 |
48 |
49 |
50 |
51 |
52 |
53 |
<%=osInfo.denoVersion%> latest version:
54 | ...
55 |
56 |
57 |
58 |
59 |
60 |
61 |
<%=osInfo.typescriptVersion%>
62 |
63 |
64 |
65 |
66 |
67 |
68 |
<%=osInfo.v8Version%>
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
80 |
81 |
82 | <% envs.forEach(function(env){ %>
83 |
84 |
85 |
86 |
87 |
<%=env.value%>
88 |
89 |
90 | <% }); %>
91 |
92 |
93 |
94 |
95 | `
96 | export const onBeforeRender = ``
97 | export const onAfterRender = `
98 | inlineScript = function() {
99 | axios.get('/api/denolatest/')
100 | .then((res) => {
101 | $('#denolatest').html(res.data)
102 | })
103 | }
104 | `
105 |
--------------------------------------------------------------------------------
/src/views/components/depscaches.ts:
--------------------------------------------------------------------------------
1 | export const title = "Deno Cache"
2 | export const body = `
3 |
4 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
29 |
30 |
Are you sure you want to delete this folder?
31 |
32 |
33 |
34 | No
35 |
36 |
37 | Yes
38 |
39 |
40 |
41 |
42 | `
43 | export const onBeforeRender = ``
44 | export const onAfterRender = `
45 | inlineScript = function() {
46 | $('.ui.dimmer.modals').remove()
47 | function uiPrompt(e) {
48 | let modal= $('.mini.modal')
49 | .modal({
50 | onApprove: () => {
51 | processDelete(e)
52 | },
53 | onDeny: () => {
54 | //console.log('deny')
55 | },
56 | onHide: () => {
57 | //console.log('hide')
58 | }
59 | });
60 | modal.modal('show')
61 | }
62 |
63 | $('button[data-folder]').click((e) => {
64 | uiPrompt(e);
65 | });
66 |
67 | function processDelete(e) {
68 | let folder = $(e.currentTarget).data('folder')
69 | let isfile = $(e.currentTarget).data('isfile')
70 | $(e.currentTarget).addClass('loading')
71 | axios.get('/api/deletefolder/' + folder)
72 | .then((res) => {
73 | if (res.data.success) {
74 | //$('.ui.dimmer.modals').remove();
75 | //renderComponent('depscaches');
76 | //remove the file or folder
77 | $('tr[data-id="' + folder + '"]').remove()
78 | let node = $('#jstree-tree').jstree(true).get_node(folder)
79 | if (!isfile) {
80 | $.jstree.reference("#jstree-tree").delete_node(node);
81 | console.log('reeeeeeeeee')
82 | }
83 | } else {
84 | alert("Error deleting this folder: Error -> " + res.data.error.name)
85 | }
86 | })
87 | .catch((error) => {
88 | alert(error)
89 | })
90 | .finally(() => {
91 | $(e.currentTarget).removeClass('loading')
92 | })
93 | }
94 |
95 |
96 | $('#jstree-tree')
97 | .on('changed.jstree', function (e, data) {
98 | let tmp = '{{#each folders}}' +
99 | '' +
100 | ' {{this.name}} ' +
101 | '{{this.size}} ' +
102 | '' +
103 | ' ' +
104 | ' ' +
105 | ' ' +
106 | ' ' +
107 | ' {{/each}}';
108 |
109 |
110 | let hd = 'Home
'
111 |
112 | let bcTemp = '{{#each items}}' +
113 | ' ' +
114 | '{{this}}
' +
115 | '{{/each}}'
116 |
117 | var objNode = data.instance.get_node(data.selected);
118 | var objPath = data.instance.get_path(data.selected)
119 | axios.get('/api/folders/' + objNode.id)
120 | .then((res) => {
121 | const template = Handlebars.compile(tmp)
122 | let folders = {
123 | folders: res.data
124 | }
125 | let html = template(folders)
126 | $('#explorer-body').html(html)
127 |
128 | const bc = Handlebars.compile(bcTemp)
129 | let bcHtml = bc({items: objPath})
130 | $('#breadcrumb').html(hd + bcHtml)
131 | $('button[data-folder]').click((e) => {
132 | uiPrompt(e);
133 | //alert(1)
134 | });
135 | })
136 | })
137 | .jstree({
138 | core: {
139 | data: {
140 | url: '/api/folders/_root_'
141 | },
142 | check_callback: function() {
143 | return true;
144 | }
145 | },
146 | "plugins" : [ "wholerow" ]
147 | });
148 |
149 | }
150 | `
151 |
--------------------------------------------------------------------------------
/src/views/components/generic.ts:
--------------------------------------------------------------------------------
1 | export const title = "generic_title"
2 | export const body = `body_<%=id%>`
3 | export const onBeforeRender = `before_script`
4 | export const onAfterRender = `after_script`
5 |
--------------------------------------------------------------------------------
/src/views/components/stop.ts:
--------------------------------------------------------------------------------
1 | export const title = "Stop Deno GUI"
2 | export const body = `
3 |
11 |
12 |
13 |
14 | Stop Deno GUI
15 |
16 |
17 | `
18 | export const onBeforeRender = ``
19 | export const onAfterRender = `
20 | inlineScript = function() {
21 | $("#btn-stop").click((e) => {
22 | e.preventDefault();
23 | $("#btn-stop").addClass("loading");
24 | axios.get('/api/stop')
25 | .then((res) => {
26 |
27 | })
28 | .catch((error) => {
29 | })
30 | .finally(() => {
31 | $('#dim').dimmer({opacity: 0.5, closable: false}).dimmer('show');
32 | })
33 | })
34 | }
35 | `
36 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rulesDirectory": [ ],
3 | "rules": {
4 | "arrow-return-shorthand": true,
5 | "callable-types": true,
6 | "class-name": true,
7 | "comment-format": [
8 | true,
9 | "check-space"
10 | ],
11 | "curly": true,
12 | "eofline": true,
13 | "forin": true,
14 | "import-blacklist": [
15 | true,
16 | "rxjs"
17 | ],
18 | "import-spacing": true,
19 | "indent": [
20 | true,
21 | "spaces"
22 | ],
23 | "interface-over-type-literal": true,
24 | "label-position": true,
25 | "max-line-length": [
26 | true,
27 | 140
28 | ],
29 | "member-access": false,
30 | "no-arg": true,
31 | "no-bitwise": true,
32 | "no-console": [
33 | true,
34 | "debug",
35 | "info",
36 | "time",
37 | "timeEnd",
38 | "trace"
39 | ],
40 | "no-construct": true,
41 | "no-debugger": true,
42 | "no-duplicate-super": true,
43 | "no-empty": false,
44 | "no-empty-interface": true,
45 | "no-eval": true,
46 | "no-inferrable-types": [
47 | true,
48 | "ignore-params"
49 | ],
50 | "no-misused-new": true,
51 | "no-non-null-assertion": true,
52 | "no-shadowed-variable": true,
53 | "no-string-literal": false,
54 | "no-string-throw": true,
55 | "no-switch-case-fall-through": true,
56 | "no-trailing-whitespace": false,
57 | "no-unnecessary-initializer": true,
58 | "no-unused-expression": true,
59 | "no-var-keyword": true,
60 | "object-literal-sort-keys": false,
61 | "one-line": [
62 | true,
63 | "check-open-brace",
64 | "check-catch",
65 | "check-else",
66 | "check-whitespace"
67 | ],
68 | "prefer-const": true,
69 | "quotemark": [
70 | true,
71 | "double"
72 | ],
73 | "radix": true,
74 | "semicolon": [
75 | "always"
76 | ],
77 | "triple-equals": [
78 | true,
79 | "allow-null-check"
80 | ],
81 | "typedef-whitespace": [
82 | true,
83 | {
84 | "call-signature": "nospace",
85 | "index-signature": "nospace",
86 | "parameter": "nospace",
87 | "property-declaration": "nospace",
88 | "variable-declaration": "nospace"
89 | }
90 | ],
91 | "unified-signatures": true,
92 | "variable-name": false,
93 | "whitespace": [
94 | true,
95 | "check-branch",
96 | "check-decl",
97 | "check-operator",
98 | "check-separator",
99 | "check-type"
100 | ]
101 | }
102 | }
--------------------------------------------------------------------------------