feat: integrate monaco-languageclient v10 with NWScript LSP

Replace hand-rolled LSP client (lspClient.ts, useLspClient.ts) with
monaco-languageclient v10 extended mode using @typefox/monaco-editor-react.
NWScript TextMate grammar from the LSP submodule provides syntax highlighting.
Full LSP features: completion, hover, diagnostics, go-to-definition, signature
help — all wired through WebSocket to the nwscript-language-server.

LSP server patches: fix workspaceFolders null assertion crash, handle missing
workspace/configuration gracefully, derive rootPath from rootUri when null,
guard tokenizer getRawTokenContent against undefined tokens.

Backend fixes: WebSocket routing changed to noServer mode so /ws, /ws/lsp,
and /ws/terminal/* don't conflict. TLK index loaded at startup (41,927 entries
from nwn-haks/layonara.tlk.json). Workspace routes get proper try/catch.
writeConfig creates parent directories. setupClone ensures workspace structure.

Frontend: GffEditor and AreaEditor rewritten with inline styles and TLK
resolution for CExoLocString fields. EditorTabs rewritten with lucide icons.
Tab content hydrates from API on refresh. Setup wizard gets friendly error
messages. SimpleEditor/SimpleDiffEditor for non-LSP editor uses. Vite config
updated for monaco-vscode-api compatibility.
This commit is contained in:
plenarius
2026-04-21 05:23:52 -04:00
parent cbe51a6e67
commit f39f1d818b
62 changed files with 9355 additions and 1137 deletions
@@ -0,0 +1,347 @@
{
"name": "Forge Dark",
"type": "dark",
"colors": {
"editor.background": "#231e17",
"editor.foreground": "#ece8e3",
"editor.lineHighlightBackground": "#302a2040",
"editor.selectionBackground": "#3d3018",
"editor.selectionHighlightBackground": "#3d301860",
"editor.inactiveSelectionBackground": "#3d301850",
"editor.wordHighlightBackground": "#3d301840",
"editor.wordHighlightStrongBackground": "#3d301860",
"editor.findMatchBackground": "#b07a0040",
"editor.findMatchHighlightBackground": "#b07a0025",
"editor.hoverHighlightBackground": "#3d301830",
"editor.rangeHighlightBackground": "#3d301820",
"editorCursor.foreground": "#b07a00",
"editorWhitespace.foreground": "#4a403550",
"editorIndentGuide.background": "#4a403530",
"editorIndentGuide.activeBackground": "#4a403580",
"editorLineNumber.foreground": "#a69f9650",
"editorLineNumber.activeForeground": "#ece8e3",
"editorBracketMatch.background": "#3d301840",
"editorBracketMatch.border": "#b07a0080",
"editorOverviewRuler.border": "#4a4035",
"editorRuler.foreground": "#4a403540",
"editorGutter.background": "#231e17",
"editorError.foreground": "#f14c4c",
"editorWarning.foreground": "#cca700",
"editorInfo.foreground": "#3794ff",
"editorWidget.background": "#3b3328",
"editorWidget.foreground": "#ece8e3",
"editorWidget.border": "#4a4035",
"editorSuggestWidget.background": "#3b3328",
"editorSuggestWidget.border": "#4a4035",
"editorSuggestWidget.foreground": "#ece8e3",
"editorSuggestWidget.highlightForeground": "#b07a00",
"editorSuggestWidget.selectedBackground": "#3d3018",
"editorHoverWidget.background": "#3b3328",
"editorHoverWidget.border": "#4a4035",
"sideBar.background": "#302a20",
"sideBar.foreground": "#ece8e3",
"sideBar.border": "#4a4035",
"sideBarTitle.foreground": "#ece8e3",
"sideBarSectionHeader.background": "#302a20",
"sideBarSectionHeader.foreground": "#ece8e3",
"sideBarSectionHeader.border": "#4a4035",
"activityBar.background": "#231e17",
"activityBar.foreground": "#ece8e3",
"activityBar.border": "#4a4035",
"activityBar.activeBorder": "#b07a00",
"activityBarBadge.background": "#b07a00",
"activityBarBadge.foreground": "#231e17",
"titleBar.activeBackground": "#231e17",
"titleBar.activeForeground": "#ece8e3",
"titleBar.inactiveBackground": "#231e17",
"titleBar.inactiveForeground": "#a69f96",
"titleBar.border": "#4a4035",
"statusBar.background": "#231e17",
"statusBar.foreground": "#a69f96",
"statusBar.border": "#4a4035",
"statusBar.debuggingBackground": "#b07a00",
"statusBar.debuggingForeground": "#231e17",
"statusBar.noFolderBackground": "#231e17",
"tab.activeBackground": "#231e17",
"tab.activeForeground": "#ece8e3",
"tab.activeBorderTop": "#b07a00",
"tab.inactiveBackground": "#302a20",
"tab.inactiveForeground": "#a69f96",
"tab.border": "#4a4035",
"tab.hoverBackground": "#3b3328",
"editorGroupHeader.tabsBackground": "#302a20",
"editorGroupHeader.tabsBorder": "#4a4035",
"editorGroup.border": "#4a4035",
"panel.background": "#302a20",
"panel.border": "#4a4035",
"panelTitle.activeBorder": "#b07a00",
"panelTitle.activeForeground": "#ece8e3",
"panelTitle.inactiveForeground": "#a69f96",
"list.activeSelectionBackground": "#3d3018",
"list.activeSelectionForeground": "#ece8e3",
"list.inactiveSelectionBackground": "#3d301880",
"list.hoverBackground": "#302a2080",
"list.highlightForeground": "#b07a00",
"list.focusOutline": "#b07a00",
"input.background": "#231e17",
"input.foreground": "#ece8e3",
"input.border": "#4a4035",
"input.placeholderForeground": "#a69f9680",
"inputOption.activeBorder": "#b07a00",
"inputOption.activeBackground": "#3d3018",
"dropdown.background": "#3b3328",
"dropdown.foreground": "#ece8e3",
"dropdown.border": "#4a4035",
"button.background": "#b07a00",
"button.foreground": "#231e17",
"button.hoverBackground": "#c88b00",
"button.secondaryBackground": "#3b3328",
"button.secondaryForeground": "#ece8e3",
"button.secondaryHoverBackground": "#4a4035",
"badge.background": "#b07a00",
"badge.foreground": "#231e17",
"scrollbar.shadow": "#00000040",
"scrollbarSlider.background": "#4a403540",
"scrollbarSlider.hoverBackground": "#4a403580",
"scrollbarSlider.activeBackground": "#4a4035a0",
"focusBorder": "#b07a0080",
"foreground": "#ece8e3",
"descriptionForeground": "#a69f96",
"icon.foreground": "#a69f96",
"selection.background": "#3d3018",
"widget.shadow": "#00000040",
"terminal.foreground": "#ece8e3",
"terminal.background": "#231e17",
"terminal.ansiBlack": "#231e17",
"terminal.ansiRed": "#f14c4c",
"terminal.ansiGreen": "#6a9955",
"terminal.ansiYellow": "#b07a00",
"terminal.ansiBlue": "#569cd6",
"terminal.ansiMagenta": "#c586c0",
"terminal.ansiCyan": "#4ec9b0",
"terminal.ansiWhite": "#ece8e3",
"terminal.ansiBrightBlack": "#a69f96",
"terminal.ansiBrightRed": "#f14c4c",
"terminal.ansiBrightGreen": "#6a9955",
"terminal.ansiBrightYellow": "#dcdcaa",
"terminal.ansiBrightBlue": "#4fc1ff",
"terminal.ansiBrightMagenta": "#c586c0",
"terminal.ansiBrightCyan": "#4ec9b0",
"terminal.ansiBrightWhite": "#ece8e3",
"breadcrumb.foreground": "#a69f96",
"breadcrumb.focusForeground": "#ece8e3",
"breadcrumb.activeSelectionForeground": "#ece8e3",
"breadcrumbPicker.background": "#3b3328",
"peekView.border": "#b07a00",
"peekViewEditor.background": "#231e17",
"peekViewResult.background": "#302a20",
"peekViewTitle.background": "#302a20",
"peekViewTitleLabel.foreground": "#ece8e3",
"peekViewTitleDescription.foreground": "#a69f96",
"peekViewResult.selectionBackground": "#3d3018",
"peekViewResult.selectionForeground": "#ece8e3",
"minimap.selectionHighlight": "#3d3018",
"minimap.findMatchHighlight": "#b07a0060",
"gitDecoration.addedResourceForeground": "#6a9955",
"gitDecoration.modifiedResourceForeground": "#e2c08d",
"gitDecoration.deletedResourceForeground": "#f14c4c",
"gitDecoration.untrackedResourceForeground": "#73c991",
"gitDecoration.ignoredResourceForeground": "#a69f9680",
"gitDecoration.conflictingResourceForeground": "#e2c08d"
},
"tokenColors": [
{
"scope": ["comment", "punctuation.definition.comment"],
"settings": {
"foreground": "#6a9955",
"fontStyle": "italic"
}
},
{
"scope": [
"string",
"string.quoted",
"string.template",
"punctuation.definition.string"
],
"settings": {
"foreground": "#ce9178"
}
},
{
"scope": "string.regexp",
"settings": {
"foreground": "#d16969"
}
},
{
"scope": [
"keyword",
"keyword.control",
"keyword.operator.new",
"keyword.operator.expression",
"keyword.operator.cast",
"keyword.operator.sizeof",
"storage.modifier"
],
"settings": {
"foreground": "#c586c0"
}
},
{
"scope": [
"storage.type",
"keyword.type",
"support.type",
"entity.name.type",
"entity.name.class",
"entity.name.namespace",
"entity.name.struct"
],
"settings": {
"foreground": "#4ec9b0"
}
},
{
"scope": [
"constant",
"variable.other.constant",
"variable.other.enummember",
"support.constant"
],
"settings": {
"foreground": "#4fc1ff"
}
},
{
"scope": ["constant.numeric", "keyword.other.unit"],
"settings": {
"foreground": "#b5cea8"
}
},
{
"scope": "constant.language",
"settings": {
"foreground": "#569cd6"
}
},
{
"scope": [
"entity.name.function",
"support.function",
"entity.name.function.preprocessor"
],
"settings": {
"foreground": "#dcdcaa"
}
},
{
"scope": [
"variable",
"variable.other",
"variable.parameter",
"meta.definition.variable"
],
"settings": {
"foreground": "#9cdcfe"
}
},
{
"scope": [
"keyword.control.directive",
"keyword.preprocessor",
"meta.preprocessor",
"entity.name.function.preprocessor"
],
"settings": {
"foreground": "#569cd6"
}
},
{
"scope": [
"keyword.operator",
"keyword.operator.assignment",
"keyword.operator.arithmetic",
"keyword.operator.logical",
"keyword.operator.comparison",
"keyword.operator.bitwise",
"punctuation"
],
"settings": {
"foreground": "#d4d4d4"
}
},
{
"scope": [
"entity.name.tag",
"punctuation.definition.tag"
],
"settings": {
"foreground": "#569cd6"
}
},
{
"scope": "entity.other.attribute-name",
"settings": {
"foreground": "#9cdcfe"
}
},
{
"scope": "constant.character.escape",
"settings": {
"foreground": "#d7ba7d"
}
},
{
"scope": "invalid",
"settings": {
"foreground": "#f44747"
}
},
{
"scope": "markup.heading",
"settings": {
"foreground": "#569cd6",
"fontStyle": "bold"
}
},
{
"scope": "markup.bold",
"settings": {
"fontStyle": "bold"
}
},
{
"scope": "markup.italic",
"settings": {
"fontStyle": "italic"
}
},
{
"scope": "markup.inline.raw",
"settings": {
"foreground": "#ce9178"
}
}
]
}