[mod] createstate

This commit is contained in:
Andy Bunce 2025-08-26 20:44:53 +01:00
parent 5a8d24dc49
commit ecb975a999
5 changed files with 58 additions and 259 deletions

View file

@ -11,8 +11,7 @@ import { closeBrackets, autocompletion, closeBracketsKeymap, completionKeymap }
import { xQuery } from "@codemirror/legacy-modes/mode/xquery"
// Theme
import { oneDark } from "@codemirror/theme-one-dark";
import { LSPClient, LSPPlugin, languageServerSupport } from "@codemirror/lsp-client";
// Language
import { xml } from "@codemirror/lang-xml";
@ -67,21 +66,6 @@ const baseExts = [
StreamLanguage.define(xQuery)
];
function createEditorState(initialContents, extensions, options = {}) {
if (options.oneDark)
extensions.push(oneDark);
return EditorState.create({
doc: initialContents,
extensions
});
}
function createEditorView(state, parent) {
return new EditorView({ state, parent });
}
function debouncedChangeListener({ delay = 750, onChange }) {
let timeoutId = null;
let lastContent = '';
@ -118,4 +102,4 @@ function listCommands(view) {
return commands;
};
export { createEditorState, createEditorView, openSearchPanel, openLintPanel, languageServerSupport, baseExts, simpleWebSocketTransport, linter, LSPPlugin, setDiagnostics, LSPClient, debouncedChangeListener, listCommands };
export { EditorView,EditorState, openSearchPanel, openLintPanel, languageServerSupport, baseExts, simpleWebSocketTransport, linter, LSPPlugin, setDiagnostics, LSPClient, debouncedChangeListener, listCommands };

41
bundles/src/try.js Normal file
View file

@ -0,0 +1,41 @@
import {basicSetup, EditorView} from "codemirror"
import { EditorState } from '@codemirror/state';
import { LSPClient, LSPPlugin, languageServerSupport } from "@codemirror/lsp-client";
import {StreamLanguage} from "@codemirror/language"
import { xQuery } from "@codemirror/legacy-modes/mode/xquery"
function simpleWebSocketTransport(uri) {
let handlers = [];
return new Promise(function (resolve, reject) {
let sock = new WebSocket(uri);
sock.onmessage = e => { for (let h of handlers) h(e.data.toString()); };
sock.onerror = e => reject(e);
sock.onopen = () => resolve({
socket: sock,
send: (message) => sock.send(message),
subscribe: (handler) => handlers.push(handler),
unsubscribe: (handler) => handlers = handlers.filter(h => h != handler)
});
}
);
};
simpleWebSocketTransport("ws://localhost:3000/ws/lsp")
.then(transport => {
client = new LSPClient().connect(transport);
let extLsp = languageServerSupport(client, file, "xquery");
const doc = view.state.doc.toString();
const state = lsp.createEditorState(doc, [...lsp.baseExts, extLsp, extLint]);
view.setState(state);
})
.catch(r => { alert("connection failed: " + server) });
new EditorView({
doc: "xquery version '3.1';\n(:~ comment:)\nmodule namespace pdfbox='ns';\n",
extensions: [basicSetup, StreamLanguage.define(xQuery)],
parent: document.body
});

View file

@ -19409,7 +19409,7 @@ var lsp = (function (exports) {
for (let tag of style.tag)
map[tag.id] = style.class;
}
let { scope, all = null } = options || {};
let { scope, all = null } = {};
return {
style: (tags) => {
let cls = all;
@ -21389,56 +21389,6 @@ var lsp = (function (exports) {
cursor: "pointer"
}
});
/**
A highlight style associates CSS styles with higlighting
[tags](https://lezer.codemirror.net/docs/ref#highlight.Tag).
*/
class HighlightStyle {
constructor(
/**
The tag styles used to create this highlight style.
*/
specs, options) {
this.specs = specs;
let modSpec;
function def(spec) {
let cls = StyleModule.newName();
(modSpec || (modSpec = Object.create(null)))["." + cls] = spec;
return cls;
}
const all = typeof options.all == "string" ? options.all : options.all ? def(options.all) : undefined;
const scopeOpt = options.scope;
this.scope = scopeOpt instanceof Language ? (type) => type.prop(languageDataProp) == scopeOpt.data
: scopeOpt ? (type) => type == scopeOpt : undefined;
this.style = tagHighlighter(specs.map(style => ({
tag: style.tag,
class: style.class || def(Object.assign({}, style, { tag: null }))
})), {
all,
}).style;
this.module = modSpec ? new StyleModule(modSpec) : null;
this.themeType = options.themeType;
}
/**
Create a highlighter style that associates the given styles to
the given tags. The specs must be objects that hold a style tag
or array of tags in their `tag` property, and either a single
`class` property providing a static CSS class (for highlighter
that rely on external styling), or a
[`style-mod`](https://github.com/marijnh/style-mod#documentation)-style
set of CSS properties (which define the styling for those tags).
The CSS rules created for a highlighter will be emitted in the
order of the spec's properties. That means that for elements that
have multiple tags associated with them, styles defined further
down in the list will have a higher CSS precedence than styles
defined earlier.
*/
static define(specs, options) {
return new HighlightStyle(specs, options || {});
}
}
const highlighterFacet = /*@__PURE__*/Facet.define();
const fallbackHighlighter = /*@__PURE__*/Facet.define({
combine(values) { return values.length ? [values[0]] : null; }
@ -21448,28 +21398,6 @@ var lsp = (function (exports) {
return main.length ? main : state.facet(fallbackHighlighter);
}
/**
Wrap a highlighter in an editor extension that uses it to apply
syntax highlighting to the editor content.
When multiple (non-fallback) styles are provided, the styling
applied is the union of the classes they emit.
*/
function syntaxHighlighting(highlighter, options) {
let ext = [treeHighlighter], themeType;
if (highlighter instanceof HighlightStyle) {
if (highlighter.module)
ext.push(EditorView.styleModule.of(highlighter.module));
themeType = highlighter.themeType;
}
if (themeType)
ext.push(highlighterFacet.computeN([EditorView.darkTheme], state => {
return state.facet(EditorView.darkTheme) == (themeType == "dark") ? [highlighter] : [];
}));
else
ext.push(highlighterFacet.of(highlighter));
return ext;
}
/**
Returns the CSS classes (if any) that the highlighters active in
the state would assign to the given style
[tags](https://lezer.codemirror.net/docs/ref#highlight.Tag) and
@ -21489,42 +21417,6 @@ var lsp = (function (exports) {
}
return result;
}
class TreeHighlighter {
constructor(view) {
this.markCache = Object.create(null);
this.tree = syntaxTree(view.state);
this.decorations = this.buildDeco(view, getHighlighters(view.state));
this.decoratedTo = view.viewport.to;
}
update(update) {
let tree = syntaxTree(update.state), highlighters = getHighlighters(update.state);
let styleChange = highlighters != getHighlighters(update.startState);
let { viewport } = update.view, decoratedToMapped = update.changes.mapPos(this.decoratedTo, 1);
if (tree.length < viewport.to && !styleChange && tree.type == this.tree.type && decoratedToMapped >= viewport.to) {
this.decorations = this.decorations.map(update.changes);
this.decoratedTo = decoratedToMapped;
}
else if (tree != this.tree || update.viewportChanged || styleChange) {
this.tree = tree;
this.decorations = this.buildDeco(update.view, highlighters);
this.decoratedTo = viewport.to;
}
}
buildDeco(view, highlighters) {
if (!highlighters || !this.tree.length)
return Decoration.none;
let builder = new RangeSetBuilder();
for (let { from, to } of view.visibleRanges) {
highlightTree(this.tree, highlighters, (from, to, style) => {
builder.add(from, to, this.markCache[style] || (this.markCache[style] = Decoration.mark({ class: style })));
}, from, to);
}
return builder.finish();
}
}
const treeHighlighter = /*@__PURE__*/Prec.high(/*@__PURE__*/ViewPlugin.fromClass(TreeHighlighter, {
decorations: v => v.decorations
}));
const baseTheme$2 = /*@__PURE__*/EditorView.baseTheme({
"&.cm-focused .cm-matchingBracket": { backgroundColor: "#328c8252" },
@ -25987,114 +25879,6 @@ var lsp = (function (exports) {
}
};
// Using https://github.com/one-dark/vscode-one-dark-theme/ as reference for the colors
const chalky = "#e5c07b", coral = "#e06c75", cyan = "#56b6c2", invalid = "#ffffff", ivory = "#abb2bf", stone = "#7d8799", // Brightened compared to original to increase contrast
malibu = "#61afef", sage = "#98c379", whiskey = "#d19a66", violet = "#c678dd", darkBackground = "#21252b", highlightBackground = "#2c313a", background = "#282c34", tooltipBackground = "#353a42", selection = "#3E4451", cursor = "#528bff";
/**
The editor theme styles for One Dark.
*/
const oneDarkTheme = /*@__PURE__*/EditorView.theme({
"&": {
color: ivory,
backgroundColor: background
},
".cm-content": {
caretColor: cursor
},
".cm-cursor, .cm-dropCursor": { borderLeftColor: cursor },
"&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection": { backgroundColor: selection },
".cm-panels": { backgroundColor: darkBackground, color: ivory },
".cm-panels.cm-panels-top": { borderBottom: "2px solid black" },
".cm-panels.cm-panels-bottom": { borderTop: "2px solid black" },
".cm-searchMatch": {
backgroundColor: "#72a1ff59",
outline: "1px solid #457dff"
},
".cm-searchMatch.cm-searchMatch-selected": {
backgroundColor: "#6199ff2f"
},
".cm-activeLine": { backgroundColor: "#6699ff0b" },
".cm-selectionMatch": { backgroundColor: "#aafe661a" },
"&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket": {
backgroundColor: "#bad0f847"
},
".cm-gutters": {
backgroundColor: background,
color: stone,
border: "none"
},
".cm-activeLineGutter": {
backgroundColor: highlightBackground
},
".cm-foldPlaceholder": {
backgroundColor: "transparent",
border: "none",
color: "#ddd"
},
".cm-tooltip": {
border: "none",
backgroundColor: tooltipBackground
},
".cm-tooltip .cm-tooltip-arrow:before": {
borderTopColor: "transparent",
borderBottomColor: "transparent"
},
".cm-tooltip .cm-tooltip-arrow:after": {
borderTopColor: tooltipBackground,
borderBottomColor: tooltipBackground
},
".cm-tooltip-autocomplete": {
"& > ul > li[aria-selected]": {
backgroundColor: highlightBackground,
color: ivory
}
}
}, { dark: true });
/**
The highlighting style for code in the One Dark theme.
*/
const oneDarkHighlightStyle = /*@__PURE__*/HighlightStyle.define([
{ tag: tags.keyword,
color: violet },
{ tag: [tags.name, tags.deleted, tags.character, tags.propertyName, tags.macroName],
color: coral },
{ tag: [/*@__PURE__*/tags.function(tags.variableName), tags.labelName],
color: malibu },
{ tag: [tags.color, /*@__PURE__*/tags.constant(tags.name), /*@__PURE__*/tags.standard(tags.name)],
color: whiskey },
{ tag: [/*@__PURE__*/tags.definition(tags.name), tags.separator],
color: ivory },
{ tag: [tags.typeName, tags.className, tags.number, tags.changed, tags.annotation, tags.modifier, tags.self, tags.namespace],
color: chalky },
{ tag: [tags.operator, tags.operatorKeyword, tags.url, tags.escape, tags.regexp, tags.link, /*@__PURE__*/tags.special(tags.string)],
color: cyan },
{ tag: [tags.meta, tags.comment],
color: stone },
{ tag: tags.strong,
fontWeight: "bold" },
{ tag: tags.emphasis,
fontStyle: "italic" },
{ tag: tags.strikethrough,
textDecoration: "line-through" },
{ tag: tags.link,
color: stone,
textDecoration: "underline" },
{ tag: tags.heading,
fontWeight: "bold",
color: coral },
{ tag: [tags.atom, tags.bool, /*@__PURE__*/tags.special(tags.variableName)],
color: whiskey },
{ tag: [tags.processingInstruction, tags.string, tags.inserted],
color: sage },
{ tag: tags.invalid,
color: invalid },
]);
/**
Extension to enable the One Dark theme (both the editor theme and
the highlight style).
*/
const oneDark = [oneDarkTheme, /*@__PURE__*/syntaxHighlighting(oneDarkHighlightStyle)];
/**
* marked v15.0.12 - a markdown parser
* Copyright (c) 2011-2025, Christopher Jeffrey. (MIT Licensed)
@ -29998,21 +29782,6 @@ ${text}</tr>
StreamLanguage.define(xQuery)
];
function createEditorState(initialContents, extensions, options = {}) {
if (options.oneDark)
extensions.push(oneDark);
return EditorState.create({
doc: initialContents,
extensions
});
}
function createEditorView(state, parent) {
return new EditorView({ state, parent });
}
function debouncedChangeListener({ delay = 750, onChange }) {
let timeoutId = null;
let lastContent = '';
@ -30048,11 +29817,11 @@ ${text}</tr>
return commands;
}
exports.EditorState = EditorState;
exports.EditorView = EditorView;
exports.LSPClient = LSPClient;
exports.LSPPlugin = LSPPlugin;
exports.baseExts = baseExts;
exports.createEditorState = createEditorState;
exports.createEditorView = createEditorView;
exports.debouncedChangeListener = debouncedChangeListener;
exports.languageServerSupport = languageServerSupport;
exports.linter = linter;

File diff suppressed because one or more lines are too long

View file

@ -1,4 +1,7 @@
const view = lsp.createEditorView(undefined, document.getElementById("editor"));
const view = new lsp.EditorView({
extensions: lsp.baseExts,
parent:document.getElementById("editor")
});
let doc = `3+1`;
var client;
var extLint;
@ -10,8 +13,8 @@ window.addEventListener('load', () => {
if (savedText) {
doc = savedText;
}
view.setState(lsp.createEditorState(doc, lsp.baseExts));
connect();
view.setState(lsp.EditorState.create({doc:doc, extensions: lsp.baseExts}));
//connect();
});
// Save content to localStorage when the page is about to unload
window.addEventListener('beforeunload', () => {
@ -72,17 +75,19 @@ function connect() {
client = new lsp.LSPClient().connect(transport);
$("popConnect").hidePopover();
connectStatus(true);
let extLsp = lsp.languageServerSupport(client, file, "XXXXX");
let extLsp = lsp.languageServerSupport(client, file, "xquery");
extLint = lsp.linter(null,{ autoPanel: true });
const doc = view.state.doc.toString();
const state = lsp.createEditorState(doc, [...lsp.baseExts, extLsp, extLint,
const exts=[...lsp.baseExts, extLsp, extLint,
lsp.debouncedChangeListener({
delay: 750,
onChange: (content, state) => {
console.log('Debounced change detected:'+content);
client.sync();
}})
]);
];
const state =lsp.EditorState.create({doc: doc,extensions:exts})
view.setState(state);
})
.catch(r => { connectStatus(false); alert("connection failed: " + server) });