Skip to content

Comments

fix: editors#11

Merged
goanpeca merged 4 commits intomainfrom
fix/editors
Feb 23, 2026
Merged

fix: editors#11
goanpeca merged 4 commits intomainfrom
fix/editors

Conversation

@echarles
Copy link
Member

Screenshot from 2026-02-21 19-39-53 Screenshot from 2026-02-21 19-40-40

Copilot AI review requested due to automatic review settings February 21, 2026 18:47
@netlify
Copy link

netlify bot commented Feb 21, 2026

Deploy Preview for datalayer-desktop failed.

Name Link
🔨 Latest commit 499688d
🔍 Latest deploy log https://app.netlify.com/projects/datalayer-desktop/deploys/699a06e2c0a2880008c2f922

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses editor runtime/module integration issues in the renderer, primarily to improve Jupyter/Lexical editor compatibility in the Electron/Vite environment.

Changes:

  • Add a path module polyfill to the RequireJS shim to unblock CommonJS JupyterLab code that does require("path").
  • Plumb a serviceManager prop from DocumentEditor into the Lexical editor flow and adjust useJupyter initialization.
  • Wrap the Lexical editor with CommentsProvider to support comment-related plugins/UI.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.

File Description
src/renderer/polyfills/requirejs.js Registers a path module in the RequireJS registry to prevent crashes in CJS JupyterLab bundles.
src/renderer/pages/DocumentEditor.tsx Passes a serviceManager into LexicalEditor when rendering the document editor.
src/renderer/components/lexical/LexicalEditor.tsx Adds serviceManager to props, changes useJupyter initialization, and wraps editor in CommentsProvider.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 320 to 327
export function LexicalEditor({
className = '',
collaboration,
onContentChange,
runtimePodName,
onRuntimeSelected,
serviceManager,
}: LexicalEditorProps) {
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

serviceManager is accepted in LexicalEditor props but never used, which will trigger @typescript-eslint/no-unused-vars (repo runs eslint with --max-warnings 0). Either forward it to LexicalEditorContainer (so it’s actually used) or rename it to _serviceManager/remove it if not needed.

Copilot uses AI. Check for mistakes.
/>
<LexicalEditorContainer
collaboration={collaboration}
onContentChange={onContentChange}
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LexicalEditorContainer expects a serviceManager prop (propsServiceManager), but LexicalEditor never passes its serviceManager down. As a result, the custom runtime/service manager created in DocumentEditor won’t be used by the Jupyter plugins inside the editor.

Suggested change
onContentChange={onContentChange}
onContentChange={onContentChange}
serviceManager={serviceManager}

Copilot uses AI. Check for mistakes.
Comment on lines +166 to +169
const { serviceManager, defaultKernel } = useJupyter({
serviceManager: propsServiceManager,
startDefaultKernel: !!propsServiceManager,
});
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useJupyter previously ran with default options, but now you always pass { startDefaultKernel: !!propsServiceManager }. Callers that don’t provide a service manager (e.g. LexicalDocument renders <LexicalEditor ... /> without serviceManager) will now pass startDefaultKernel: false, which can prevent defaultKernel from ever being created and break JupyterInputOutputPlugin/ComponentPickerMenuPlugin. Preserve the prior default by omitting startDefaultKernel when propsServiceManager is undefined (or default it to true).

Suggested change
const { serviceManager, defaultKernel } = useJupyter({
serviceManager: propsServiceManager,
startDefaultKernel: !!propsServiceManager,
});
const jupyterOptions = propsServiceManager
? { serviceManager: propsServiceManager, startDefaultKernel: true }
: {};
const { serviceManager, defaultKernel } = useJupyter(jupyterOptions);

Copilot uses AI. Check for mistakes.
Comment on lines 54 to 57
return '/' + paths.filter(p => p).join('/').replace(/\/+/g, '/');
},
relative: function (from, to) {
return to || '';
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new path polyfill’s resolve()/relative() don’t match Node’s path.posix semantics (e.g., relative(from, to) currently ignores from, and resolve() doesn’t normalize ./.. segments). If any Jupyterlab CJS code relies on these, it will produce incorrect paths. Either implement minimal-but-correct posix semantics for the functions you expose, or restrict the polyfill to only the functions you know are needed (and fail loudly for unsupported ones).

Suggested change
return '/' + paths.filter(p => p).join('/').replace(/\/+/g, '/');
},
relative: function (from, to) {
return to || '';
// Minimal POSIX-like resolve: process from right to left, stop at first
// absolute path, then normalize. We treat "/" as the cwd when no absolute
// segment is provided.
let resolvedPath = '';
let isAbsolute = false;
for (let i = paths.length - 1; i >= 0; i--) {
let p = paths[i];
if (!p) continue;
if (p[0] === '/') {
resolvedPath = p + '/' + resolvedPath;
isAbsolute = true;
break;
} else {
resolvedPath = p + '/' + resolvedPath;
}
}
if (!isAbsolute) {
resolvedPath = '/' + resolvedPath;
}
// Use existing normalize implementation to handle "." and ".." segments.
return this.normalize(resolvedPath);
},
relative: function (from, to) {
// Minimal POSIX-like relative: compute the relative path from "from" to "to"
// using the resolved, normalized absolute paths.
from = this.resolve(from || '');
to = this.resolve(to || '');
if (from === to) {
return '';
}
const fromParts = from.slice(1).split('/').filter(Boolean);
const toParts = to.slice(1).split('/').filter(Boolean);
const length = Math.min(fromParts.length, toParts.length);
let samePartsLength = length;
for (let i = 0; i < length; i++) {
if (fromParts[i] !== toParts[i]) {
samePartsLength = i;
break;
}
}
const outputParts = [];
for (let i = samePartsLength; i < fromParts.length; i++) {
outputParts.push('..');
}
outputParts.push(...toParts.slice(samePartsLength));
return outputParts.join('/');

Copilot uses AI. Check for mistakes.
Comment on lines +83 to +89
return {
root: '',
dir: this.dirname(p),
base: this.basename(p),
ext: this.extname(p),
name: this.basename(p, this.extname(p)),
};
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parse() relies on this.dirname/this.basename/..., which will break if consumers ever call it unbound (e.g. const { parse } = require('path'); parse('x')). Also root is always returned as '', but for absolute paths Node returns '/' in path.posix.parse. Use direct references (not this) and align the returned shape with Node’s path.posix.parse to avoid subtle incompatibilities in downstream Jupyterlab code.

Suggested change
return {
root: '',
dir: this.dirname(p),
base: this.basename(p),
ext: this.extname(p),
name: this.basename(p, this.extname(p)),
};
// Align with Node's path.posix.parse semantics.
if (!p) {
return { root: '', dir: '', base: '', ext: '', name: '' };
}
const isAbsolute = p[0] === '/';
const root = isAbsolute ? '/' : '';
const dirRaw = pathModule.dirname(p);
const dir = !isAbsolute && dirRaw === '.' ? '' : dirRaw;
const base = pathModule.basename(p);
const ext = pathModule.extname(p);
const name = pathModule.basename(p, ext);
return { root, dir, base, ext, name };

Copilot uses AI. Check for mistakes.
@echarles echarles requested a review from goanpeca February 21, 2026 18:52
@goanpeca goanpeca merged commit 2b617b8 into main Feb 23, 2026
3 of 14 checks passed
@goanpeca goanpeca deleted the fix/editors branch February 23, 2026 14:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants