kdl-org.github.io/static/play/play.js

162 lines
5.0 KiB
JavaScript

import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker.js?url'
import * as monaco from 'monaco-editor/esm/vs/editor/editor.main.js'
import * as KDL from "@bgotink/kdl";
import nordTheme from 'monaco-themes/themes/Nord.json'
import * as KDLMonarch from './kdl.monarch'
self.MonacoEnvironment = {
getWorkerUrl: function (moduleId, label) {
return EditorWorker
}
}
monaco.languages.register({ id: 'kdl' })
monaco.languages.setMonarchTokensProvider('kdl', KDLMonarch.language)
monaco.languages.setLanguageConfiguration('kdl', KDLMonarch.config)
monaco.editor.defineTheme('nord', nordTheme)
monaco.editor.setTheme('nord')
function addTag(el, tag) {
if (!tag) return
const tagEl = document.createElement('span')
tagEl.classList.add('tag')
tagEl.textContent = tag
el.append(tagEl)
}
function buildValue(value) {
const valueEl = document.createElement('span')
if (value === null) {
valueEl.textContent = "null"
valueEl.classList.add('null')
} else if (value === true || value === false) {
valueEl.textContent = value ? 'true' : 'false'
valueEl.classList.add('boolean')
} else if (typeof value === "string") {
valueEl.textContent = JSON.stringify(value)
valueEl.classList.add('string')
} else {
valueEl.textContent = value.toString()
valueEl.classList.add('number')
}
return valueEl
}
/**
* @param {KDL.Node} node
* @returns {HTMLElement}
*/
function buildNodeTree(node) {
const nodeEl = document.createElement('div')
nodeEl.classList.add('node')
nodeEl.classList.add('open')
const nameEl = document.createElement('button')
nameEl.addEventListener('click', () => nodeEl.classList.toggle('open'))
nameEl.classList.add('name')
addTag(nameEl, node.getTag())
nameEl.append(document.createTextNode(node.getName()))
nodeEl.append(nameEl)
const contentEl = document.createElement('ul')
contentEl.classList.add('content')
node.entries.forEach((entry) => {
if (entry.name === null) {
const valueEl = document.createElement('li')
valueEl.classList.add('value')
addTag(valueEl, entry.getTag())
valueEl.append(buildValue(entry.getValue()))
contentEl.append(valueEl)
} else {
const propEl = document.createElement('li')
propEl.classList.add('property')
const keyEl = document.createElement('span')
keyEl.classList.add('key')
keyEl.textContent = entry.getName()
propEl.append(keyEl)
addTag(propEl, entry.getTag())
propEl.append(buildValue(entry.getValue()))
contentEl.append(propEl)
}
})
node.children?.nodes.forEach(child => {
contentEl.append(buildNodeTree(child))
})
nodeEl.append(contentEl)
return nodeEl
}
addEventListener("DOMContentLoaded", (event) => {
const editor = monaco.editor.create(document.getElementById('input'), {
value: 'foo 1 "two" three=(decimal)0xff {\n (thing)bar #true #false #null\n}',
language: 'kdl',
scrollBeyondLastLine: false,
minimap: { enabled: false },
fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace',
fontSize: 16,
automaticLayout: true
})
const model = editor.getModel()
const output = document.getElementById('output')
function parse() {
const markers = []
try {
let document = KDL.parse(model.getValue())
output.classList.remove('error')
output.innerHTML = ''
document.nodes.forEach(node => {
output.append(buildNodeTree(node))
})
} catch (error) {
output.classList.add('error')
if (error instanceof KDL.InvalidKdlError) {
markers.push({
message: error.message,
severity: monaco.MarkerSeverity.Error,
startLineNumber: error.token?.start.line,
startColumn: error.token?.start.column,
endLineNumber: error.token?.end.line,
endColumn: error.token?.end.column,
})
} else if (typeof AggregateError === 'function' && error instanceof AggregateError) {
for (const suberror of error.errors) {
if (suberror instanceof KDL.InvalidKdlError) {
markers.push({
message: suberror.message,
severity: monaco.MarkerSeverity.Error,
startLineNumber: suberror.token?.start.line,
startColumn: suberror.token?.start.column,
endLineNumber: suberror.token?.end.line,
endColumn: suberror.token?.end.column,
})
} else {
console.error(suberror);
markers.push({
message: "Failed to parse KDL",
severity: monaco.MarkerSeverity.Error,
startLineNumber: 1,
startColumn: 1,
})
}
}
} else {
console.error(error)
markers.push({
message: "Failed to parse KDL",
severity: monaco.MarkerSeverity.Error,
startLineNumber: 1,
startColumn: 1,
})
}
}
monaco.editor.setModelMarkers(model, "owner", markers)
}
model.onDidChangeContent(parse)
parse()
})