yo static files tho??
This commit is contained in:
parent
50f2c97d0c
commit
21dd617a4b
|
@ -699,6 +699,25 @@ dependencies = [
|
|||
"unicode-normalization",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "include_dir"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18762faeff7122e89e0857b02f7ce6fcc0d101d5e9ad2ad7846cc01d61b7f19e"
|
||||
dependencies = [
|
||||
"include_dir_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "include_dir_macros"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b139284b5cf57ecfa712bcc66950bb635b31aff41c188e8a4cfc758eca374a3f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.3"
|
||||
|
@ -1253,6 +1272,8 @@ dependencies = [
|
|||
"dotenvy",
|
||||
"futures-util",
|
||||
"git2",
|
||||
"include_dir",
|
||||
"mime_guess",
|
||||
"rnix",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
|
|
@ -13,6 +13,8 @@ clap = { version = "4", features = ["env", "derive"] }
|
|||
dotenvy = "0.15"
|
||||
futures-util = "0.3"
|
||||
git2 = { version = "0.18", default-features = false }
|
||||
include_dir = "0.7"
|
||||
mime_guess = "2"
|
||||
rnix = "0.11"
|
||||
serde = "1"
|
||||
serde_json = "1"
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
use axum::{
|
||||
body::{self, Empty, Full},
|
||||
extract::Path,
|
||||
http::{header, HeaderValue, Response, StatusCode},
|
||||
response::IntoResponse,
|
||||
};
|
||||
use include_dir::{include_dir, Dir};
|
||||
|
||||
static STATIC_DIR: Dir<'_> = include_dir!("$CARGO_MANIFEST_DIR/static");
|
||||
|
||||
pub(super) async fn static_path(Path(path): Path<String>) -> impl IntoResponse {
|
||||
let path = path.trim_start_matches('/');
|
||||
let mime_type = mime_guess::from_path(path).first_or_text_plain();
|
||||
|
||||
match STATIC_DIR.get_file(path) {
|
||||
None => Response::builder()
|
||||
.status(StatusCode::NOT_FOUND)
|
||||
.body(body::boxed(Empty::new()))
|
||||
.unwrap(),
|
||||
Some(file) => Response::builder()
|
||||
.status(StatusCode::OK)
|
||||
.header(
|
||||
header::CONTENT_TYPE,
|
||||
HeaderValue::from_str(mime_type.as_ref()).unwrap(),
|
||||
)
|
||||
.body(body::boxed(Full::from(file.contents())))
|
||||
.unwrap(),
|
||||
}
|
||||
}
|
|
@ -13,6 +13,9 @@ use askama::Template;
|
|||
use axum::{extract::State, response::IntoResponse, routing::get, Json, Router};
|
||||
use serde_json::json;
|
||||
|
||||
use self::assets::static_path;
|
||||
|
||||
mod assets;
|
||||
mod container;
|
||||
mod stack;
|
||||
|
||||
|
@ -40,6 +43,7 @@ async fn get_sys_info() -> impl IntoResponse {
|
|||
|
||||
pub(crate) fn router() -> Router<AppState> {
|
||||
Router::new()
|
||||
.route("/static/*path", get(static_path))
|
||||
.route("/", get(home))
|
||||
.route("/sysinfo", get(get_sys_info))
|
||||
.nest("/stack", stack::router())
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
.editor form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1ch;
|
||||
|
||||
& .row {
|
||||
display: flex;
|
||||
gap: 0.5ch;
|
||||
|
||||
& input,
|
||||
& button {
|
||||
font-size: 13pt;
|
||||
padding: 6px 10px;
|
||||
|
||||
&.wide {
|
||||
padding: 6px 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#editor {
|
||||
border-width: 3px;
|
||||
min-height: 50vh;
|
||||
}
|
||||
|
||||
.ace_editor {
|
||||
min-height: 50vh;
|
||||
border: 3px solid #5958B1;
|
||||
border-radius: 3px;
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
:root {
|
||||
--background: #13131E;
|
||||
--bg-raised: #171625;
|
||||
--text: #E0DFFE;
|
||||
|
||||
--link: #FFC53D;
|
||||
--link-hover: #e28d0e;
|
||||
|
||||
--button-color: #B1A9FF;
|
||||
--button-bg: #202248;
|
||||
--button-border: #5B5BD6;
|
||||
--button-bg-hover: #7E451D;
|
||||
|
||||
background-color: var(--background);
|
||||
color: var(--text);
|
||||
font-family: Inter, sans-serif;
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: "Iosevka Web", monospace;
|
||||
font-size: 11pt;
|
||||
}
|
||||
|
||||
a[href],
|
||||
a[href]:visited {
|
||||
color: var(--link);
|
||||
|
||||
&:hover {
|
||||
color: var(--link-hover);
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
nav {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
background-color: var(--bg-raised);
|
||||
|
||||
& a {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
text-decoration: none;
|
||||
padding: 5px 8px;
|
||||
justify-content: center;
|
||||
max-width: 100px;
|
||||
box-shadow: inset 0 -2px var(--button-bg);
|
||||
font-size: 11pt;
|
||||
text-transform: uppercase;
|
||||
|
||||
&[href],
|
||||
&[href]:visited {
|
||||
color: var(--button-color);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: #1E160F;
|
||||
box-shadow: inset 0 -2px var(--button-bg-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
main {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
body,
|
||||
html {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: var(--button-bg);
|
||||
color: var(--button-color);
|
||||
border: 1px solid var(--button-border);
|
||||
padding: 4px 8px;
|
||||
border-radius: 3px;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background-color: var(--button-bg-hover);
|
||||
color: var(--link-hover);
|
||||
border-color: var(--link-hover);
|
||||
}
|
||||
}
|
||||
|
||||
table.table {
|
||||
background-color: var(--bg-raised);
|
||||
border: 3px solid #5958B1;
|
||||
border-radius: 3px;
|
||||
|
||||
& th,
|
||||
& td {
|
||||
padding: 3px 5px;
|
||||
}
|
||||
|
||||
& th {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
& thead {
|
||||
background-color: #202248;
|
||||
}
|
||||
}
|
||||
|
||||
.full-width {
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
input,
|
||||
textarea {
|
||||
border: 1px solid #5958B1;
|
||||
border-radius: 3px;
|
||||
background-color: var(--bg-raised);
|
||||
color: var(--text);
|
||||
padding: 4px;
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
import "../vendor/ace/ace.js";
|
||||
import { findNearestParent } from "./node-utils.mjs";
|
||||
|
||||
export default class Editor {
|
||||
/**
|
||||
* Create a new editor
|
||||
* @param {string} elementID ID of element to replace with the editor
|
||||
* @param {boolean} [hookForm=true] Automatically add event to parent form (if any) to set the value on submit
|
||||
*/
|
||||
constructor(elementID, hookForm = true) {
|
||||
/** @type {string} */
|
||||
let originalElementName = null;
|
||||
|
||||
/** @type {HTMLFormElement} */
|
||||
let parentForm = null;
|
||||
|
||||
if (hookForm) {
|
||||
const el = document.getElementById(elementID);
|
||||
if (!el) {
|
||||
throw new Error("there is no element with the specified ID");
|
||||
}
|
||||
|
||||
originalElementName = el.getAttribute("name");
|
||||
if (originalElementName) {
|
||||
// If it has a name it might have a form for a parent
|
||||
parentForm = findNearestParent(el, (parent) => parent.tagName == "FORM");
|
||||
}
|
||||
}
|
||||
|
||||
// Create editor
|
||||
ace.config.set('basePath', '/static/vendor/ace')
|
||||
this.editor = ace.edit(elementID);
|
||||
|
||||
// todo make this stuff customizable??
|
||||
this.editor.setTheme("ace/theme/dracula");
|
||||
this.editor.setOptions({
|
||||
fontFamily: "Iosevka Web",
|
||||
fontSize: "12pt",
|
||||
});
|
||||
this.editor.getSession().setUseWrapMode(true);
|
||||
this.editor.setKeyboardHandler("ace/keyboard/vim");
|
||||
this.editor.session.setMode("ace/mode/nix");
|
||||
|
||||
if (parentForm !== null) {
|
||||
parentForm.addEventListener("formdata", (ev) => {
|
||||
ev.formData.set(originalElementName, this.editor.getValue());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
|
||||
/**
|
||||
* Find nearest parent that satisfies a requirement
|
||||
* @param {Node|Element} node
|
||||
* @param {(el: Element) => boolean} findFn
|
||||
* @returns {HTMLElement | null} Found element, or null if no parent matches
|
||||
*/
|
||||
export function findNearestParent(node, findFn) {
|
||||
let parent = node.parentElement;
|
||||
while (parent) {
|
||||
if (findFn(parent)) {
|
||||
return parent;
|
||||
}
|
||||
parent = parent.parentElement;
|
||||
}
|
||||
return null;
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,555 @@
|
|||
ace.define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module){"use strict";
|
||||
var oop = require("../lib/oop");
|
||||
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
|
||||
var DocCommentHighlightRules = function () {
|
||||
this.$rules = {
|
||||
"start": [
|
||||
{
|
||||
token: "comment.doc.tag",
|
||||
regex: "@\\w+(?=\\s|$)"
|
||||
}, DocCommentHighlightRules.getTagRule(), {
|
||||
defaultToken: "comment.doc",
|
||||
caseInsensitive: true
|
||||
}
|
||||
]
|
||||
};
|
||||
};
|
||||
oop.inherits(DocCommentHighlightRules, TextHighlightRules);
|
||||
DocCommentHighlightRules.getTagRule = function (start) {
|
||||
return {
|
||||
token: "comment.doc.tag.storage.type",
|
||||
regex: "\\b(?:TODO|FIXME|XXX|HACK)\\b"
|
||||
};
|
||||
};
|
||||
DocCommentHighlightRules.getStartRule = function (start) {
|
||||
return {
|
||||
token: "comment.doc",
|
||||
regex: "\\/\\*(?=\\*)",
|
||||
next: start
|
||||
};
|
||||
};
|
||||
DocCommentHighlightRules.getEndRule = function (start) {
|
||||
return {
|
||||
token: "comment.doc",
|
||||
regex: "\\*\\/",
|
||||
next: start
|
||||
};
|
||||
};
|
||||
exports.DocCommentHighlightRules = DocCommentHighlightRules;
|
||||
|
||||
});
|
||||
|
||||
ace.define("ace/mode/c_cpp_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"], function(require, exports, module){"use strict";
|
||||
var oop = require("../lib/oop");
|
||||
var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules;
|
||||
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
|
||||
var cFunctions = exports.cFunctions = "hypot|hypotf|hypotl|sscanf|system|snprintf|scanf|scalbn|scalbnf|scalbnl|scalbln|scalblnf|scalblnl|sin|sinh|sinhf|sinhl|sinf|sinl|signal|signbit|strstr|strspn|strncpy|strncat|strncmp|strcspn|strchr|strcoll|strcpy|strcat|strcmp|strtoimax|strtod|strtoul|strtoull|strtoumax|strtok|strtof|strtol|strtold|strtoll|strerror|strpbrk|strftime|strlen|strrchr|strxfrm|sprintf|setjmp|setvbuf|setlocale|setbuf|sqrt|sqrtf|sqrtl|swscanf|swprintf|srand|nearbyint|nearbyintf|nearbyintl|nexttoward|nexttowardf|nexttowardl|nextafter|nextafterf|nextafterl|nan|nanf|nanl|csin|csinh|csinhf|csinhl|csinf|csinl|csqrt|csqrtf|csqrtl|ccos|ccosh|ccoshf|ccosf|ccosl|cimag|cimagf|cimagl|ctime|ctan|ctanh|ctanhf|ctanhl|ctanf|ctanl|cos|cosh|coshf|coshl|cosf|cosl|conj|conjf|conjl|copysign|copysignf|copysignl|cpow|cpowf|cpowl|cproj|cprojf|cprojl|ceil|ceilf|ceill|cexp|cexpf|cexpl|clock|clog|clogf|clogl|clearerr|casin|casinh|casinhf|casinhl|casinf|casinl|cacos|cacosh|cacoshf|cacoshl|cacosf|cacosl|catan|catanh|catanhf|catanhl|catanf|catanl|calloc|carg|cargf|cargl|cabs|cabsf|cabsl|creal|crealf|creall|cbrt|cbrtf|cbrtl|time|toupper|tolower|tan|tanh|tanhf|tanhl|tanf|tanl|trunc|truncf|truncl|tgamma|tgammaf|tgammal|tmpnam|tmpfile|isspace|isnormal|isnan|iscntrl|isinf|isdigit|isunordered|isupper|ispunct|isprint|isfinite|iswspace|iswcntrl|iswctype|iswdigit|iswupper|iswpunct|iswprint|iswlower|iswalnum|iswalpha|iswgraph|iswxdigit|iswblank|islower|isless|islessequal|islessgreater|isalnum|isalpha|isgreater|isgreaterequal|isgraph|isxdigit|isblank|ilogb|ilogbf|ilogbl|imaxdiv|imaxabs|div|difftime|_Exit|ungetc|ungetwc|pow|powf|powl|puts|putc|putchar|putwc|putwchar|perror|printf|erf|erfc|erfcf|erfcl|erff|erfl|exit|exp|exp2|exp2f|exp2l|expf|expl|expm1|expm1f|expm1l|vsscanf|vsnprintf|vscanf|vsprintf|vswscanf|vswprintf|vprintf|vfscanf|vfprintf|vfwscanf|vfwprintf|vwscanf|vwprintf|va_start|va_copy|va_end|va_arg|qsort|fscanf|fsetpos|fseek|fclose|ftell|fopen|fdim|fdimf|fdiml|fpclassify|fputs|fputc|fputws|fputwc|fprintf|feholdexcept|fesetenv|fesetexceptflag|fesetround|feclearexcept|fetestexcept|feof|feupdateenv|feraiseexcept|ferror|fegetenv|fegetexceptflag|fegetround|fflush|fwscanf|fwide|fwprintf|fwrite|floor|floorf|floorl|fabs|fabsf|fabsl|fgets|fgetc|fgetpos|fgetws|fgetwc|freopen|free|fread|frexp|frexpf|frexpl|fmin|fminf|fminl|fmod|fmodf|fmodl|fma|fmaf|fmal|fmax|fmaxf|fmaxl|ldiv|ldexp|ldexpf|ldexpl|longjmp|localtime|localeconv|log|log1p|log1pf|log1pl|log10|log10f|log10l|log2|log2f|log2l|logf|logl|logb|logbf|logbl|labs|lldiv|llabs|llrint|llrintf|llrintl|llround|llroundf|llroundl|lrint|lrintf|lrintl|lround|lroundf|lroundl|lgamma|lgammaf|lgammal|wscanf|wcsstr|wcsspn|wcsncpy|wcsncat|wcsncmp|wcscspn|wcschr|wcscoll|wcscpy|wcscat|wcscmp|wcstoimax|wcstod|wcstoul|wcstoull|wcstoumax|wcstok|wcstof|wcstol|wcstold|wcstoll|wcstombs|wcspbrk|wcsftime|wcslen|wcsrchr|wcsrtombs|wcsxfrm|wctob|wctomb|wcrtomb|wprintf|wmemset|wmemchr|wmemcpy|wmemcmp|wmemmove|assert|asctime|asin|asinh|asinhf|asinhl|asinf|asinl|acos|acosh|acoshf|acoshl|acosf|acosl|atoi|atof|atol|atoll|atexit|atan|atanh|atanhf|atanhl|atan2|atan2f|atan2l|atanf|atanl|abs|abort|gets|getc|getchar|getenv|getwc|getwchar|gmtime|rint|rintf|rintl|round|roundf|roundl|rename|realloc|rewind|remove|remquo|remquof|remquol|remainder|remainderf|remainderl|rand|raise|bsearch|btowc|modf|modff|modfl|memset|memchr|memcpy|memcmp|memmove|mktime|malloc|mbsinit|mbstowcs|mbsrtowcs|mbtowc|mblen|mbrtowc|mbrlen";
|
||||
var c_cppHighlightRules = function (extraKeywords) {
|
||||
var keywordControls = ("break|case|continue|default|do|else|for|goto|if|_Pragma|" +
|
||||
"return|switch|while|catch|operator|try|throw|using");
|
||||
var storageType = ("asm|__asm__|auto|bool|_Bool|char|_Complex|double|enum|float|" +
|
||||
"_Imaginary|int|int8_t|int16_t|int32_t|int64_t|long|short|signed|size_t|struct|typedef|uint8_t|uint16_t|uint32_t|uint64_t|union|unsigned|void|" +
|
||||
"class|wchar_t|template|char16_t|char32_t");
|
||||
var storageModifiers = ("const|extern|register|restrict|static|volatile|inline|private|" +
|
||||
"protected|public|friend|explicit|virtual|export|mutable|typename|" +
|
||||
"constexpr|new|delete|alignas|alignof|decltype|noexcept|thread_local");
|
||||
var keywordOperators = ("and|and_eq|bitand|bitor|compl|not|not_eq|or|or_eq|typeid|xor|xor_eq|" +
|
||||
"const_cast|dynamic_cast|reinterpret_cast|static_cast|sizeof|namespace");
|
||||
var builtinConstants = ("NULL|true|false|TRUE|FALSE|nullptr");
|
||||
var keywordMapper = this.$keywords = this.createKeywordMapper(Object.assign({
|
||||
"keyword.control": keywordControls,
|
||||
"storage.type": storageType,
|
||||
"storage.modifier": storageModifiers,
|
||||
"keyword.operator": keywordOperators,
|
||||
"variable.language": "this",
|
||||
"constant.language": builtinConstants,
|
||||
"support.function.C99.c": cFunctions
|
||||
}, extraKeywords), "identifier");
|
||||
var identifierRe = "[a-zA-Z\\$_\u00a1-\uffff][a-zA-Z\\d\\$_\u00a1-\uffff]*\\b";
|
||||
var escapeRe = /\\(?:['"?\\abfnrtv]|[0-7]{1,3}|x[a-fA-F\d]{2}|u[a-fA-F\d]{4}U[a-fA-F\d]{8}|.)/.source;
|
||||
var formatRe = "%"
|
||||
+ /(\d+\$)?/.source // field (argument #)
|
||||
+ /[#0\- +']*/.source // flags
|
||||
+ /[,;:_]?/.source // separator character (AltiVec)
|
||||
+ /((-?\d+)|\*(-?\d+\$)?)?/.source // minimum field width
|
||||
+ /(\.((-?\d+)|\*(-?\d+\$)?)?)?/.source // precision
|
||||
+ /(hh|h|ll|l|j|t|z|q|L|vh|vl|v|hv|hl)?/.source // length modifier
|
||||
+ /(\[[^"\]]+\]|[diouxXDOUeEfFgGaACcSspn%])/.source; // conversion type
|
||||
this.$rules = {
|
||||
"start": [
|
||||
{
|
||||
token: "comment",
|
||||
regex: "//$",
|
||||
next: "start"
|
||||
}, {
|
||||
token: "comment",
|
||||
regex: "//",
|
||||
next: "singleLineComment"
|
||||
},
|
||||
DocCommentHighlightRules.getStartRule("doc-start"),
|
||||
{
|
||||
token: "comment",
|
||||
regex: "\\/\\*",
|
||||
next: "comment"
|
||||
}, {
|
||||
token: "string",
|
||||
regex: "'(?:" + escapeRe + "|.)?'"
|
||||
}, {
|
||||
token: "string.start",
|
||||
regex: '"',
|
||||
stateName: "qqstring",
|
||||
next: [
|
||||
{ token: "string", regex: /\\\s*$/, next: "qqstring" },
|
||||
{ token: "constant.language.escape", regex: escapeRe },
|
||||
{ token: "constant.language.escape", regex: formatRe },
|
||||
{ token: "string.end", regex: '"|$', next: "start" },
|
||||
{ defaultToken: "string" }
|
||||
]
|
||||
}, {
|
||||
token: "string.start",
|
||||
regex: 'R"\\(',
|
||||
stateName: "rawString",
|
||||
next: [
|
||||
{ token: "string.end", regex: '\\)"', next: "start" },
|
||||
{ defaultToken: "string" }
|
||||
]
|
||||
}, {
|
||||
token: "constant.numeric",
|
||||
regex: "0[xX][0-9a-fA-F]+(L|l|UL|ul|u|U|F|f|ll|LL|ull|ULL)?\\b"
|
||||
}, {
|
||||
token: "constant.numeric",
|
||||
regex: "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?(L|l|UL|ul|u|U|F|f|ll|LL|ull|ULL)?\\b"
|
||||
}, {
|
||||
token: "keyword",
|
||||
regex: "#\\s*(?:include|import|pragma|line|define|undef)\\b",
|
||||
next: "directive"
|
||||
}, {
|
||||
token: "keyword",
|
||||
regex: "#\\s*(?:endif|if|ifdef|else|elif|ifndef)\\b"
|
||||
}, {
|
||||
token: keywordMapper,
|
||||
regex: "[a-zA-Z_$][a-zA-Z0-9_$]*"
|
||||
}, {
|
||||
token: "keyword.operator",
|
||||
regex: /--|\+\+|<<=|>>=|>>>=|<>|&&|\|\||\?:|[*%\/+\-&\^|~!<>=]=?/
|
||||
}, {
|
||||
token: "punctuation.operator",
|
||||
regex: "\\?|\\:|\\,|\\;|\\."
|
||||
}, {
|
||||
token: "paren.lparen",
|
||||
regex: "[[({]"
|
||||
}, {
|
||||
token: "paren.rparen",
|
||||
regex: "[\\])}]"
|
||||
}, {
|
||||
token: "text",
|
||||
regex: "\\s+"
|
||||
}
|
||||
],
|
||||
"comment": [
|
||||
{
|
||||
token: "comment",
|
||||
regex: "\\*\\/",
|
||||
next: "start"
|
||||
}, {
|
||||
defaultToken: "comment"
|
||||
}
|
||||
],
|
||||
"singleLineComment": [
|
||||
{
|
||||
token: "comment",
|
||||
regex: /\\$/,
|
||||
next: "singleLineComment"
|
||||
}, {
|
||||
token: "comment",
|
||||
regex: /$/,
|
||||
next: "start"
|
||||
}, {
|
||||
defaultToken: "comment"
|
||||
}
|
||||
],
|
||||
"directive": [
|
||||
{
|
||||
token: "constant.other.multiline",
|
||||
regex: /\\/
|
||||
},
|
||||
{
|
||||
token: "constant.other.multiline",
|
||||
regex: /.*\\/
|
||||
},
|
||||
{
|
||||
token: "constant.other",
|
||||
regex: "\\s*<.+?>",
|
||||
next: "start"
|
||||
},
|
||||
{
|
||||
token: "constant.other",
|
||||
regex: '\\s*["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]',
|
||||
next: "start"
|
||||
},
|
||||
{
|
||||
token: "constant.other",
|
||||
regex: "\\s*['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']",
|
||||
next: "start"
|
||||
},
|
||||
{
|
||||
token: "constant.other",
|
||||
regex: /[^\\\/]+/,
|
||||
next: "start"
|
||||
}
|
||||
]
|
||||
};
|
||||
this.embedRules(DocCommentHighlightRules, "doc-", [DocCommentHighlightRules.getEndRule("start")]);
|
||||
this.normalizeRules();
|
||||
};
|
||||
oop.inherits(c_cppHighlightRules, TextHighlightRules);
|
||||
exports.c_cppHighlightRules = c_cppHighlightRules;
|
||||
|
||||
});
|
||||
|
||||
ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"], function(require, exports, module){"use strict";
|
||||
var Range = require("../range").Range;
|
||||
var MatchingBraceOutdent = function () { };
|
||||
(function () {
|
||||
this.checkOutdent = function (line, input) {
|
||||
if (!/^\s+$/.test(line))
|
||||
return false;
|
||||
return /^\s*\}/.test(input);
|
||||
};
|
||||
this.autoOutdent = function (doc, row) {
|
||||
var line = doc.getLine(row);
|
||||
var match = line.match(/^(\s*\})/);
|
||||
if (!match)
|
||||
return 0;
|
||||
var column = match[1].length;
|
||||
var openBracePos = doc.findMatchingBracket({ row: row, column: column });
|
||||
if (!openBracePos || openBracePos.row == row)
|
||||
return 0;
|
||||
var indent = this.$getIndent(doc.getLine(openBracePos.row));
|
||||
doc.replace(new Range(row, 0, row, column - 1), indent);
|
||||
};
|
||||
this.$getIndent = function (line) {
|
||||
return line.match(/^\s*/)[0];
|
||||
};
|
||||
}).call(MatchingBraceOutdent.prototype);
|
||||
exports.MatchingBraceOutdent = MatchingBraceOutdent;
|
||||
|
||||
});
|
||||
|
||||
ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"], function(require, exports, module){"use strict";
|
||||
var oop = require("../../lib/oop");
|
||||
var Range = require("../../range").Range;
|
||||
var BaseFoldMode = require("./fold_mode").FoldMode;
|
||||
var FoldMode = exports.FoldMode = function (commentRegex) {
|
||||
if (commentRegex) {
|
||||
this.foldingStartMarker = new RegExp(this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start));
|
||||
this.foldingStopMarker = new RegExp(this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end));
|
||||
}
|
||||
};
|
||||
oop.inherits(FoldMode, BaseFoldMode);
|
||||
(function () {
|
||||
this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/;
|
||||
this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/;
|
||||
this.singleLineBlockCommentRe = /^\s*(\/\*).*\*\/\s*$/;
|
||||
this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/;
|
||||
this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/;
|
||||
this._getFoldWidgetBase = this.getFoldWidget;
|
||||
this.getFoldWidget = function (session, foldStyle, row) {
|
||||
var line = session.getLine(row);
|
||||
if (this.singleLineBlockCommentRe.test(line)) {
|
||||
if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line))
|
||||
return "";
|
||||
}
|
||||
var fw = this._getFoldWidgetBase(session, foldStyle, row);
|
||||
if (!fw && this.startRegionRe.test(line))
|
||||
return "start"; // lineCommentRegionStart
|
||||
return fw;
|
||||
};
|
||||
this.getFoldWidgetRange = function (session, foldStyle, row, forceMultiline) {
|
||||
var line = session.getLine(row);
|
||||
if (this.startRegionRe.test(line))
|
||||
return this.getCommentRegionBlock(session, line, row);
|
||||
var match = line.match(this.foldingStartMarker);
|
||||
if (match) {
|
||||
var i = match.index;
|
||||
if (match[1])
|
||||
return this.openingBracketBlock(session, match[1], row, i);
|
||||
var range = session.getCommentFoldRange(row, i + match[0].length, 1);
|
||||
if (range && !range.isMultiLine()) {
|
||||
if (forceMultiline) {
|
||||
range = this.getSectionRange(session, row);
|
||||
}
|
||||
else if (foldStyle != "all")
|
||||
range = null;
|
||||
}
|
||||
return range;
|
||||
}
|
||||
if (foldStyle === "markbegin")
|
||||
return;
|
||||
var match = line.match(this.foldingStopMarker);
|
||||
if (match) {
|
||||
var i = match.index + match[0].length;
|
||||
if (match[1])
|
||||
return this.closingBracketBlock(session, match[1], row, i);
|
||||
return session.getCommentFoldRange(row, i, -1);
|
||||
}
|
||||
};
|
||||
this.getSectionRange = function (session, row) {
|
||||
var line = session.getLine(row);
|
||||
var startIndent = line.search(/\S/);
|
||||
var startRow = row;
|
||||
var startColumn = line.length;
|
||||
row = row + 1;
|
||||
var endRow = row;
|
||||
var maxRow = session.getLength();
|
||||
while (++row < maxRow) {
|
||||
line = session.getLine(row);
|
||||
var indent = line.search(/\S/);
|
||||
if (indent === -1)
|
||||
continue;
|
||||
if (startIndent > indent)
|
||||
break;
|
||||
var subRange = this.getFoldWidgetRange(session, "all", row);
|
||||
if (subRange) {
|
||||
if (subRange.start.row <= startRow) {
|
||||
break;
|
||||
}
|
||||
else if (subRange.isMultiLine()) {
|
||||
row = subRange.end.row;
|
||||
}
|
||||
else if (startIndent == indent) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
endRow = row;
|
||||
}
|
||||
return new Range(startRow, startColumn, endRow, session.getLine(endRow).length);
|
||||
};
|
||||
this.getCommentRegionBlock = function (session, line, row) {
|
||||
var startColumn = line.search(/\s*$/);
|
||||
var maxRow = session.getLength();
|
||||
var startRow = row;
|
||||
var re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/;
|
||||
var depth = 1;
|
||||
while (++row < maxRow) {
|
||||
line = session.getLine(row);
|
||||
var m = re.exec(line);
|
||||
if (!m)
|
||||
continue;
|
||||
if (m[1])
|
||||
depth--;
|
||||
else
|
||||
depth++;
|
||||
if (!depth)
|
||||
break;
|
||||
}
|
||||
var endRow = row;
|
||||
if (endRow > startRow) {
|
||||
return new Range(startRow, startColumn, endRow, line.length);
|
||||
}
|
||||
};
|
||||
}).call(FoldMode.prototype);
|
||||
|
||||
});
|
||||
|
||||
ace.define("ace/mode/c_cpp",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/c_cpp_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/folding/cstyle"], function(require, exports, module){"use strict";
|
||||
var oop = require("../lib/oop");
|
||||
var TextMode = require("./text").Mode;
|
||||
var c_cppHighlightRules = require("./c_cpp_highlight_rules").c_cppHighlightRules;
|
||||
var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
|
||||
var CStyleFoldMode = require("./folding/cstyle").FoldMode;
|
||||
var Mode = function () {
|
||||
this.HighlightRules = c_cppHighlightRules;
|
||||
this.$outdent = new MatchingBraceOutdent();
|
||||
this.$behaviour = this.$defaultBehaviour;
|
||||
this.foldingRules = new CStyleFoldMode();
|
||||
};
|
||||
oop.inherits(Mode, TextMode);
|
||||
(function () {
|
||||
this.lineCommentStart = "//";
|
||||
this.blockComment = { start: "/*", end: "*/" };
|
||||
this.getNextLineIndent = function (state, line, tab) {
|
||||
var indent = this.$getIndent(line);
|
||||
var tokenizedLine = this.getTokenizer().getLineTokens(line, state);
|
||||
var tokens = tokenizedLine.tokens;
|
||||
var endState = tokenizedLine.state;
|
||||
if (tokens.length && tokens[tokens.length - 1].type == "comment") {
|
||||
return indent;
|
||||
}
|
||||
if (state == "start") {
|
||||
var match = line.match(/^.*[\{\(\[]\s*$/);
|
||||
if (match) {
|
||||
indent += tab;
|
||||
}
|
||||
}
|
||||
else if (state == "doc-start") {
|
||||
if (endState == "start") {
|
||||
return "";
|
||||
}
|
||||
var match = line.match(/^\s*(\/?)\*/);
|
||||
if (match) {
|
||||
if (match[1]) {
|
||||
indent += " ";
|
||||
}
|
||||
indent += "* ";
|
||||
}
|
||||
}
|
||||
return indent;
|
||||
};
|
||||
this.checkOutdent = function (state, line, input) {
|
||||
return this.$outdent.checkOutdent(line, input);
|
||||
};
|
||||
this.autoOutdent = function (state, doc, row) {
|
||||
this.$outdent.autoOutdent(doc, row);
|
||||
};
|
||||
this.$id = "ace/mode/c_cpp";
|
||||
this.snippetFileId = "ace/snippets/c_cpp";
|
||||
}).call(Mode.prototype);
|
||||
exports.Mode = Mode;
|
||||
|
||||
});
|
||||
|
||||
ace.define("ace/mode/nix_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module){"use strict";
|
||||
var oop = require("../lib/oop");
|
||||
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
|
||||
var NixHighlightRules = function () {
|
||||
var constantLanguage = "true|false";
|
||||
var keywordControl = "with|import|if|else|then|inherit";
|
||||
var keywordDeclaration = "let|in|rec";
|
||||
var keywordMapper = this.createKeywordMapper({
|
||||
"constant.language.nix": constantLanguage,
|
||||
"keyword.control.nix": keywordControl,
|
||||
"keyword.declaration.nix": keywordDeclaration
|
||||
}, "identifier");
|
||||
this.$rules = {
|
||||
"start": [{
|
||||
token: "comment",
|
||||
regex: /#.*$/
|
||||
}, {
|
||||
token: "comment",
|
||||
regex: /\/\*/,
|
||||
next: "comment"
|
||||
}, {
|
||||
token: "constant",
|
||||
regex: "<[^>]+>"
|
||||
}, {
|
||||
regex: "(==|!=|<=?|>=?)",
|
||||
token: ["keyword.operator.comparison.nix"]
|
||||
}, {
|
||||
regex: "((?:[+*/%-]|\\~)=)",
|
||||
token: ["keyword.operator.assignment.arithmetic.nix"]
|
||||
}, {
|
||||
regex: "=",
|
||||
token: "keyword.operator.assignment.nix"
|
||||
}, {
|
||||
token: "string",
|
||||
regex: "''",
|
||||
next: "qqdoc"
|
||||
}, {
|
||||
token: "string",
|
||||
regex: "'",
|
||||
next: "qstring"
|
||||
}, {
|
||||
token: "string",
|
||||
regex: '"',
|
||||
push: "qqstring"
|
||||
}, {
|
||||
token: "constant.numeric",
|
||||
regex: "0[xX][0-9a-fA-F]+\\b"
|
||||
}, {
|
||||
token: "constant.numeric",
|
||||
regex: "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
|
||||
}, {
|
||||
token: keywordMapper,
|
||||
regex: "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
|
||||
}, {
|
||||
regex: "}",
|
||||
token: function (val, start, stack) {
|
||||
return stack[1] && stack[1].charAt(0) == "q" ? "constant.language.escape" : "text";
|
||||
},
|
||||
next: "pop"
|
||||
}],
|
||||
"comment": [{
|
||||
token: "comment",
|
||||
regex: "\\*\\/",
|
||||
next: "start"
|
||||
}, {
|
||||
defaultToken: "comment"
|
||||
}],
|
||||
"qqdoc": [
|
||||
{
|
||||
token: "constant.language.escape",
|
||||
regex: /\$\{/,
|
||||
push: "start"
|
||||
}, {
|
||||
token: "string",
|
||||
regex: "''",
|
||||
next: "pop"
|
||||
}, {
|
||||
defaultToken: "string"
|
||||
}
|
||||
],
|
||||
"qqstring": [
|
||||
{
|
||||
token: "constant.language.escape",
|
||||
regex: /\$\{/,
|
||||
push: "start"
|
||||
}, {
|
||||
token: "string",
|
||||
regex: '"',
|
||||
next: "pop"
|
||||
}, {
|
||||
defaultToken: "string"
|
||||
}
|
||||
],
|
||||
"qstring": [
|
||||
{
|
||||
token: "constant.language.escape",
|
||||
regex: /\$\{/,
|
||||
push: "start"
|
||||
}, {
|
||||
token: "string",
|
||||
regex: "'",
|
||||
next: "pop"
|
||||
}, {
|
||||
defaultToken: "string"
|
||||
}
|
||||
]
|
||||
};
|
||||
this.normalizeRules();
|
||||
};
|
||||
oop.inherits(NixHighlightRules, TextHighlightRules);
|
||||
exports.NixHighlightRules = NixHighlightRules;
|
||||
|
||||
});
|
||||
|
||||
ace.define("ace/mode/nix",["require","exports","module","ace/lib/oop","ace/mode/c_cpp","ace/mode/nix_highlight_rules","ace/mode/folding/cstyle"], function(require, exports, module){/*
|
||||
THIS FILE WAS AUTOGENERATED BY mode.tmpl.js
|
||||
*/
|
||||
"use strict";
|
||||
var oop = require("../lib/oop");
|
||||
var CMode = require("./c_cpp").Mode;
|
||||
var NixHighlightRules = require("./nix_highlight_rules").NixHighlightRules;
|
||||
var CStyleFoldMode = require("./folding/cstyle").FoldMode;
|
||||
var Mode = function () {
|
||||
CMode.call(this);
|
||||
this.HighlightRules = NixHighlightRules;
|
||||
this.foldingRules = new CStyleFoldMode();
|
||||
this.$behaviour = this.$defaultBehaviour;
|
||||
};
|
||||
oop.inherits(Mode, CMode);
|
||||
(function () {
|
||||
this.lineCommentStart = "#";
|
||||
this.blockComment = { start: "/*", end: "*/" };
|
||||
this.$id = "ace/mode/nix";
|
||||
}).call(Mode.prototype);
|
||||
exports.Mode = Mode;
|
||||
|
||||
}); (function() {
|
||||
ace.require(["ace/mode/nix"], function(m) {
|
||||
if (typeof module == "object" && typeof exports == "object" && module) {
|
||||
module.exports = m;
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
ace.define("ace/theme/dracula-css",["require","exports","module"], function(require, exports, module){module.exports = "/*\n * Copyright \u00A9 2017 Zeno Rocha <hi@zenorocha.com>\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \u201CSoftware\u201D), 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:\n *\n * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \u201CAS IS\u201D, 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.\n */\n\n.ace-dracula .ace_gutter {\n background: #282a36;\n color: rgb(144,145,148)\n}\n\n.ace-dracula .ace_print-margin {\n width: 1px;\n background: #44475a\n}\n\n.ace-dracula {\n background-color: #282a36;\n color: #f8f8f2\n}\n\n.ace-dracula .ace_cursor {\n color: #f8f8f0\n}\n\n.ace-dracula .ace_marker-layer .ace_selection {\n background: #44475a\n}\n\n.ace-dracula.ace_multiselect .ace_selection.ace_start {\n box-shadow: 0 0 3px 0px #282a36;\n border-radius: 2px\n}\n\n.ace-dracula .ace_marker-layer .ace_step {\n background: rgb(198, 219, 174)\n}\n\n.ace-dracula .ace_marker-layer .ace_bracket {\n margin: -1px 0 0 -1px;\n border: 1px solid #a29709\n}\n\n.ace-dracula .ace_marker-layer .ace_active-line {\n background: #44475a\n}\n\n.ace-dracula .ace_gutter-active-line {\n background-color: #44475a\n}\n\n.ace-dracula .ace_marker-layer .ace_selected-word {\n box-shadow: 0px 0px 0px 1px #a29709;\n border-radius: 3px;\n}\n\n.ace-dracula .ace_fold {\n background-color: #50fa7b;\n border-color: #f8f8f2\n}\n\n.ace-dracula .ace_keyword {\n color: #ff79c6\n}\n\n.ace-dracula .ace_constant.ace_language {\n color: #bd93f9\n}\n\n.ace-dracula .ace_constant.ace_numeric {\n color: #bd93f9\n}\n\n.ace-dracula .ace_constant.ace_character {\n color: #bd93f9\n}\n\n.ace-dracula .ace_constant.ace_character.ace_escape {\n color: #ff79c6\n}\n\n.ace-dracula .ace_constant.ace_other {\n color: #bd93f9\n}\n\n.ace-dracula .ace_support.ace_function {\n color: #8be9fd\n}\n\n.ace-dracula .ace_support.ace_constant {\n color: #6be5fd\n}\n\n.ace-dracula .ace_support.ace_class {\n font-style: italic;\n color: #66d9ef\n}\n\n.ace-dracula .ace_support.ace_type {\n font-style: italic;\n color: #66d9ef\n}\n\n.ace-dracula .ace_storage {\n color: #ff79c6\n}\n\n.ace-dracula .ace_storage.ace_type {\n font-style: italic;\n color: #8be9fd\n}\n\n.ace-dracula .ace_invalid {\n color: #F8F8F0;\n background-color: #ff79c6\n}\n\n.ace-dracula .ace_invalid.ace_deprecated {\n color: #F8F8F0;\n background-color: #bd93f9\n}\n\n.ace-dracula .ace_string {\n color: #f1fa8c\n}\n\n.ace-dracula .ace_comment {\n color: #6272a4\n}\n\n.ace-dracula .ace_variable {\n color: #50fa7b\n}\n\n.ace-dracula .ace_variable.ace_parameter {\n font-style: italic;\n color: #ffb86c\n}\n\n.ace-dracula .ace_entity.ace_other.ace_attribute-name {\n color: #50fa7b\n}\n\n.ace-dracula .ace_entity.ace_name.ace_function {\n color: #50fa7b\n}\n\n.ace-dracula .ace_entity.ace_name.ace_tag {\n color: #ff79c6\n}\n.ace-dracula .ace_invisible {\n color: #626680;\n}\n\n.ace-dracula .ace_indent-guide {\n background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYHB3d/8PAAOIAdULw8qMAAAAAElFTkSuQmCC) right repeat-y\n}\n\n.ace-dracula .ace_indent-guide-active {\n background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACAQMAAACjTyRkAAAABlBMVEUAAADCwsK76u2xAAAAAXRSTlMAQObYZgAAAAxJREFUCNdjYGBoAAAAhACBGFbxzQAAAABJRU5ErkJggg==\") right repeat-y;\n}\n";
|
||||
|
||||
});
|
||||
|
||||
ace.define("ace/theme/dracula",["require","exports","module","ace/theme/dracula-css","ace/lib/dom"], function(require, exports, module){exports.isDark = true;
|
||||
exports.cssClass = "ace-dracula";
|
||||
exports.cssText = require("./dracula-css");
|
||||
exports.$selectionColorConflict = true;
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass, false);
|
||||
|
||||
}); (function() {
|
||||
ace.require(["ace/theme/dracula"], function(m) {
|
||||
if (typeof module == "object" && typeof exports == "object" && module) {
|
||||
module.exports = m;
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
|
@ -8,123 +8,7 @@
|
|||
<link rel="preconnect" href="https://rsms.me/">
|
||||
<link rel="stylesheet" href="https://rsms.me/inter/inter.css">
|
||||
<link rel="stylesheet" href="https://iosevka-webfonts.github.io/iosevka/iosevka.css">
|
||||
<style>
|
||||
:root {
|
||||
--background: #13131E;
|
||||
--bg-raised: #171625;
|
||||
--text: #E0DFFE;
|
||||
|
||||
--link: #FFC53D;
|
||||
--link-hover: #e28d0e;
|
||||
|
||||
--button-color: #B1A9FF;
|
||||
--button-bg: #202248;
|
||||
--button-border: #5B5BD6;
|
||||
--button-bg-hover: #7E451D;
|
||||
|
||||
background-color: var(--background);
|
||||
color: var(--text);
|
||||
font-family: Inter, sans-serif;
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: "Iosevka Web", monospace;
|
||||
font-size: 11pt;
|
||||
}
|
||||
|
||||
a[href],
|
||||
a[href]:visited {
|
||||
color: var(--link);
|
||||
|
||||
&:hover {
|
||||
color: var(--link-hover);
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
nav {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
background-color: var(--bg-raised);
|
||||
|
||||
& a {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
text-decoration: none;
|
||||
padding: 5px 8px;
|
||||
justify-content: center;
|
||||
max-width: 100px;
|
||||
box-shadow: inset 0 -2px var(--button-bg);
|
||||
font-size: 11pt;
|
||||
text-transform: uppercase;
|
||||
|
||||
&[href],
|
||||
&[href]:visited {
|
||||
color: var(--button-color);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: #1E160F;
|
||||
box-shadow: inset 0 -2px var(--button-bg-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
main {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
body,
|
||||
html {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: var(--button-bg);
|
||||
color: var(--button-color);
|
||||
border: 1px solid var(--button-border);
|
||||
padding: 4px 8px;
|
||||
border-radius: 3px;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background-color: var(--button-bg-hover);
|
||||
color: var(--link-hover);
|
||||
border-color: var(--link-hover);
|
||||
}
|
||||
}
|
||||
|
||||
table.table {
|
||||
background-color: var(--bg-raised);
|
||||
border: 3px solid #5958B1;
|
||||
border-radius: 3px;
|
||||
|
||||
& th,
|
||||
& td {
|
||||
padding: 3px 5px;
|
||||
}
|
||||
|
||||
& th {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
& thead {
|
||||
background-color: #202248;
|
||||
}
|
||||
}
|
||||
|
||||
.full-width {
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="/static/css/screen.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
</section>
|
||||
</main>
|
||||
|
||||
<link rel="stylesheet" href="/static/css/editor.css" />
|
||||
<style scoped>
|
||||
main {
|
||||
display: flex;
|
||||
|
@ -84,48 +85,6 @@
|
|||
color: #E796F3;
|
||||
}
|
||||
|
||||
.editor form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5ch;
|
||||
|
||||
& .row {
|
||||
display: flex;
|
||||
gap: 0.5ch;
|
||||
|
||||
& input,
|
||||
& button {
|
||||
font-size: 13pt;
|
||||
padding: 6px 10px;
|
||||
|
||||
&.wide {
|
||||
padding: 6px 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
input,
|
||||
textarea {
|
||||
border: 1px solid #5958B1;
|
||||
border-radius: 3px;
|
||||
background-color: var(--bg-raised);
|
||||
color: var(--text);
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
#editor {
|
||||
border-width: 3px;
|
||||
min-height: 50vh;
|
||||
}
|
||||
|
||||
.ace_editor {
|
||||
min-height: 50vh;
|
||||
border: 3px solid #5958B1;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
|
@ -141,23 +100,11 @@
|
|||
}
|
||||
</style>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.31.2/ace.min.js"
|
||||
integrity="sha512-4qIbBlcJOvbOmEB50FfnviJ9jOCen2yhi4skodkbTLU/uJJdULPxlX2R9Enf1oOBleUK9KD3fGmMcnItFQdNeA=="
|
||||
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
<script>
|
||||
var editor = ace.edit("editor");
|
||||
editor.setTheme("ace/theme/dracula");
|
||||
editor.setOptions({
|
||||
fontFamily: "Iosevka Web",
|
||||
fontSize: "12pt"
|
||||
});
|
||||
editor.getSession().setUseWrapMode(true);
|
||||
editor.setKeyboardHandler("ace/keyboard/vim");
|
||||
editor.session.setMode("ace/mode/nix");
|
||||
|
||||
document.getElementById("editor-form").addEventListener("formdata", (ev) => {
|
||||
ev.formData.set("source", editor.getValue());
|
||||
});
|
||||
<script type="module">
|
||||
import Editor from "/static/js/ace.mjs";
|
||||
|
||||
new Editor("editor");
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
|
@ -3,4 +3,36 @@
|
|||
{% block title %}New stack{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<main>
|
||||
<header>
|
||||
<h1>New stack</h1>
|
||||
</header>
|
||||
<section class="editor">
|
||||
<form method="POST" action="./edit" id="editor-form">
|
||||
<div class="row">
|
||||
<input style="flex:1" name="name" type="text" placeholder="Stack name" />
|
||||
</div>
|
||||
<textarea name="source" id="editor">{}</textarea>
|
||||
<div class="row">
|
||||
<button type="submit">Create & Deploy</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<link rel="stylesheet" href="/static/css/editor.css" />
|
||||
<style scoped>
|
||||
main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="module">
|
||||
import Editor from "/static/js/ace.mjs";
|
||||
|
||||
new Editor("editor");
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
Loading…
Reference in New Issue