editor first run

This commit is contained in:
EugeneTes
2026-02-04 14:20:08 +01:00
parent 2748c6586e
commit eca5ced38a
33 changed files with 2322 additions and 5 deletions

View File

@@ -0,0 +1,180 @@
h1:focus {
outline: none;
}
html, body {
margin: 0;
padding: 0;
height: 100%;
overflow: hidden;
}
.editor-container {
display: flex;
flex-direction: column;
height: 100vh;
}
.toolbar {
display: flex;
gap: 4px;
padding: 6px 8px;
background: #2d2d2d;
border-bottom: 1px solid #404040;
flex-shrink: 0;
}
.toolbar-btn {
padding: 4px 14px;
background: #3c3c3c;
color: #cccccc;
border: 1px solid #555;
border-radius: 3px;
cursor: pointer;
font-size: 13px;
}
.toolbar-btn:hover {
background: #505050;
}
.toolbar-separator {
width: 1px;
background: #555;
margin: 2px 6px;
}
.json-indicator {
display: inline-flex;
align-items: center;
padding: 2px 10px;
background: #2b4a3e;
color: #4EC9B0;
border: 1px solid #3a6b57;
border-radius: 3px;
font-size: 12px;
max-width: 200px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.split-pane {
display: flex;
flex: 1;
min-height: 0;
}
.pane {
display: flex;
flex-direction: column;
min-width: 0;
}
.pane-editor {
flex: 1;
border-right: 1px solid #404040;
}
.pane-preview {
flex: 1;
background: #1e1e1e;
}
.pane-header {
padding: 4px 10px;
background: #252526;
color: #888;
font-size: 12px;
text-transform: uppercase;
letter-spacing: 0.5px;
border-bottom: 1px solid #404040;
flex-shrink: 0;
}
#my-editor-id {
flex: 1;
min-height: 0;
}
.preview-content {
flex: 1;
padding: 16px;
overflow: auto;
color: #cccccc;
}
.valid.modified:not([type=checkbox]) {
outline: 1px solid #26b050;
}
.invalid {
outline: 1px solid #e50000;
}
.validation-message {
color: #e50000;
}
#blazor-error-ui {
color-scheme: light only;
background: lightyellow;
bottom: 0;
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
box-sizing: border-box;
display: none;
left: 0;
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
position: fixed;
width: 100%;
z-index: 1000;
}
#blazor-error-ui .dismiss {
cursor: pointer;
position: absolute;
right: 0.75rem;
top: 0.5rem;
}
.blazor-error-boundary {
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
padding: 1rem 1rem 1rem 3.7rem;
color: white;
}
.blazor-error-boundary::after {
content: "An error has occurred."
}
.darker-border-checkbox.form-check-input {
border-color: #929292;
}
.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
color: var(--bs-secondary-color);
text-align: end;
}
.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
text-align: start;
}
.status-bar-safe-area {
display: none;
}
@supports (-webkit-touch-callout: none) {
.status-bar-safe-area {
display: flex;
position: sticky;
top: 0;
height: env(safe-area-inset-top);
background-color: #f7f7f7;
width: 100%;
z-index: 1;
}
.flex-column, .navbar-brand {
padding-left: env(safe-area-inset-left);
}
}

View File

@@ -0,0 +1,33 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
<title>Inspectron.PrintServer.TemplateEditor</title>
<base href="/" />
<link rel="stylesheet" href="app.css" />
<link rel="stylesheet" href="Inspectron.PrintServer.TemplateEditor.styles.css" />
<link rel="icon" href="data:,">
<script src="_content/BlazorMonaco/jsInterop.js"></script>
<script src="_content/BlazorMonaco/lib/monaco-editor/min/vs/loader.js"></script>
<script src="_content/BlazorMonaco/lib/monaco-editor/min/vs/editor/editor.main.js"></script>
<script src="receiptLanguage.js"></script>
</head>
<body>
<div class="status-bar-safe-area"></div>
<div id="app">Loading...</div>
<div id="blazor-error-ui" data-nosnippet>
An unhandled error has occurred.
<a href="." class="reload">Reload</a>
<span class="dismiss">🗙</span>
</div>
<script src="_framework/blazor.webview.js" autostart="false"></script>
</body>
</html>

View File

@@ -0,0 +1,158 @@
window.receiptLanguage = {
_registered: false,
register: function () {
if (this._registered) return;
this._registered = true;
monaco.languages.register({ id: 'receipt-xml' });
monaco.languages.setLanguageConfiguration('receipt-xml', {
comments: {
blockComment: ['<!--', '-->']
},
brackets: [
['<', '>'],
['{{', '}}']
],
autoClosingPairs: [
{ open: '<', close: '>' },
{ open: '{{', close: '}}' },
{ open: '"', close: '"' },
{ open: "'", close: "'" }
],
surroundingPairs: [
{ open: '<', close: '>' },
{ open: '"', close: '"' },
{ open: "'", close: "'" }
]
});
var knownElements = [
'receipt', 'line', 'columns', 'row', 'col', 'separator',
'cut', 'feed', 'table', 'foreach', 'if', 'else'
];
monaco.languages.setMonarchTokensProvider('receipt-xml', {
knownElements: knownElements,
tokenizer: {
root: [
// Expression open
[/\{\{/, { token: 'delimiter.expression', next: '@expression' }],
// XML comment
[/<!--/, { token: 'comment', next: '@comment' }],
// Closing tag
[/<\//, { token: 'delimiter.tag', next: '@closingTag' }],
// Self-closing or opening tag
[/</, { token: 'delimiter.tag', next: '@openingTag' }],
// Plain text
[/[^<{]+/, 'text']
],
expression: [
[/\}\}/, { token: 'delimiter.expression', next: '@pop' }],
[/\$index|\$first|\$last/, 'variable.special'],
[/:[^}]+/, 'string.format'],
[/[a-zA-Z_][\w]*(?:\.[a-zA-Z_][\w]*)*/, 'variable.property'],
[/./, 'variable.property']
],
openingTag: [
// Match element name
[/([a-zA-Z][\w-]*)/, {
cases: {
'@knownElements': { token: 'tag.element', next: '@tagAttributes' },
'@default': { token: 'tag.unknown', next: '@tagAttributes' }
}
}],
[/>/, { token: 'delimiter.tag', next: '@pop' }]
],
closingTag: [
[/([a-zA-Z][\w-]*)/, {
cases: {
'@knownElements': 'tag.element',
'@default': 'tag.unknown'
}
}],
[/>/, { token: 'delimiter.tag', next: '@pop' }],
[/\s+/, '']
],
tagAttributes: [
// Self-closing
[/\/>/, { token: 'delimiter.tag', next: '@popall' }],
// Close tag
[/>/, { token: 'delimiter.tag', next: '@popall' }],
// Attribute name
[/[a-zA-Z_][\w-]*/, 'attribute.name'],
// Equals sign
[/=/, 'delimiter'],
// Quoted attribute values
[/"/, { token: 'attribute.value.delimiter', next: '@attrValueDouble' }],
[/'/, { token: 'attribute.value.delimiter', next: '@attrValueSingle' }],
// Whitespace
[/\s+/, '']
],
attrValueDouble: [
[/\{\{/, { token: 'delimiter.expression', next: '@expression' }],
[/"/, { token: 'attribute.value.delimiter', next: '@pop' }],
[/[^"{]+/, 'attribute.value']
],
attrValueSingle: [
[/\{\{/, { token: 'delimiter.expression', next: '@expression' }],
[/'/, { token: 'attribute.value.delimiter', next: '@pop' }],
[/[^'{]+/, 'attribute.value']
],
comment: [
[/-->/, { token: 'comment', next: '@pop' }],
[/./, 'comment']
]
}
});
},
defineTheme: function () {
monaco.editor.defineTheme('receipt-dark', {
base: 'vs-dark',
inherit: true,
rules: [
{ token: 'tag.element', foreground: '569CD6', fontStyle: 'bold' },
{ token: 'tag.unknown', foreground: 'F44747' },
{ token: 'attribute.name', foreground: '9CDCFE' },
{ token: 'attribute.value', foreground: 'CE9178' },
{ token: 'attribute.value.delimiter', foreground: 'CE9178' },
{ token: 'delimiter.tag', foreground: '808080' },
{ token: 'delimiter', foreground: '808080' },
{ token: 'delimiter.expression', foreground: 'DCDCAA', fontStyle: 'bold' },
{ token: 'variable.property', foreground: '4EC9B0' },
{ token: 'variable.special', foreground: 'C586C0', fontStyle: 'italic' },
{ token: 'string.format', foreground: 'D7BA7D' },
{ token: 'comment', foreground: '6A9955', fontStyle: 'italic' },
{ token: 'text', foreground: 'D4D4D4' }
],
colors: {}
});
},
getEditorContent: function (editorId) {
var editor = blazorMonaco.editor.getEditorById(editorId);
if (editor) {
return editor.getValue();
}
return '';
}
};