-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtemplate.html
174 lines (172 loc) · 7.93 KB
/
template.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/gh/highlightjs/[email protected]/build/styles/atom-one-dark.min.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/[email protected]/dist/quill.snow.css">
<script src="//cdn.jsdelivr.net/npm/[email protected]/dist/jquery.slim.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"></script>
<script src="//cdn.jsdelivr.net/gh/highlightjs/[email protected]/build/highlight.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/[email protected]/dist/quill.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/[email protected]/moment.min.js"></script>
<style>
.btn-link {
color: lightblue;
}
.btn-link:hover {
color: lightgray;
}
.ql-editor {
padding: 0;
}
.ql-snow .ql-editor pre.ql-syntax {
margin: 0;
background-color: black;
font-size: 14px;
}
.row {
margin-left: 0px;
margin-right: 0px;
}
.hljs {
background-color: transparent;
}
</style>
<script type="text/javascript">
let quill = null
function onload() {
const textarea = document.getElementById('script')
const editor = document.getElementById('editor')
const form = document.getElementById('form')
const inputList = <%=JSON.stringify(_.map(_.filter(repl.getLogs(), ({ type }) => type === 'input'), 'content'))%>
let inputListCursor = inputList.length
let cacheText = ''
editor.addEventListener('keydown', function(e) {
// console.log('keydown', e)
if(e.ctrlKey && e.keyCode === 13) { // ctrl + enter
quill.disable()
form.script.value = quill.getText()
form.logScript.value = ''
form.wait.value = '0'
form.submit()
e.preventDefault()
} else if(e.altKey && e.keyCode === 13) { // alt + enter
quill.disable()
form.logScript.value = quill.getText().trim()
form.wait.value = '50'
const callback = '(err, stdout, stderr) => { if (err) { throw err } else { if (stderr) console.log(String(stderr)); if (stdout) console.log(String(stdout)) }}'
form.script.value = form.logScript.value ? 'child_process.exec(' + JSON.stringify(form.logScript.value) + ', ' + callback + '), undefined' : ''
form.submit()
e.preventDefault()
} else if (e.ctrlKey && e.keyCode === 38) { // ctrl + up
if (inputListCursor === inputList.length) {
cacheText = quill.getText()
}
inputListCursor = Math.max(0, inputListCursor - 1)
const insert = inputList[inputListCursor]
quill.setContents([{ insert, attributes: { 'code-block': true } } ])
} else if (e.ctrlKey && e.keyCode === 40) { // ctrl + down
inputListCursor = Math.min(inputListCursor + 1, inputList.length)
const insert = inputListCursor === inputList.length ? cacheText : inputList[inputListCursor]
quill.setContents([{ insert, attributes: { 'code-block': true } }])
} else if (e.keyCode === 13) {
// todo indent
}
})
editor.addEventListener('input', function(e) {
inputListCursor = inputList.length
})
quill = new Quill('#editor', {
modules: { syntax: true, toolbar: false },
theme: 'snow'
})
quill.setContents([{ insert: '\n', attributes: { 'code-block': true } }])
quill.focus()
document.querySelectorAll('.timestamp').forEach((e) => {
e.innerText = moment(Number(e.innerText)).format('HH:mm:ss')
})
}
hljs.initHighlightingOnLoad()
</script>
</head>
<body onload="onload()">
<div class="row" style="background-color: darkslateblue;">
<a href="#" class="btn btn-link" data-toggle="modal" data-target="#NodeModulesModal">
<svg class="bi bi-terminal" width="1.5em" height="1.5em" viewBox="0 0 20 20" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M16 4H4a1 1 0 00-1 1v10a1 1 0 001 1h12a1 1 0 001-1V5a1 1 0 00-1-1zM4 3a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V5a2 2 0 00-2-2H4z" clip-rule="evenodd"></path>
<path fill-rule="evenodd" d="M8 11a.5.5 0 01.5-.5h3a.5.5 0 010 1h-3A.5.5 0 018 11zM5.146 6.146a.5.5 0 01.708 0l2 2a.5.5 0 010 .708l-2 2a.5.5 0 01-.708-.708L6.793 8.5 5.146 6.854a.5.5 0 010-.708z" clip-rule="evenodd"></path>
</svg>
</a>
<!-- NodeModules Modal -->
<div class="modal fade" id="NodeModulesModal" tabindex="-1" role="dialog" aria-labelledby="NodeModulesModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="NodeModulesModalLabel">Node Modules of <%=repl.packageJson.name%></h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p><%=_.isEmpty(repl.packageJson.dependencies) ? 'No dependencies' : ''%></p>
<% _.forEach(repl.packageJson.dependencies, (v, k) => {%>
<p><%=[k, v].join('@')%></p>
<%})%>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">OK</button>
</div>
</div>
</div>
</div>
<span style="margin: 8px auto; color: lightblue;">💻️ NodeJS REPL</span>
<a href="#" class="btn btn-link" data-toggle="modal" data-target="#helpModal">
<svg class="bi bi-question-square" width="1.5em" height="1.5em" viewBox="0 0 20 20" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M16 3H4a1 1 0 00-1 1v12a1 1 0 001 1h12a1 1 0 001-1V4a1 1 0 00-1-1zM4 2a2 2 0 00-2 2v12a2 2 0 002 2h12a2 2 0 002-2V4a2 2 0 00-2-2H4z" clip-rule="evenodd"></path>
<path d="M7.25 8.033h1.32c0-.781.458-1.384 1.36-1.384.685 0 1.313.343 1.313 1.168 0 .635-.374.927-.965 1.371-.673.489-1.206 1.06-1.168 1.987l.007.463h1.307v-.355c0-.718.273-.927 1.01-1.486.609-.463 1.244-.977 1.244-2.056 0-1.511-1.276-2.241-2.673-2.241-1.326 0-2.786.647-2.754 2.533zm1.562 5.516c0 .533.425.927 1.01.927.609 0 1.028-.394 1.028-.927 0-.552-.42-.94-1.029-.94-.584 0-1.009.388-1.009.94z"></path>
</svg>
</a>
<!-- Help Modal -->
<div class="modal fade" id="helpModal" tabindex="-1" role="dialog" aria-labelledby="helpModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="helpModalLabel">Help</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p><kbd>Ctrl</kbd>+<kbd>Enter</kbd> to submit the script to node repl. Submit empty to refresh the page.</p>
<p><kbd>Alt</kbd>+<kbd>Enter</kbd> to submit the script to shell</p>
<p><kbd>Ctrl</kbd>+<kbd>Up/Down</kbd> to browse input history.</p>
<p>.clear: Clear the logs of the current session.</p>
<p>.exit: Remove and exit the current session.</p>
<p>require('pck@version'): Package will be automatically installed when requires.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">OK</button>
</div>
</div>
</div>
</div>
</div>
<form action="" method="POST" class="form" id="form" style="background-color: black; min-height: 100px;">
<% _.forEach(repl.getLogs(), ({ timestamp, content, type }) => {%>
<div class="row">
<div class="col-1">
<pre style="margin: 5px"><div class="timestamp" style="color: lightgrey; padding: .5em;"><%=timestamp%></div></pre>
</div>
<div class="col-11">
<pre style="margin: 5px"><code class="javascript"><%=_.escape(content)%></code></pre>
</div>
</div>
<%})%>
<textarea id="script" name="script" hidden></textarea>
<input type="text" name="logScript" hidden />
<input type="text" name="wait" hidden />
</form>
<div id="editor"></div>
</body>
</html>