This commit is contained in:
blueloveTH 2024-08-11 15:41:07 +08:00
parent d3a851fb46
commit ca459f6b65
10 changed files with 1907 additions and 356 deletions

View File

@ -7,4 +7,8 @@ mkdir web/lib
SRC=$(find src/ -name "*.c")
emcc $SRC -Iinclude/ -s -Os -sEXPORTED_FUNCTIONS=_py_initialize,_py_finalize,_py_exec,_py_replinput -sEXPORTED_RUNTIME_METHODS=ccall -o web/lib/pocketpy.js
emcc $SRC -Iinclude/ -s -Os \
-sEXPORTED_FUNCTIONS=_py_initialize,_py_exec,_py_finalize,_py_printexc,_py_clearexc \
-sEXPORTED_RUNTIME_METHODS=ccall \
-sALLOW_MEMORY_GROWTH=1 \
-o web/lib/pocketpy.js

View File

@ -1,15 +1,256 @@
<!doctype html>
<html>
<head>
<!--
Note:
This site was created by modifying code pen https://codepen.io/antonmedv/pen/PoPoGwg
written by 'Anton Medvedev' the license can be found bellow.
LICENSE
-------
Copyright (c) 2022 by Anton Medvedev (https://codepen.io/antonmedv/pen/PoPoGwg)
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>pocketpy demo</title>
<link rel="stylesheet" href="xterm/xterm.css" />
<script src="xterm/xterm.js"></script>
<script src="index.js" ></script>
</head>
<body>
<div id="terminal"></div>
<script>term_init();</script>
<script src="./lib/pocketpy.js"></script>
</body>
</html>
<script src="static/codejar/codejar.js"></script>
<script src="static/codejar/linenumbers.js"></script>
<script src="static/highlight.js/highlight.min.js"></script>
<link rel="stylesheet" href="static/highlight.js/github-dark-dimmed.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<style>
@import url("https://fonts.googleapis.com/css2?family=Lato:wght@300&family=PT+Mono&display=swap");
.hljs{display:block;overflow-x:auto;padding:.5em;background:#282a36}
.hljs-keyword,.hljs-selector-tag,.hljs-literal,.hljs-section,.hljs-link{color:#73cbde}
.hljs,.hljs-subst{color:#f8f8f2}
.hljs-string,.hljs-title,.hljs-name,.hljs-type,.hljs-attribute,.hljs-symbol,
.hljs-bullet,.hljs-addition,.hljs-variable,.hljs-template-tag,.hljs-template-variable{color:#f1fa8c}
.hljs-comment,.hljs-quote,.hljs-deletion,.hljs-meta{color:#6272a4}
.hljs-keyword,.hljs-selector-tag,.hljs-literal,.hljs-title,.hljs-section,.hljs-doctag,
.hljs-type,.hljs-name,.hljs-strong{font-weight:bold}.hljs-emphasis{font-style:italic}
:root {
--window-width: 80%;
}
body {
background-color: #778abb;
font-family: Lato, sans-serif;
font-weight: 300;
font-size: 15px;
margin: 0;
}
*,
*:before,
*:after {
box-sizing: border-box;
}
*:focus {
outline: none;
}
a,
a:visited,
a:active {
color: black;
}
main {
min-height: 100vh;
display: flex;
align-items: center;
flex-direction: column;
}
.title {
color: #fff;
text-align: center;
font-weight: 300;
font-size: 34px;
margin-top: 20px;
}
.window {
width: var(--window-width);
border-radius: 6px;
box-shadow: 0 8px 12px rgba(0, 0, 0, 0.1);
overflow: hidden;
margin-bottom: 20px;
}
.window .window-header {
height: 25px;
background: Gainsboro;
position: relative;
}
.window .window-header .action-buttons {
position: absolute;
top: 50%;
left: 10px;
margin-top: -5px;
width: 10px;
height: 10px;
background: Crimson;
border-radius: 50%;
box-shadow: 15px 0 0 Orange, 30px 0 0 LimeGreen;
}
#code-editor {
border-bottom-left-radius: 6px;
border-bottom-right-radius: 6px;
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12),
0 3px 1px -2px rgba(0, 0, 0, 0.2);
font-family: "PT Mono", monospace;
font-size: 14px;
font-weight: 400;
min-height: 300px;
letter-spacing: normal;
line-height: 20px;
padding: 10px;
resize: none !important;
tab-size: 4;
}
#run-button {
padding-left: 10px;
padding-right: 10px;
font-weight: bold;
cursor: pointer;
}
#code-editor.hljs {
padding: 10px;
}
#output-wrapper {
font-family: "PT Mono", monospace;
width: var(--window-width);
min-height: 50px;
background-color: #282a36;
border-radius: 6px;
padding: 10px;
color: white;
margin:0 !important;
}
#code-output span.error-line {
color: #ec5424;
}
.controls {
font-size: 14px;
position: absolute;
top: 50%;
right: 10px;
margin-top: -10px;
display: flex;
}
.controls > div:first-child > a {
display: inline-block;
width: 40px;
}
.features {
width: 547px;
font-size: 16px;
margin-bottom: 30px;
}
</style>
<title>Try Online</title>
</head>
<body id="tryonline-body">
<main>
<br>
<div class="window">
<div class="window-header">
<div class="action-buttons"></div>
<div class="controls">
<div id="run-button">Run</div>
</div>
</div>
<div class="window-body">
<div id="code-editor" class="language-python" data-gramm="false"># A recursive fibonacci function.
def fib(n):
if n &lt; 2:
return n
return fib(n-1) + fib(n-2)
# Prints all fibonacci from 0 to 10 exclusive.
for i in range(10):
print(f"fib({i}) = {fib(i)}")
</div>
</div>
</div>
<pre id="output-wrapper"><div id="code-output">...</div></pre>
<br>
</main>
<script>
let code_editor = document.querySelector('#code-editor');
let code_output = document.querySelector('#code-output');
let run_button = document.querySelector('#run-button');
let highlight = withLineNumbers(function(editor) {
editor.textContent = editor.textContent;
hljs.highlightElement(editor);
});
highlight(code_editor);
CodeJar(code_editor, highlight); //, { indentOn: /[(\[{:]$/});
var Module = {
onRuntimeInitialized: function() {
Module.ccall('py_initialize', null, [], []);
},
print: function(text) {
console.log(text);
code_output.innerText += text + '\n';
},
onabort: function(what) {
code_output.innerText += 'Aborted: ' + what + '\n';
Module.ccall('py_finalize', null, [], []);
}
};
window.onload = function() {
var script = document.createElement('script');
script.src = 'lib/pocketpy.js';
document.head.appendChild(script);
run_button.onclick = function() {
code_output.innerText = '';
const source = code_editor.textContent;
var ok = Module.ccall(
'py_exec', 'boolean', ['string', 'string', 'number', 'number'],
[source, 'main.py', 0, 0]
);
if (!ok) {
Module.ccall('py_printexc', null, [], []);
Module.ccall('py_clearexc', null, ['number'], [0]);
}
}
}
</script>
</body>
</html>

View File

@ -1,163 +0,0 @@
const MINIMUM_COLS = 2
const MINIMUM_ROWS = 1
class FitAddon {
constructor() {}
activate(terminal) {
this._terminal = terminal
}
dispose() {}
fit() {
const dims = this.proposeDimensions()
if (!dims || !this._terminal || isNaN(dims.cols) || isNaN(dims.rows)) {
return
}
// TODO: Remove reliance on private API
const core = this._terminal._core
// Force a full render
if (
this._terminal.rows !== dims.rows ||
this._terminal.cols !== dims.cols
) {
core._renderService.clear()
this._terminal.resize(dims.cols, dims.rows)
}
}
proposeDimensions() {
if (!this._terminal) {
return undefined
}
if (!this._terminal.element || !this._terminal.element.parentElement) {
return undefined
}
// TODO: Remove reliance on private API
const core = this._terminal._core
const dims = core._renderService.dimensions
if (dims.actualCellWidth === 0 || dims.actualCellHeight === 0) {
return undefined
}
const scrollbarWidth =
this._terminal.options.scrollback === 0 ? 0 : core.viewport.scrollBarWidth
const parentElementStyle = window.getComputedStyle(
this._terminal.element.parentElement
)
const parentElementHeight = parseInt(
parentElementStyle.getPropertyValue("height")
)
const parentElementWidth = Math.max(
0,
parseInt(parentElementStyle.getPropertyValue("width"))
)
const elementStyle = window.getComputedStyle(this._terminal.element)
const elementPadding = {
top: parseInt(elementStyle.getPropertyValue("padding-top")),
bottom: parseInt(elementStyle.getPropertyValue("padding-bottom")),
right: parseInt(elementStyle.getPropertyValue("padding-right")),
left: parseInt(elementStyle.getPropertyValue("padding-left"))
}
const elementPaddingVer = elementPadding.top + elementPadding.bottom
const elementPaddingHor = elementPadding.right + elementPadding.left
const availableHeight = parentElementHeight - elementPaddingVer
const availableWidth =
parentElementWidth - elementPaddingHor - scrollbarWidth
const geometry = {
cols: Math.max(
MINIMUM_COLS,
Math.floor(availableWidth / dims.actualCellWidth)
),
rows: Math.max(
MINIMUM_ROWS,
Math.floor(availableHeight / dims.actualCellHeight)
)
}
return geometry
}
}
/******************************************************/
const term = new Terminal(
{
cursorBlink: true,
fontSize: 16,
theme: {
background: '#282C34',
foreground: '#ffffff',
cursor: '#ffffff',
cursorAccent: '#282C34',
selection: '#41454E',
},
}
);
var command = "";
var need_more_lines = false;
var stopped = false;
var repl = 0;
var Module = {
'print': function(text) {
term.write(text + "\r\n");
},
'printErr': function(text) {
term.write(text + "\r\n");
},
'onRuntimeInitialized': function(text) {
var vm = Module.ccall('pkpy_new_vm', 'number', ['boolean'], [true]);
repl = Module.ccall('pkpy_new_repl', 'number', ['number'], [vm]);
term.write(need_more_lines ? "... " : ">>> ");
},
'onAbort': function(text) {
stopped = true;
},
};
function term_init() {
term.open(document.getElementById('terminal'));
const addon = new FitAddon();
term.loadAddon(addon);
addon.fit();
// refit when window is resized
window.addEventListener('resize', () => {
addon.fit();
});
term.onData(e => {
if (stopped) return;
switch (e) {
case '\r': // Enter
term.write("\r\n");
need_more_lines = Module.ccall('pkpy_repl_input', 'bool', ['number', 'string'], [repl, command]);
command = '';
term.write(need_more_lines ? "... " : ">>> ");
break;
case '\u007F': // Backspace (DEL)
var cnt = term._core.buffer.x-4;
if(cnt<=0 || command.length==0) break;
// delete the last unicode char
command = command.replace(/.$/u, "");
// clear the whole line
term.write('\b \b'.repeat(cnt));
// re-write the command
term.write(command);
break;
default: // Print all other characters for demo
if (e >= String.fromCharCode(0x20) && e <= String.fromCharCode(0x7E) || e >= '\u00a0') {
command += e;
term.write(e);
}
}
});
}

View File

@ -0,0 +1,423 @@
const globalWindow = window;
function CodeJar(editor, highlight, opt = {}) {
const options = Object.assign({ tab: '\t', indentOn: /{$/, spellcheck: false, catchTab: true, preserveIdent: true, addClosing: true, history: true, window: globalWindow }, opt);
const window = options.window;
const document = window.document;
let listeners = [];
let history = [];
let at = -1;
let focus = false;
let callback;
let prev; // code content prior keydown event
let isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
editor.setAttribute('contentEditable', isFirefox ? 'true' : 'plaintext-only');
editor.setAttribute('spellcheck', options.spellcheck ? 'true' : 'false');
editor.style.outline = 'none';
editor.style.overflowWrap = 'break-word';
editor.style.overflowY = 'auto';
editor.style.resize = 'vertical';
editor.style.whiteSpace = 'pre-wrap';
highlight(editor);
const debounceHighlight = debounce(() => {
const pos = save();
highlight(editor, pos);
restore(pos);
}, 30);
let recording = false;
const shouldRecord = (event) => {
return !isUndo(event) && !isRedo(event)
&& event.key !== 'Meta'
&& event.key !== 'Control'
&& event.key !== 'Alt'
&& !event.key.startsWith('Arrow');
};
const debounceRecordHistory = debounce((event) => {
if (shouldRecord(event)) {
recordHistory();
recording = false;
}
}, 300);
const on = (type, fn) => {
listeners.push([type, fn]);
editor.addEventListener(type, fn);
};
on('keydown', event => {
if (event.defaultPrevented)
return;
prev = toString();
if (options.preserveIdent)
handleNewLine(event);
else
firefoxNewLineFix(event);
if (options.catchTab)
handleTabCharacters(event);
if (options.addClosing)
handleSelfClosingCharacters(event);
if (options.history) {
handleUndoRedo(event);
if (shouldRecord(event) && !recording) {
recordHistory();
recording = true;
}
}
});
on('keyup', event => {
if (event.defaultPrevented)
return;
if (event.isComposing)
return;
if (prev !== toString())
debounceHighlight();
debounceRecordHistory(event);
if (callback)
callback(toString());
});
on('focus', _event => {
focus = true;
});
on('blur', _event => {
focus = false;
});
on('paste', event => {
recordHistory();
handlePaste(event);
recordHistory();
if (callback)
callback(toString());
});
function save() {
const s = getSelection();
const pos = { start: 0, end: 0, dir: undefined };
visit(editor, el => {
if (el === s.anchorNode && el === s.focusNode) {
pos.start += s.anchorOffset;
pos.end += s.focusOffset;
pos.dir = s.anchorOffset <= s.focusOffset ? '->' : '<-';
return 'stop';
}
if (el === s.anchorNode) {
pos.start += s.anchorOffset;
if (!pos.dir) {
pos.dir = '->';
}
else {
return 'stop';
}
}
else if (el === s.focusNode) {
pos.end += s.focusOffset;
if (!pos.dir) {
pos.dir = '<-';
}
else {
return 'stop';
}
}
if (el.nodeType === Node.TEXT_NODE) {
if (pos.dir != '->')
pos.start += el.nodeValue.length;
if (pos.dir != '<-')
pos.end += el.nodeValue.length;
}
});
return pos;
}
function restore(pos) {
const s = getSelection();
let startNode, startOffset = 0;
let endNode, endOffset = 0;
if (!pos.dir)
pos.dir = '->';
if (pos.start < 0)
pos.start = 0;
if (pos.end < 0)
pos.end = 0;
// Flip start and end if the direction reversed
if (pos.dir == '<-') {
const { start, end } = pos;
pos.start = end;
pos.end = start;
}
let current = 0;
visit(editor, el => {
if (el.nodeType !== Node.TEXT_NODE)
return;
const len = (el.nodeValue || '').length;
if (current + len >= pos.start) {
if (!startNode) {
startNode = el;
startOffset = pos.start - current;
}
if (current + len >= pos.end) {
endNode = el;
endOffset = pos.end - current;
return 'stop';
}
}
current += len;
});
// If everything deleted place cursor at editor
if (!startNode)
startNode = editor;
if (!endNode)
endNode = editor;
// Flip back the selection
if (pos.dir == '<-') {
[startNode, startOffset, endNode, endOffset] = [endNode, endOffset, startNode, startOffset];
}
s.setBaseAndExtent(startNode, startOffset, endNode, endOffset);
}
function beforeCursor() {
const s = getSelection();
const r0 = s.getRangeAt(0);
const r = document.createRange();
r.selectNodeContents(editor);
r.setEnd(r0.startContainer, r0.startOffset);
return r.toString();
}
function afterCursor() {
const s = getSelection();
const r0 = s.getRangeAt(0);
const r = document.createRange();
r.selectNodeContents(editor);
r.setStart(r0.endContainer, r0.endOffset);
return r.toString();
}
function handleNewLine(event) {
if (event.key === 'Enter') {
const before = beforeCursor();
const after = afterCursor();
let [padding] = findPadding(before);
let newLinePadding = padding;
// If last symbol is "{" ident new line
// Allow user defines indent rule
if (options.indentOn.test(before)) {
newLinePadding += options.tab;
}
// Preserve padding
if (newLinePadding.length > 0) {
preventDefault(event);
event.stopPropagation();
insert('\n' + newLinePadding);
}
else {
firefoxNewLineFix(event);
}
// Place adjacent "}" on next line
if (newLinePadding !== padding && after[0] === '}') {
const pos = save();
insert('\n' + padding);
restore(pos);
}
}
}
function firefoxNewLineFix(event) {
// Firefox does not support plaintext-only mode
// and puts <div><br></div> on Enter. Let's help.
if (isFirefox && event.key === 'Enter') {
preventDefault(event);
event.stopPropagation();
if (afterCursor() == '') {
insert('\n ');
const pos = save();
pos.start = --pos.end;
restore(pos);
}
else {
insert('\n');
}
}
}
function handleSelfClosingCharacters(event) {
const open = `([{'"`;
const close = `)]}'"`;
const codeAfter = afterCursor();
const codeBefore = beforeCursor();
const escapeCharacter = codeBefore.substr(codeBefore.length - 1) === '\\';
const charAfter = codeAfter.substr(0, 1);
if (close.includes(event.key) && !escapeCharacter && charAfter === event.key) {
// We already have closing char next to cursor.
// Move one char to right.
const pos = save();
preventDefault(event);
pos.start = ++pos.end;
restore(pos);
}
else if (open.includes(event.key)
&& !escapeCharacter
&& (`"'`.includes(event.key) || ['', ' ', '\n'].includes(charAfter))) {
preventDefault(event);
const pos = save();
const wrapText = pos.start == pos.end ? '' : getSelection().toString();
const text = event.key + wrapText + close[open.indexOf(event.key)];
insert(text);
pos.start++;
pos.end++;
restore(pos);
}
}
function handleTabCharacters(event) {
if (event.key === 'Tab') {
preventDefault(event);
if (event.shiftKey) {
const before = beforeCursor();
let [padding, start,] = findPadding(before);
if (padding.length > 0) {
const pos = save();
// Remove full length tab or just remaining padding
const len = Math.min(options.tab.length, padding.length);
restore({ start, end: start + len });
document.execCommand('delete');
pos.start -= len;
pos.end -= len;
restore(pos);
}
}
else {
insert(options.tab);
}
}
}
function handleUndoRedo(event) {
if (isUndo(event)) {
preventDefault(event);
at--;
const record = history[at];
if (record) {
editor.innerHTML = record.html;
restore(record.pos);
}
if (at < 0)
at = 0;
}
if (isRedo(event)) {
preventDefault(event);
at++;
const record = history[at];
if (record) {
editor.innerHTML = record.html;
restore(record.pos);
}
if (at >= history.length)
at--;
}
}
function recordHistory() {
if (!focus)
return;
const html = editor.innerHTML;
const pos = save();
const lastRecord = history[at];
if (lastRecord) {
if (lastRecord.html === html
&& lastRecord.pos.start === pos.start
&& lastRecord.pos.end === pos.end)
return;
}
at++;
history[at] = { html, pos };
history.splice(at + 1);
const maxHistory = 300;
if (at > maxHistory) {
at = maxHistory;
history.splice(0, 1);
}
}
function handlePaste(event) {
preventDefault(event);
const text = (event.originalEvent || event)
.clipboardData
.getData('text/plain')
.replace(/\r/g, '');
const pos = save();
insert(text);
highlight(editor);
restore({ start: pos.start + text.length, end: pos.start + text.length });
}
function visit(editor, visitor) {
const queue = [];
if (editor.firstChild)
queue.push(editor.firstChild);
let el = queue.pop();
while (el) {
if (visitor(el) === 'stop')
break;
if (el.nextSibling)
queue.push(el.nextSibling);
if (el.firstChild)
queue.push(el.firstChild);
el = queue.pop();
}
}
function isCtrl(event) {
return event.metaKey || event.ctrlKey;
}
function isUndo(event) {
return isCtrl(event) && !event.shiftKey && event.key === 'z';
}
function isRedo(event) {
return isCtrl(event) && event.shiftKey && event.key === 'z';
}
function insert(text) {
text = text
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#039;');
document.execCommand('insertHTML', false, text);
}
function debounce(cb, wait) {
let timeout = 0;
return (...args) => {
clearTimeout(timeout);
timeout = window.setTimeout(() => cb(...args), wait);
};
}
function findPadding(text) {
// Find beginning of previous line.
let i = text.length - 1;
while (i >= 0 && text[i] !== '\n')
i--;
i++;
// Find padding of the line.
let j = i;
while (j < text.length && /[ \t]/.test(text[j]))
j++;
return [text.substring(i, j) || '', i, j];
}
function toString() {
return editor.textContent || '';
}
function preventDefault(event) {
event.preventDefault();
}
function getSelection() {
var _a;
if (((_a = editor.parentNode) === null || _a === void 0 ? void 0 : _a.nodeType) == Node.DOCUMENT_FRAGMENT_NODE) {
return editor.parentNode.getSelection();
}
return window.getSelection();
}
return {
updateOptions(options) {
options = Object.assign(Object.assign({}, options), options);
},
updateCode(code) {
editor.textContent = code;
highlight(editor);
},
onUpdate(cb) {
callback = cb;
},
toString,
save,
restore,
recordHistory,
destroy() {
for (let [type, fn] of listeners) {
editor.removeEventListener(type, fn);
}
},
};
}

View File

@ -0,0 +1,60 @@
function withLineNumbers(highlight, options = {}) {
const opts = Object.assign({ class: "codejar-linenumbers", wrapClass: "codejar-wrap", width: "35px", backgroundColor: "rgba(128, 128, 128, 0.15)", color: "" }, options);
let lineNumbers;
return function (editor) {
highlight(editor);
if (!lineNumbers) {
lineNumbers = init(editor, opts);
editor.addEventListener("scroll", () => lineNumbers.style.top = `-${editor.scrollTop}px`);
}
const code = editor.textContent || "";
//const linesCount = code.replace(/\n+$/, "\n").split("\n").length + 1;
const linesCount = code.split("\n").length;
let text = "";
for (let i = 1; i < linesCount; i++) {
text += `${i}\n`;
}
lineNumbers.innerText = text;
};
}
function init(editor, opts) {
const css = getComputedStyle(editor);
const wrap = document.createElement("div");
wrap.className = opts.wrapClass;
wrap.style.position = "relative";
const gutter = document.createElement("div");
gutter.className = opts.class;
wrap.appendChild(gutter);
// Add own styles
gutter.style.position = "absolute";
gutter.style.top = "0px";
gutter.style.left = "0px";
gutter.style.bottom = "0px";
gutter.style.width = opts.width;
gutter.style.overflow = "hidden";
gutter.style.backgroundColor = opts.backgroundColor;
gutter.style.color = opts.color || css.color;
gutter.style.setProperty("mix-blend-mode", "difference");
// Copy editor styles
gutter.style.fontFamily = css.fontFamily;
gutter.style.fontSize = css.fontSize;
gutter.style.lineHeight = css.lineHeight;
gutter.style.paddingTop = css.paddingTop;
gutter.style.paddingLeft = css.paddingLeft;
gutter.style.borderTopLeftRadius = css.borderTopLeftRadius;
gutter.style.borderBottomLeftRadius = css.borderBottomLeftRadius;
// Add line numbers
const lineNumbers = document.createElement("div");
lineNumbers.style.position = "relative";
lineNumbers.style.top = "0px";
gutter.appendChild(lineNumbers);
// Tweak editor styles
editor.style.paddingLeft = `calc(${opts.width} + ${gutter.style.paddingLeft})`;
editor.style.whiteSpace = "pre";
// Swap editor with a wrap
editor.parentNode.insertBefore(wrap, editor);
wrap.appendChild(editor);
return lineNumbers;
}

View File

@ -0,0 +1,11 @@
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}/*!
Theme: GitHub Dark Dimmed
Description: Dark dimmed theme as seen on github.com
Author: github.com
Maintainer: @Hirse
Updated: 2021-05-15
Colors taken from GitHub's CSS
*/
.hljs{color:#adbac7;background:#22272e}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#f47067}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#dcbdfb}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-variable{color:#6cb6ff}.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#96d0ff}.hljs-built_in,.hljs-symbol{color:#f69d50}.hljs-code,.hljs-comment,.hljs-formula{color:#768390}.hljs-name,.hljs-quote,.hljs-selector-pseudo,.hljs-selector-tag{color:#8ddb8c}.hljs-subst{color:#adbac7}.hljs-section{color:#316dca;font-weight:700}.hljs-bullet{color:#eac55f}.hljs-emphasis{color:#adbac7;font-style:italic}.hljs-strong{color:#adbac7;font-weight:700}.hljs-addition{color:#b4f1b4;background-color:#1b4721}.hljs-deletion{color:#ffd8d3;background-color:#78191b}

1152
web/static/highlight.js/highlight.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,174 +0,0 @@
.xterm {
cursor: text;
position: relative;
user-select: none;
-ms-user-select: none;
-webkit-user-select: none;
}
.xterm.focus,
.xterm:focus {
outline: none;
}
.xterm .xterm-helpers {
position: absolute;
top: 0;
/**
* The z-index of the helpers must be higher than the canvases in order for
* IMEs to appear on top.
*/
z-index: 5;
}
.xterm .xterm-helper-textarea {
padding: 0;
border: 0;
margin: 0;
/* Move textarea out of the screen to the far left, so that the cursor is not visible */
position: absolute;
opacity: 0;
left: -9999em;
top: 0;
width: 0;
height: 0;
z-index: -5;
/** Prevent wrapping so the IME appears against the textarea at the correct position */
white-space: nowrap;
overflow: hidden;
resize: none;
}
.xterm .composition-view {
/* TODO: Composition position got messed up somewhere */
background: #000;
color: #FFF;
display: none;
position: absolute;
white-space: nowrap;
z-index: 1;
}
.xterm .composition-view.active {
display: block;
}
#terminal {
border: #FFF;
border-style: solid;
border-width: 1px;
padding: 4px;
/* zoom: 1.2 !important; */
}
body {
margin: 0px;
height: 100%;
width: 100%;
background-color: #282C34;
overflow: hidden;
}
.xterm .xterm-viewport {
/* On OS X this is required in order for the scroll bar to appear fully opaque */
/* background-color: rgb(13,17,23) !important; */
/*overflow-y: scroll;*/
overflow: hidden;
cursor: default;
position: absolute;
right: 0;
left: 0;
top: 0;
bottom: 0;
}
.xterm .xterm-screen {
position: relative;
}
.xterm .xterm-screen canvas {
position: absolute;
left: 0;
top: 0;
}
.xterm .xterm-scroll-area {
visibility: hidden;
}
.xterm-char-measure-element {
display: inline-block;
visibility: hidden;
position: absolute;
top: 0;
left: -9999em;
line-height: normal;
}
.xterm.enable-mouse-events {
/* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */
cursor: default;
}
.xterm.xterm-cursor-pointer,
.xterm .xterm-cursor-pointer {
cursor: pointer;
}
.xterm.column-select.focus {
/* Column selection mode */
cursor: crosshair;
}
.xterm .xterm-accessibility,
.xterm .xterm-message {
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
z-index: 10;
color: transparent;
}
.xterm .live-region {
position: absolute;
left: -9999px;
width: 1px;
height: 1px;
overflow: hidden;
}
.xterm-dim {
opacity: 0.5;
}
.xterm-underline-1 { text-decoration: underline; }
.xterm-underline-2 { text-decoration: double underline; }
.xterm-underline-3 { text-decoration: wavy underline; }
.xterm-underline-4 { text-decoration: dotted underline; }
.xterm-underline-5 { text-decoration: dashed underline; }
.xterm-strikethrough {
text-decoration: line-through;
}
.xterm-screen .xterm-decoration-container .xterm-decoration {
z-index: 6;
position: absolute;
}
.xterm-decoration-overview-ruler {
z-index: 7;
position: absolute;
top: 0;
right: 0;
pointer-events: none;
}
.xterm-decoration-top {
z-index: 2;
position: relative;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long