pywebexec 1.7.10__py3-none-any.whl → 1.7.12__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -36,17 +36,6 @@ th {
36
36
  .outcol {
37
37
  width: 100%;
38
38
  }
39
- select { /* Safari bug */
40
- -webkit-appearance: none;
41
- -webkit-border-radius: none;
42
- appearance: none;
43
- outline: none;
44
- font-size: 15px;
45
- border: #aaa solid 1px;
46
- border-radius: 5px;
47
- padding: 0px 5px 5px 0px;
48
- min-width: 150px;
49
- }
50
39
  .output {
51
40
  background: #111;
52
41
  padding: 10px;
@@ -74,13 +63,14 @@ button {
74
63
  -webkit-border-radius: none;
75
64
  appearance: none;
76
65
  border-radius: 15px;
77
- padding-right: 13px;
66
+ padding: 0px 13px;
78
67
  border: 1px #555 solid;
79
68
  height: 22px;
80
69
  font-size: 13px;
81
70
  outline: none;
82
- text-indent: 10px;
83
71
  background-color: #eee;
72
+ color: #000;
73
+ font-weight: normal;
84
74
  }
85
75
  form {
86
76
  padding-bottom: 15px;
@@ -138,7 +128,7 @@ form {
138
128
  .copy_clip_ok, .copy_clip_ok:hover {
139
129
  background-image: url("/static/images/copy_ok.svg");
140
130
  }
141
- #params, #commandName {
131
+ #params, #command {
142
132
  -webkit-appearance: none;
143
133
  -webkit-border-radius: none;
144
134
  appearance: none;
@@ -152,7 +142,7 @@ form {
152
142
  margin: 0; /* Remove margin */
153
143
  }
154
144
 
155
- #commandName {
145
+ #command {
156
146
  width: auto; /* Allow dynamic width */
157
147
  background-size: 16px 16px;
158
148
  border-radius: 15px 0px 0px 15px;
@@ -211,15 +201,18 @@ form {
211
201
  margin-top: 2px;
212
202
  overflow-y: auto;
213
203
  z-index: 1000;
204
+ max-height: 200px;
214
205
  }
215
206
 
216
207
  .command-item {
217
- padding: 3px 5px 3px 5px;
208
+ padding: 1px 5px 1px 5px;
209
+ margin-top: 1px;
218
210
  cursor: pointer;
211
+ outline: none; /* Remove default focus border */
219
212
  }
220
213
 
221
- .command-item:hover, .command-item.highlighted {
222
- background-color: #eee;
214
+ .command-item:hover, .command-item.highlighted, .command-item:focus {
215
+ background-color: #a7d0ff;
223
216
  }
224
217
 
225
218
  .currentcommand {
@@ -300,17 +293,9 @@ span {
300
293
  }
301
294
  .font-increase {
302
295
  background-image: url("/static/images/font-increase.svg");
303
- /*background-size: contain;*/
304
- background-repeat: no-repeat;
305
- background-position: center;
306
- background-size: 14px 14px;
307
296
  }
308
297
  .font-decrease {
309
298
  background-image: url("/static/images/font-decrease.svg");
310
- /*background-size: contain;*/
311
- background-repeat: no-repeat;
312
- background-position: center;
313
- background-size: 14px 14px;
314
299
  }
315
300
  .font-size-button {
316
301
  background-color: #444;
@@ -321,6 +306,9 @@ span {
321
306
  font-size: 14px;
322
307
  width: 20px;
323
308
  height: 20px;
309
+ background-repeat: no-repeat;
310
+ background-position: center;
311
+ background-size: 14px 14px;
324
312
  }
325
313
  .font-size-button:hover {
326
314
  background-color: #666;
@@ -1,47 +1,46 @@
1
1
  // commands.js
2
- let commandInput = document.getElementById('commandName');
2
+ let commandInput = document.getElementById('command');
3
3
  let paramsInput = document.getElementById('params');
4
- let commandListSelect = document.getElementById('commandList');
4
+ let commandListDiv = document.getElementById('commandList');
5
5
  let showCommandListButton = document.getElementById('showCommandListButton');
6
6
  let isHandlingKeydown = false;
7
7
  let firstVisibleItem = 0;
8
8
 
9
9
  function unfilterCommands() {
10
- const options = commandListSelect.options;
11
- for (let i = 0; i < options.length; i++) {
12
- options[i].style.display = 'block';
10
+ const items = commandListDiv.children;
11
+ for (let i = 0; i < items.length; i++) {
12
+ items[i].style.display = 'block';
13
13
  }
14
- commandListSelect.size = Math.min(20, commandListSelect.options.length);
14
+ commandListDiv.style.display = 'block';
15
15
  }
16
16
 
17
17
  function filterCommands() {
18
18
  const value = commandInput.value.slice(0, commandInput.selectionStart);
19
- const options = commandListSelect.options;
19
+ const items = commandListDiv.children;
20
20
  let nbVisibleItems = 0;
21
21
  firstVisibleItem = -1;
22
- for (let i = 0; i < options.length; i++) {
23
- if (options[i].text.startsWith(value)) {
24
- options[i].style.display = 'block';
22
+ for (let i = 0; i < items.length; i++) {
23
+ if (items[i].textContent.startsWith(value)) {
24
+ items[i].style.display = 'block';
25
25
  nbVisibleItems += 1;
26
26
  if (firstVisibleItem === -1) {
27
27
  firstVisibleItem = i;
28
28
  }
29
29
  } else {
30
- options[i].style.display = 'none';
30
+ items[i].style.display = 'none';
31
31
  }
32
32
  }
33
33
  if (nbVisibleItems > 1) {
34
- commandListSelect.size = Math.min(20, nbVisibleItems);
35
- commandListSelect.style.display = 'block';
34
+ commandListDiv.style.display = 'block';
36
35
  } else {
37
- commandListSelect.style.display = 'none';
36
+ commandListDiv.style.display = 'none';
38
37
  }
39
38
  }
40
39
 
41
40
  function setCommandListPosition() {
42
41
  const rect = commandInput.getBoundingClientRect();
43
- commandListSelect.style.left = `${rect.left}px`;
44
- commandListSelect.style.top = `${rect.bottom}px`;
42
+ commandListDiv.style.left = `${rect.left}px`;
43
+ commandListDiv.style.top = `${rect.bottom}px`;
45
44
  }
46
45
 
47
46
  function adjustInputWidth(input) {
@@ -49,7 +48,6 @@ function adjustInputWidth(input) {
49
48
  input.style.width = `${input.scrollWidth}px`;
50
49
  }
51
50
 
52
-
53
51
  paramsInput.addEventListener('input', () => adjustInputWidth(paramsInput));
54
52
  commandInput.addEventListener('input', () => {
55
53
  adjustInputWidth(commandInput);
@@ -73,12 +71,12 @@ commandInput.addEventListener('input', (event) => {
73
71
  commandInput.setSelectionRange(newValue.length, newValue.length);
74
72
  }
75
73
  const value = commandInput.value;
76
- const options = commandListSelect.options;
74
+ const options = commandListDiv.children;
77
75
  if (value) {
78
- const match = Array.from(options).find(option => option.text.startsWith(value));
76
+ const match = Array.from(options).find(option => option.textContent.startsWith(value));
79
77
  if (match) {
80
- commandInput.value = match.text;
81
- commandInput.setSelectionRange(value.length, match.text.length);
78
+ commandInput.value = match.textContent;
79
+ commandInput.setSelectionRange(value.length, match.textContent.length);
82
80
  } else {
83
81
  commandInput.value = value.slice(0, -1);
84
82
  }
@@ -88,17 +86,15 @@ commandInput.addEventListener('input', (event) => {
88
86
  });
89
87
 
90
88
  commandInput.addEventListener('keydown', (event) => {
91
- if (event.key === ' ' || event.key === 'ArrowRight') {
89
+ if (event.key === ' ' || event.key === 'ArrowRight' || event.key === 'Tab') {
92
90
  event.preventDefault();
93
91
  paramsInput.focus();
94
92
  paramsInput.setSelectionRange(0, paramsInput.value.length);
93
+ commandListDiv.style.display = 'none'
95
94
  } else if (event.key === 'ArrowDown') {
96
- if (commandListSelect.options.length > 1) {
97
- commandListSelect.style.display = 'block';
98
- commandListSelect.selectedIndex = firstVisibleItem;
99
- commandListSelect.focus();
100
- commandListSelect.options[firstVisibleItem].scrollIntoView();
101
- commandListSelect.options[firstVisibleItem].focus();
95
+ if (commandListDiv.children.length > 1) {
96
+ commandListDiv.style.display = 'block';
97
+ commandListDiv.children[firstVisibleItem].focus();
102
98
  }
103
99
  event.preventDefault();
104
100
  }
@@ -121,47 +117,65 @@ paramsInput.addEventListener('keydown', (event) => {
121
117
  }
122
118
  });
123
119
 
124
- commandListSelect.addEventListener('keydown', (event) => {
125
- if (event.key === 'Enter') {
126
- event.preventDefault(); // Prevent form submission
127
- const selectedOption = commandListSelect.options[commandListSelect.selectedIndex];
128
- commandInput.value = selectedOption.text;
129
- commandListSelect.style.display = 'none';
130
- adjustInputWidth(commandInput);
131
- paramsInput.focus();
132
- return;
133
- }
134
- if (event.key === 'ArrowUp' && commandListSelect.selectedIndex == 0) {
120
+ commandListDiv.addEventListener('keydown', (event) => {
121
+ const items = Array.from(commandListDiv.children);
122
+ const currentIndex = items.indexOf(document.activeElement);
123
+
124
+ if (event.key === 'Escape') {
135
125
  commandInput.focus();
136
- commandListSelect.style.display = 'none'
126
+ commandListDiv.style.display = 'none';
127
+ }else if (event.key === 'ArrowDown') {
128
+ event.preventDefault();
129
+ const nextIndex = (currentIndex + 1) % items.length;
130
+ items[nextIndex].focus();
131
+ } else if (event.key === 'ArrowUp') {
132
+ event.preventDefault();
133
+ if (currentIndex === 0 || items[currentIndex-1].style.display == 'none') {
134
+ commandInput.focus();
135
+ commandListDiv.style.display = 'none';
136
+ } else {
137
+ const prevIndex = (currentIndex - 1 + items.length) % items.length;
138
+ items[prevIndex].focus();
139
+ }
140
+ } else if (event.key === 'Enter' || event.key === 'Tab' || event.key === ' ') {
141
+ event.preventDefault(); // Prevent form submission
142
+ const selectedOption = document.activeElement;
143
+ if (selectedOption.classList.contains('command-item')) {
144
+ commandInput.value = selectedOption.textContent;
145
+ commandListDiv.style.display = 'none';
146
+ adjustInputWidth(commandInput);
147
+ paramsInput.focus();
148
+ }
137
149
  }
138
150
  });
139
151
 
140
- commandListSelect.addEventListener('click', (event) => {
152
+ commandListDiv.addEventListener('click', (event) => {
141
153
  event.preventDefault(); // Prevent form submission
142
- const selectedOption = commandListSelect.options[commandListSelect.selectedIndex];
143
- commandInput.value = selectedOption.text;
144
- commandListSelect.style.display = 'none';
145
- adjustInputWidth(commandInput);
146
- paramsInput.focus();
154
+ const selectedOption = event.target;
155
+ if (selectedOption.classList.contains('command-item')) {
156
+ commandInput.value = selectedOption.textContent;
157
+ commandListDiv.style.display = 'none';
158
+ adjustInputWidth(commandInput);
159
+ paramsInput.focus();
160
+ }
147
161
  });
148
162
 
149
163
 
150
164
  commandInput.addEventListener('click', () => {
151
165
  setCommandListPosition();
152
- if (commandListSelect.style.display == 'none')
153
- commandListSelect.style.display = 'block';
166
+ if (commandListDiv.style.display == 'none')
167
+ commandListDiv.style.display = 'block';
154
168
  else
155
- commandListSelect.style.display = 'none';
169
+ commandListDiv.style.display = 'none';
156
170
  filterCommands();
157
171
  });
158
172
 
159
173
  commandInput.addEventListener('blur', (event) => {
160
- if (event.relatedTarget === showCommandListButton || event.relatedTarget === commandListSelect) {
174
+ if (event.relatedTarget === showCommandListButton || event.relatedTarget === commandListDiv || event.relatedTarget.classList.includes('command-item')) {
161
175
  event.preventDefault();
162
176
  return;
163
177
  }
164
- commandListSelect.style.display = 'none';
178
+ commandListDiv.style.display = 'none';
165
179
  adjustInputWidth(commandInput);
166
180
  });
167
181
 
@@ -169,20 +183,16 @@ showCommandListButton.addEventListener('click', (event) => {
169
183
  event.preventDefault();
170
184
  setCommandListPosition();
171
185
  unfilterCommands();
172
- if (commandListSelect.style.display == 'none')
173
- commandListSelect.style.display = 'block';
174
- else
175
- commandListSelect.style.display = 'none';
176
186
  });
177
187
 
178
188
  window.addEventListener('click', (event) => {
179
- if (!commandInput.contains(event.target) && !commandListSelect.contains(event.target) && !showCommandListButton.contains(event.target)) {
180
- commandListSelect.style.display = 'none';
189
+ if (!commandInput.contains(event.target) && !commandListDiv.contains(event.target) && !showCommandListButton.contains(event.target)) {
190
+ commandListDiv.style.display = 'none';
181
191
  }
182
192
  });
183
193
 
184
194
  window.addEventListener('keydown', (event) => {
185
- if ([commandInput, paramsInput, commandListSelect].includes(document.activeElement)) return;
195
+ if ([commandInput, paramsInput, commandListDiv].includes(document.activeElement)) return;
186
196
  if (event.code === `Key${event.key.toUpperCase()}`) {
187
197
  commandInput.focus();
188
198
  commandInput.dispatchEvent(new KeyboardEvent('keydown', event));
@@ -207,22 +217,22 @@ async function fetchExecutables() {
207
217
  throw new Error('Failed to fetch command status');
208
218
  }
209
219
  const executables = await response.json();
210
- commandListSelect.innerHTML = '';
220
+ commandListDiv.innerHTML = '';
211
221
  executables.forEach(executable => {
212
- const option = document.createElement('option');
213
- option.className = 'command-item';
214
- option.text = executable;
215
- commandListSelect.appendChild(option);
222
+ const div = document.createElement('div');
223
+ div.className = 'command-item';
224
+ div.textContent = executable;
225
+ div.tabIndex = 0; // Make the div focusable
226
+ commandListDiv.appendChild(div);
216
227
  });
217
228
  } catch (error) {
218
229
  alert("Failed to fetch executables");
219
230
  }
220
- commandListSelect.size = Math.min(20, commandListSelect.options.length);
221
- if (commandListSelect.options.length == 1) {
222
- commandInput.value = commandListSelect.options[0].text;
231
+ if (commandListDiv.children.length == 1) {
232
+ commandInput.value = commandListDiv.children[0].textContent;
223
233
  showCommandListButton.style.display = 'none';
224
234
  }
225
- if (commandListSelect.options.length == 0)
235
+ if (commandListDiv.children.length == 0)
226
236
  document.getElementById('launchForm').style.display = 'none';
227
237
 
228
238
  }
@@ -126,8 +126,8 @@ const urlToken = getTokenParam();
126
126
 
127
127
  document.getElementById('launchForm').addEventListener('submit', async (event) => {
128
128
  event.preventDefault();
129
- const commandName = document.getElementById('commandName').value;
130
- const params = document.getElementById('params').value.split(' ');
129
+ const commandName = commandInput.value;
130
+ const params = paramsInput.value.split(' ');
131
131
  fitAddon.fit();
132
132
  terminal.clear();
133
133
  try {
@@ -13,13 +13,13 @@
13
13
  </div>
14
14
  <h2><span class="status-icon title-icon"></span>{{ title }}</h2>
15
15
  <form id="launchForm" class="form-inline">
16
- <label for="commandName">Command</label>
16
+ <label for="command">Command</label>
17
17
  <div class="input-group">
18
- <input type="text" id="commandName" name="commandName" size=5 autocomplete="off" style="width: 100px;" autofocus>
18
+ <input type="text" id="command" name="command" size=5 autocomplete="off" style="width: 100px;" autofocus>
19
19
  <div id="showCommandListButton" class="show-command-list-button">
20
20
  <span class="arrow">&#9660;</span>
21
21
  </div>
22
- <select id="commandList" class="command-list" size="20"></select>
22
+ <div id="commandList" class="command-list"></div>
23
23
  <input type="text" id="params" name="params" oninput="this.style.width = ((this.value.length + 1) * 8) + 'px';">
24
24
  </div>
25
25
  <button type="submit">Run</button>
pywebexec/version.py CHANGED
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '1.7.10'
16
- __version_tuple__ = version_tuple = (1, 7, 10)
15
+ __version__ = version = '1.7.12'
16
+ __version_tuple__ = version_tuple = (1, 7, 12)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pywebexec
3
- Version: 1.7.10
3
+ Version: 1.7.12
4
4
  Summary: Simple Python HTTP Exec Server
5
5
  Home-page: https://github.com/joknarf/pywebexec
6
6
  Author: Franck Jouvanceau
@@ -1,8 +1,8 @@
1
1
  pywebexec/__init__.py,sha256=4spIsVaF8RJt8S58AG_wWoORRNkws9Iwqprj27C3ljM,99
2
2
  pywebexec/pywebexec.py,sha256=MmpHK2SscvIPj1gmV9AcJXYfeaL-at5BDgLhKIxzZBc,33604
3
- pywebexec/version.py,sha256=BcMHo4x9krobfBaTHQOg-i0s8jUuLIhj-_tcl9epPPg,413
3
+ pywebexec/version.py,sha256=dSwjHj4iLBCyQl7aZEEt5q3jGDuArBY7LwcMyXcjaUg,413
4
4
  pywebexec/static/css/Consolas NF.ttf,sha256=DJEOzF0eqZ-kxu3Gs_VE8X0NJqiobBzmxWDGpdgGRxI,1313900
5
- pywebexec/static/css/style.css,sha256=3s7QgbCh4wb7kfZ7Pjo-B6o3lDIBogZ-3j6AfaPdpzU,8209
5
+ pywebexec/static/css/style.css,sha256=6Q89tdXTzuGaMJJ26gp-YD2L0eIsFb7C83IYOoMJb8g,7915
6
6
  pywebexec/static/css/xterm.css,sha256=uo5phWaUiJgcz0DAzv46uoByLLbJLeetYosL1xf68rY,5559
7
7
  pywebexec/static/images/aborted.svg,sha256=2nuvSwGBIZGWtlM1DrBO3qiSq1reDbcZDAj9rJXBnjY,380
8
8
  pywebexec/static/images/copy.svg,sha256=d9OwtGh5GzzZHzYcDrLfNxZYLth1Q64x7bRyYxu4Px0,622
@@ -20,9 +20,9 @@ pywebexec/static/images/popup.svg,sha256=0Bl9A_v5cBsMPn6FnOlVWlAQKgd2zqiWQbhjcL9
20
20
  pywebexec/static/images/resume.svg,sha256=99LP1Ya2JXakRCO9kW8JMuT_4a_CannF65EiuwtvK4A,607
21
21
  pywebexec/static/images/running.svg,sha256=fBCYwYb2O9K4N3waC2nURP25NRwZlqR4PbDZy6JQMww,610
22
22
  pywebexec/static/images/success.svg,sha256=NVwezvVMplt46ElW798vqGfrL21Mw_DWHUp_qiD_FU8,489
23
- pywebexec/static/js/commands.js,sha256=h2fkd9qpypLBxvhEEbay23nwuqUwcKJA0vHugcyL8pU,7961
23
+ pywebexec/static/js/commands.js,sha256=1g771zk-EV1H7vKGWZSrTK_avWF6pBgdIy860hodxiw,8332
24
24
  pywebexec/static/js/popup.js,sha256=_2GzUizJ-sdZFWG7SZwbYJTPbu4EvVq7D5Q_UE8nepA,9452
25
- pywebexec/static/js/script.js,sha256=VUrypyN39pawdT-uEQqvgve0nQuGZrQ5Q5L3WDOk9Vk,18530
25
+ pywebexec/static/js/script.js,sha256=bmaR9TJhZMEK_Niz0TCp8CJdnLKh4ayaxLvqgjxdoRs,18482
26
26
  pywebexec/static/js/xterm/LICENSE,sha256=EU1P4eXTull-_T9I80VuwnJXubB-zLzUl3xpEYj2T1M,1083
27
27
  pywebexec/static/js/xterm/addon-canvas.js,sha256=ez6QTVvsmLVNJmdJlM-ZQ5bErwlxAQ_9DUmDIptl2TM,94607
28
28
  pywebexec/static/js/xterm/addon-canvas.js.map,sha256=ECBA4B-BqUpdFeRzlsEWLSQnudnhLP-yPQJ8_hKquMo,379537
@@ -33,11 +33,11 @@ pywebexec/static/js/xterm/addon-unicode11.js.map,sha256=paDj5KKtTIUGedQn2x7CaUTD
33
33
  pywebexec/static/js/xterm/xterm.js,sha256=H5kaw7Syg-v5bmCuI6AKUnZd06Lkb6b92p8aqwMvdJU,289441
34
34
  pywebexec/static/js/xterm/xterm.js.map,sha256=Y7O2Pb-fIS7Z8AC1D5s04_aiW_Jf1f4mCfN0U_OI6Zw,1118392
35
35
  pywebexec/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
- pywebexec/templates/index.html,sha256=CcLN3v_42lnj4juiTntDTiGHJ8-zQnmB9oqpSK_0kks,2981
36
+ pywebexec/templates/index.html,sha256=KSdQYBdzWKP6v0ETZsMO_729aosGBAzJxAss8T5jCto,2953
37
37
  pywebexec/templates/popup.html,sha256=f5m4u8WKpkevL2mQamGqo4_y-rSuLOXGuNsezuUbniY,1508
38
- pywebexec-1.7.10.dist-info/LICENSE,sha256=gRJf0JPT_wsZJsUGlWPTS8Vypfl9vQ1qjp6sNbKykuA,1064
39
- pywebexec-1.7.10.dist-info/METADATA,sha256=C22AhjECWjwwIzMYNlksxKgkEiMHunck34lwNK0adXM,8149
40
- pywebexec-1.7.10.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
41
- pywebexec-1.7.10.dist-info/entry_points.txt,sha256=l52GBkPCXRkmlHfEyoVauyfBdg8o-CAtC8qQpOIjJK0,55
42
- pywebexec-1.7.10.dist-info/top_level.txt,sha256=vHoHyzngrfGdm_nM7Xn_5iLmaCrf10XO1EhldgNLEQ8,10
43
- pywebexec-1.7.10.dist-info/RECORD,,
38
+ pywebexec-1.7.12.dist-info/LICENSE,sha256=gRJf0JPT_wsZJsUGlWPTS8Vypfl9vQ1qjp6sNbKykuA,1064
39
+ pywebexec-1.7.12.dist-info/METADATA,sha256=9LbZYl-e-jOLwTE48iI17WHMvnd1ukT7zMcL2Z8QLSE,8149
40
+ pywebexec-1.7.12.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
41
+ pywebexec-1.7.12.dist-info/entry_points.txt,sha256=l52GBkPCXRkmlHfEyoVauyfBdg8o-CAtC8qQpOIjJK0,55
42
+ pywebexec-1.7.12.dist-info/top_level.txt,sha256=vHoHyzngrfGdm_nM7Xn_5iLmaCrf10XO1EhldgNLEQ8,10
43
+ pywebexec-1.7.12.dist-info/RECORD,,