pythononlinegcc commited on
Commit
1df87ad
·
verified ·
1 Parent(s): 89e328e

Upload index2.html

Browse files
Files changed (1) hide show
  1. templates/index2.html +262 -0
templates/index2.html ADDED
@@ -0,0 +1,262 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="ru">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Online Python - IDE, Editor, Compiler, Interpreter</title>
7
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/codemirror.min.css">
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
9
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.0/dist/katex.min.css">
10
+ <script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.0/dist/katex.min.js"></script>
11
+ <script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.0/dist/contrib/auto-render.min.js"></script>
12
+ <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
13
+
14
+ <style>
15
+ .output-body {
16
+ line-height: 1.6;
17
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
18
+ color: #2c3e50;
19
+ }
20
+ .output-body h1, .output-body h2, .output-body h3 { color: #007bff; margin-top: 20px; }
21
+ .output-body code { background: #f0f0f0; padding: 2px 4px; border-radius: 4px; font-family: monospace; }
22
+ .katex-display {
23
+ padding: 10px 0;
24
+ margin: 10px 0;
25
+ overflow-x: auto;
26
+ overflow-y: hidden;
27
+ }
28
+ hr.process-divider {
29
+ border: 0;
30
+ border-top: 2px solid #eaedf1;
31
+ margin: 20px 0 10px 0;
32
+ }
33
+ </style>
34
+ <style>
35
+ :root {
36
+ --blue-primary: #007bff;
37
+ --blue-hover: #0056b3;
38
+ --green-primary: #28a745;
39
+ --green-hover: #218838;
40
+ --gray-bg: #f8f9fa;
41
+ --gray-border: #dee2e6;
42
+ --text-dark: #343a40;
43
+ --text-muted: #6c757d;
44
+ }
45
+
46
+ body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; margin: 0; background-color: var(--gray-bg); color: var(--text-dark); display: flex; flex-direction: column; height: 100vh; overflow: hidden; }
47
+
48
+ .header { background-color: var(--blue-primary); color: white; display: flex; justify-content: space-between; align-items: center; padding: 10px 15px; border-bottom: 1px solid rgba(0,0,0,.1); }
49
+ .header-left { display: flex; align-items: center; gap: 10px; font-weight: bold; font-size: 1.1em; }
50
+ .header-left img { height: 24px; }
51
+ .header-right { display: flex; align-items: center; gap: 10px; }
52
+ .btn-learn { background-color: white; color: var(--blue-primary); border: 1px solid white; padding: 6px 12px; font-size: 0.9em; font-weight: bold; border-radius: 4px; cursor: pointer; text-decoration: none; }
53
+ .btn-learn:hover { background-color: #f1f1f1; }
54
+ .btn-try-new { background-color: var(--green-primary); color: white; border: none; padding: 6px 12px; font-size: 0.9em; font-weight: bold; border-radius: 4px; cursor: pointer; text-decoration: none; display: flex; align-items: center; gap: 5px; }
55
+ .btn-try-new:hover { background-color: var(--green-hover); }
56
+
57
+ .toolbar-wrapper { display: flex; flex-direction: column; background: #eaedf1; border-bottom: 1px solid var(--gray-border); }
58
+ .file-tabs { display: flex; align-items: center; background: #e2e6ea; padding: 5px 10px 0 10px; border-bottom: 1px solid var(--gray-border); }
59
+ .file-tab { padding: 8px 15px; background: white; border: 1px solid var(--gray-border); border-bottom: 1px solid white; border-radius: 4px 4px 0 0; font-family: monospace; font-size: 0.9em; cursor: pointer; margin-right: 5px; position: relative; bottom: -1px; }
60
+ .btn-add-file { color: var(--text-muted); padding: 5px; cursor: pointer; }
61
+
62
+ .toolbar-core { display: flex; justify-content: space-between; align-items: center; padding: 8px 15px; background-color: #f1f3f5; border-bottom: 1px solid var(--gray-border); }
63
+ .toolbar-left, .toolbar-right { display: flex; align-items: center; gap: 10px; }
64
+ .toolbar-btn { background: white; color: var(--text-muted); border: 1px solid var(--gray-border); border-radius: 4px; padding: 6px 12px; cursor: pointer; font-size: 0.9em; }
65
+ .toolbar-btn:hover { color: var(--blue-primary); background-color: #f8f9fa; }
66
+ .btn-run { background-color: var(--green-primary); color: white; font-weight: bold; display: flex; align-items: center; gap: 5px; }
67
+ .btn-run:hover { background-color: var(--green-hover); }
68
+ .toolbar-group { display: flex; gap: 5px; }
69
+ .input-group { position: relative; }
70
+ .input-group input { border: 1px solid var(--gray-border); border-radius: 4px; padding: 6px 10px; font-size: 0.9em; width: 200px; }
71
+ .input-group i { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); color: var(--text-muted); cursor: pointer; }
72
+
73
+ .content-wrapper { flex: 1; display: flex; overflow: hidden; }
74
+ .editor-pane { flex: 1; border-right: 2px solid #ddd; display: flex; flex-direction: column; }
75
+ .CodeMirror { flex: 1; height: 100%; font-size: 14px; line-height: 1.4; border: none; }
76
+
77
+ .output-pane { flex: 1; display: flex; }
78
+ .output-sidebar { width: 40px; background-color: #f1f3f5; border-right: 1px solid var(--gray-border); display: flex; flex-direction: column; align-items: center; padding-top: 10px; gap: 15px; }
79
+ .sidebar-icon { color: var(--text-muted); cursor: pointer; font-size: 1.1em; }
80
+ .sidebar-icon:hover, .sidebar-icon.active { color: var(--blue-primary); }
81
+
82
+ .output-main { flex: 1; display: flex; flex-direction: column; background: white; }
83
+ .output-header-pane { border-bottom: 1px solid var(--gray-border); padding: 5px 15px; color: var(--text-muted); font-size: 0.85em; text-transform: uppercase; font-weight: bold; background: #f8f9fa; }
84
+ .output-body { flex: 1; padding: 15px; white-space: pre-wrap; font-family: 'Courier New', Courier, monospace; overflow-y: auto; color: #333; font-size: 14px; }
85
+ .loading-text { color: var(--text-muted); }
86
+
87
+ .status-bar { background-color: #eaedf1; color: var(--text-muted); font-size: 0.8em; padding: 4px 15px; border-top: 1px solid var(--gray-border); display: flex; justify-content: flex-start; gap: 15px; }
88
+ </style>
89
+ </head>
90
+ <body>
91
+ <header class="header">
92
+ <div class="header-left">
93
+ <i class="fa-brands fa-python"></i> <span>ONLINE PYTHON</span>
94
+ </div>
95
+ <div class="header-right">
96
+ <a href="#" class="btn-learn">Learn Python</a>
97
+ <a href="#" class="btn-try-new">Try New IDE <i class="fa-solid fa-arrow-right-long"></i></a>
98
+ </div>
99
+ </header>
100
+
101
+ <div class="toolbar-wrapper">
102
+ <div class="file-tabs">
103
+ <div class="file-tab">main.py</div>
104
+ <i class="fa-solid fa-plus btn-add-file"></i>
105
+ </div>
106
+ <div class="toolbar-core">
107
+ <div class="toolbar-left">
108
+ <div class="toolbar-group">
109
+ <button class="toolbar-btn"><i class="fa-solid fa-arrow-rotate-left"></i></button>
110
+ <button class="toolbar-btn"><i class="fa-solid fa-arrow-rotate-right"></i></button>
111
+ <button class="toolbar-btn"><i class="fa-solid fa-arrow-right-from-bracket"></i></button>
112
+ </div>
113
+ <button class="toolbar-btn" style="color: black;"><i class="fa-solid fa-plus-circle"></i> Install Module</button>
114
+ </div>
115
+ <div class="toolbar-right">
116
+ <button onclick="runCode()" class="toolbar-btn btn-run"><i class="fa-solid fa-play"></i> Run</button>
117
+ <button class="toolbar-btn"><i class="fa-solid fa-share-nodes"></i> Share</button>
118
+ <div class="input-group">
119
+ <input type="text" placeholder="Command Line Arguments">
120
+ <i class="fa-solid fa-paperclip"></i>
121
+ </div>
122
+ <div class="toolbar-group">
123
+ <button class="toolbar-btn"><i class="fa-solid fa-user-circle"></i></button>
124
+ <button class="toolbar-btn"><i class="fa-solid fa-moon"></i></button>
125
+ <button class="toolbar-btn"><i class="fa-solid fa-cog"></i></button>
126
+ <button class="toolbar-btn"><i class="fa-solid fa-life-ring"></i></button>
127
+ </div>
128
+ </div>
129
+ </div>
130
+ </div>
131
+
132
+ <div class="content-wrapper">
133
+ <div class="editor-pane">
134
+ <textarea id="editor"></textarea>
135
+ </div>
136
+ <div class="output-pane">
137
+ <div class="output-sidebar">
138
+ <i class="fa-solid fa-terminal sidebar-icon active"></i>
139
+ <i class="fa-solid fa-folder-open sidebar-icon"></i>
140
+ <i class="fa-solid fa-search sidebar-icon"></i>
141
+ <i class="fa-solid fa-code-merge sidebar-icon"></i>
142
+ </div>
143
+ <div class="output-main">
144
+ <div class="output-header-pane">Terminal / Output</div>
145
+ <div id="output" class="output-body">Process finished with exit code 0</div>
146
+ </div>
147
+ </div>
148
+ </div>
149
+
150
+ <footer class="status-bar">
151
+ <span>Ln: <span id="line-count">1</span>, Col: <span id="col-count">1</span></span>
152
+ </footer>
153
+
154
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/codemirror.min.js"></script>
155
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/mode/python/python.min.js"></script>
156
+
157
+ <script>
158
+ var editor = CodeMirror.fromTextArea(document.getElementById("editor"), {
159
+ mode: "python",
160
+ theme: "default",
161
+ lineNumbers: true,
162
+ indentUnit: 4,
163
+ matchBrackets: true,
164
+ autofocus: true
165
+ });
166
+
167
+ editor.setValue("# Online Python - IDE, Editor, Compiler, Interpreter\n\ndef sum(a, b):\n return (a + b)\n\na = int(input('Enter 1st number: '))\nb = int(input('Enter 2nd number: '))\n\nprint(f'Sum of {a} and {b} is {sum(a, b)}')\n");
168
+
169
+ function updateStatusBar() {
170
+ var cursor = editor.getCursor();
171
+ document.getElementById('line-count').innerText = cursor.line + 1;
172
+ document.getElementById('col-count').innerText = cursor.ch + 1;
173
+ }
174
+ editor.on('cursorActivity', updateStatusBar);
175
+ updateStatusBar();
176
+
177
+ /**
178
+ * Защищает блоки с математическими формулами от обработки Markdown-парсером.
179
+ * Заменяет формулы на уникальные плейсхолдеры, а после парсинга восстанавливает их.
180
+ */
181
+ function renderOutput(rawText) {
182
+ const mathBlocks = [];
183
+
184
+ // Функция для сохранения формулы и возврата плейсхолдера
185
+ const protect = (match) => {
186
+ const id = mathBlocks.length;
187
+ mathBlocks.push(match);
188
+ return `%%MATH_BLOCK_${id}%%`;
189
+ };
190
+
191
+ let text = rawText;
192
+
193
+ // 1. Защищаем блочные формулы $$...$$ (многострочные)
194
+ text = text.replace(/\$\$([\s\S]*?)\$\$/g, protect);
195
+
196
+ // 2. Защищаем блочные формулы \[...\]
197
+ text = text.replace(/\\\[([\s\S]*?)\\\]/g, protect);
198
+
199
+ // 3. Защищаем инлайновые формулы \(...\)
200
+ text = text.replace(/\\\([\s\S]*?\\\)/g, protect);
201
+
202
+ // 4. Защищаем инлайновые формулы $...$ (не многострочные)
203
+ text = text.replace(/\$([^\$\n]+?)\$/g, protect);
204
+
205
+ // 5. Парсим Markdown — теперь он не видит LaTeX
206
+ marked.setOptions({ breaks: true, gfm: true });
207
+ let html = marked.parse(text);
208
+
209
+ // 6. Восстанавливаем формулы обратно в HTML
210
+ html = html.replace(/%%MATH_BLOCK_(\d+)%%/g, (_, idx) => mathBlocks[parseInt(idx)]);
211
+
212
+ return html;
213
+ }
214
+
215
+ async function runCode() {
216
+ const code = editor.getValue();
217
+ const outputDiv = document.getElementById("output");
218
+
219
+ outputDiv.innerHTML = "<span class='loading-text'>Executing main.py...</span>";
220
+
221
+ try {
222
+ const response = await fetch('/run', {
223
+ method: 'POST',
224
+ headers: { 'Content-Type': 'application/json' },
225
+ body: JSON.stringify({ code: code })
226
+ });
227
+
228
+ const data = await response.json();
229
+
230
+ if (data.output) {
231
+ // Рендерим Markdown с защитой формул
232
+ outputDiv.innerHTML = renderOutput(data.output);
233
+
234
+ // Запускаем KaTeX — теперь формулы уже восстановлены в DOM
235
+ renderMathInElement(outputDiv, {
236
+ delimiters: [
237
+ { left: '$$', right: '$$', display: true },
238
+ { left: '$', right: '$', display: false },
239
+ { left: '\\(', right: '\\)', display: false },
240
+ { left: '\\[', right: '\\]', display: true }
241
+ ],
242
+ throwOnError: false,
243
+ ignoredTags: ["script", "noscript", "style", "textarea", "pre", "code"]
244
+ });
245
+
246
+ } else if (data.error) {
247
+ outputDiv.innerHTML = `<span style="color: #dc3545;">${data.error}</span>`;
248
+ }
249
+
250
+ outputDiv.innerHTML += `
251
+ <hr class="process-divider">
252
+ <span style="color: #6c757d; font-size: 0.9em;">Process finished with exit code 0</span>
253
+ `;
254
+
255
+ } catch (err) {
256
+ outputDiv.innerText = "Error: Could not connect to the server.";
257
+ console.error(err);
258
+ }
259
+ }
260
+ </script>
261
+ </body>
262
+ </html>