143 lines
4.2 KiB
JavaScript
143 lines
4.2 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) {
|
|
for (const detail of error.flat()) {
|
|
markers.push({
|
|
message: detail.message,
|
|
severity: monaco.MarkerSeverity.Error,
|
|
startLineNumber: detail.start?.line,
|
|
startColumn: detail.start?.column,
|
|
endLineNumber: detail.end?.line,
|
|
endColumn: detail.end?.column,
|
|
})
|
|
}
|
|
} 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()
|
|
})
|