@coldsmirk/inkstone-monaco 0.34.0 → 0.34.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +43 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ Part of [inkstone](https://github.com/coldsmirk/inkstone). For a drop-in React c
|
|
|
12
12
|
- **`disabledKeybindings` / `installDisabledKeybindings`** — swallow the find/replace chords and the command palette's F1 for editors that opt in. Monaco's standalone keybinding service is page-global and its rules are permanent, so the install registers each chord once per monaco module's service (duplicate copies of this package share the ledger; independent monaco bundles register their own) and scopes it with a per-capability context key created on the opted-in editor; the chord table is held to the installed `monaco-editor` by an upgrade-tripwire test.
|
|
13
13
|
- **`installJsxTagClosing`** — VS Code's auto-closing JSX tags: a typed `>` that completes an opening tag inserts the matching closing tag and keeps the caret between the pair. Parser-backed: the bundled TS worker subclasses monaco's stock worker to expose `getJsxClosingTagAtPosition` — a language-service call monaco never proxied (VS Code ships the feature in its TypeScript extension, outside the editor core) — so generics, comparisons, arrow functions, and already-closed elements never trigger. Only a *typed* `>` triggers: the gates require one bare single-character insertion into a **writable** TypeScript/JavaScript model whose path ends in `.tsx` / `.jsx`, and the reply lands only while the caret still sits right after that `>` — so `replaceInEditor` replacements, `StreamingEditorController` appends (the stream holds the editor read-only), and other programmatic writes never earn a closing tag, and the insert arrives as its own undo step (one undo removes just the closing tag). A `getWorker` override that routes the `typescript` label to a worker without the subclass is detected on its first lookup and the install disarms silently. Multi-cursor typing and the diff editor's panes are deliberately out of scope. `<MonacoEditor>` installs it automatically.
|
|
14
14
|
- **`dropMonacoWorkerFallbacks()`** (from **`@coldsmirk/inkstone-monaco/vite`**) — a Vite plugin that removes monaco's built-in worker fallbacks at build time. Monaco's language workerManagers statically reference their workers as `new Worker(new URL(...))` fallbacks that never run under `ensureMonacoHost` (the environment check prefers `getWorker`), yet bundlers emit a chunk per reference — including a ~7MB TypeScript worker duplicate that is never fetched. The plugin rewrites the fallbacks into located throws so the duplicates are never emitted; if a monaco bump reshapes the pattern it warns and leaves the file untouched (the dead chunk returns, nothing breaks).
|
|
15
|
-
- **Embedded-editor fixes** — works around [microsoft/monaco-editor#5177](https://github.com/microsoft/monaco-editor/issues/5177) (find-widget button tooltips landing on top of the buttons they describe) with a `width: max-content` hover-layer style tagged `data-inkstone="monaco-hover-geometry"`; deleted the moment upstream fixes it. And 0.57 draws an editor's context menu under `fixedOverflowWidgets` (inkstone's default) in a shadow root hosted in the node the editor was created in, which no theme color reaches — a transparent menu, its items over the code ([microsoft/monaco-editor#5511](https://github.com/microsoft/monaco-editor/issues/5511)); the host makes that node a `.monaco-component`, the class Monaco writes its theme's colors on, so the menu inherits them, and `<MonacoEditor>` keeps the class in the `className` it renders.
|
|
15
|
+
- **Embedded-editor fixes** — works around [microsoft/monaco-editor#5177](https://github.com/microsoft/monaco-editor/issues/5177) (find-widget button tooltips landing on top of the buttons they describe) with a `width: max-content` hover-layer style tagged `data-inkstone="monaco-hover-geometry"`; deleted the moment upstream fixes it. And 0.57 draws an editor's context menu under `fixedOverflowWidgets` (inkstone's default) in a shadow root hosted in the node the editor was created in, which no theme color reaches — a transparent menu, its items over the code ([microsoft/monaco-editor#5511](https://github.com/microsoft/monaco-editor/issues/5511)); the host makes that node a `.monaco-component`, the class Monaco writes its theme's colors on, so the menu inherits them, and `<MonacoEditor>` keeps the class in the `className` it renders. Those tooltips and that menu also stand in the node the editor was created in even where the host gave the editor an `overflowWidgetsDomNode` — so a modal or a scroll region around the editor cut them off at its edge; the host answers such an editor with its overflow widgets node instead, where its hover and completion list already stand.
|
|
16
16
|
- **`StreamingEditorController`** — stream generated text into an editor without routing every token through app state: `begin()` / `append(chunk)` / `end()` / `discard()`, `attach(editor)` / `detach(editor)` with buffered replay for late-mounting editors (and for a model swapped onto the attached editor mid-stream, including after the final chunk), and `isStreaming()` for the onChange guard. The stream locks every editor it touches read-only and `end()` / `discard()` restore each one's own setting — by handle, so an editor detached mid-stream is restored too; `discard()` puts every displaced document back into the model it came from, and `end()` does the same for every model except the one keeping the streamed text. Full-buffer writes and restorations preserve each model's UTF-8 BOM. Editors and models the app disposed mid-stream are skipped, never touched — teardown can race the stream without wedging it.
|
|
17
17
|
- **`replaceInEditor(editor, old, new, all)`** — exact find-and-replace on an editor handle via `executeEdits`, preserving undo/cursor/folds; returns whether the edit landed (`false` = no editor / empty search / no match / a read-only editor refused it — e.g. one locked by a stream in progress), so a tool-call handler knows to fall back to a state write.
|
|
18
18
|
- **`registerShikiHighlighting(monaco, highlighter)`** — wire `@coldsmirk/inkstone-core`'s shared Shiki highlighter onto a monaco module (one from `ensureMonacoHost`), once per distinct module: defines the highlighter's themes as Monaco themes, registers each loaded grammar's canonical name as a Monaco language where Monaco has none and its Shiki tokenization in Monaco's registry — over Monaco's own, JSON's included (its mode's tokenizer is turned off through its configuration, its other features left on) — and patches `setTheme` so the Shiki theme ids route through the highlighter while non-Shiki ids (vs/vs-dark, caller-defined) keep Monaco's original path. Called again on a bridged module, it registers the grammars loaded since. A failed registration is restored and retried on the next call.
|
package/dist/index.js
CHANGED
|
@@ -191,6 +191,48 @@ function installContextMenuThemeFix(monaco) {
|
|
|
191
191
|
});
|
|
192
192
|
}
|
|
193
193
|
//#endregion
|
|
194
|
+
//#region src/context-view-fix.ts
|
|
195
|
+
async function loadContextViewInternals() {
|
|
196
|
+
const [services, layout, editors, scoped] = await Promise.all([
|
|
197
|
+
import("monaco-editor/editor/standalone/browser/standaloneServices.js"),
|
|
198
|
+
import("monaco-editor/platform/layout/browser/layoutService.js"),
|
|
199
|
+
import("monaco-editor/editor/browser/services/codeEditorService.js"),
|
|
200
|
+
import("monaco-editor/editor/standalone/browser/standaloneLayoutService.js")
|
|
201
|
+
]);
|
|
202
|
+
return {
|
|
203
|
+
get: (service) => services.StandaloneServices.get(service),
|
|
204
|
+
layoutService: layout.ILayoutService,
|
|
205
|
+
codeEditorService: editors.ICodeEditorService,
|
|
206
|
+
standaloneLayout: Object.getPrototypeOf(scoped.EditorScopedLayoutService)
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
function standContextViewsWithOverflowWidgets(internals) {
|
|
210
|
+
const layout = internals.get(internals.layoutService);
|
|
211
|
+
if (typeof layout !== "object" || layout === null || Object.getPrototypeOf(layout) !== internals.standaloneLayout.prototype || Object.hasOwn(layout, "activeContainer")) return;
|
|
212
|
+
const answered = Object.getOwnPropertyDescriptor(internals.standaloneLayout.prototype, "activeContainer")?.get;
|
|
213
|
+
if (answered === void 0) return;
|
|
214
|
+
const editors = internals.get(internals.codeEditorService);
|
|
215
|
+
const container = () => {
|
|
216
|
+
return (editors.getFocusedCodeEditor() ?? editors.getActiveCodeEditor())?.getOverflowWidgetsDomNode() ?? answered.call(layout);
|
|
217
|
+
};
|
|
218
|
+
Object.defineProperties(layout, {
|
|
219
|
+
activeContainer: {
|
|
220
|
+
configurable: true,
|
|
221
|
+
get: container
|
|
222
|
+
},
|
|
223
|
+
getContainer: {
|
|
224
|
+
configurable: true,
|
|
225
|
+
value: container
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
function installContextViewFix(monaco, internals) {
|
|
230
|
+
const created = monaco.editor.onDidCreateEditor(() => {
|
|
231
|
+
created.dispose();
|
|
232
|
+
standContextViewsWithOverflowWidgets(internals);
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
//#endregion
|
|
194
236
|
//#region src/geometry-fixes.ts
|
|
195
237
|
const HOVER_GEOMETRY_STYLE_SELECTOR = "style[data-inkstone=\"monaco-hover-geometry\"]";
|
|
196
238
|
function installHoverGeometryFix() {
|
|
@@ -320,6 +362,7 @@ function ensureMonacoHost(options = {}) {
|
|
|
320
362
|
rememberInternals(monaco, await loadMonacoInternals());
|
|
321
363
|
globalThis.MonacoEnvironment = { getWorker: (workerId, label) => getWorker?.(workerId, label) ?? builtinGetWorker(label) };
|
|
322
364
|
installContextMenuThemeFix(monaco);
|
|
365
|
+
installContextViewFix(monaco, await loadContextViewInternals());
|
|
323
366
|
if (locale === "zh-cn") monaco.editor.onDidCreateEditor(localizeActionDescriptions);
|
|
324
367
|
return monaco;
|
|
325
368
|
} catch (error) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coldsmirk/inkstone-monaco",
|
|
3
|
-
"version": "0.34.
|
|
3
|
+
"version": "0.34.1",
|
|
4
4
|
"description": "Framework-agnostic Monaco assembly: lazy offline host (all language workers bundled, no CDN), opt-in Simplified-Chinese UI via monaco's official NLS catalog, a streaming editor controller for AI-typed content, and the shared Shiki highlighting bridge.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"monaco",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@shikijs/vscode-textmate": "^10.0.2",
|
|
43
43
|
"shiki": "^4.5.0",
|
|
44
|
-
"@coldsmirk/inkstone-core": "^0.34.
|
|
44
|
+
"@coldsmirk/inkstone-core": "^0.34.1"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"monaco-editor": "^0.57.0",
|