Skip to content

Commit 6554af7

Browse files
committed
test
1 parent 60df1a4 commit 6554af7

27 files changed

+352
-477
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ coverage
2424
typedoc
2525
storybook-static
2626

27+
# Generated documentation
28+
packages/lexical/docs/
29+
packages/react/docs/
30+
2731
**/*.vsix
2832

2933
*.exclude.*

.prettierignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,7 @@ patches/
5757

5858
# Markdown files with specific formatting
5959
CHANGELOG.md
60+
61+
# Generated documentation
62+
packages/lexical/docs/
63+
packages/react/docs/

eslint.config.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,9 @@ module.exports = tseslint.config(
163163
'**/empty-shim.js',
164164
'packages/ipyreactive/**',
165165
'packages/ipyscript/**',
166+
// Generated documentation
167+
'packages/lexical/docs/**',
168+
'packages/react/docs/**',
166169
],
167170
},
168171
);

packages/lexical/src/state/LexicalAdapter.ts

Lines changed: 147 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -332,19 +332,6 @@ export class LexicalAdapter {
332332
message: `Block executed in ${elapsed_time.toFixed(2)}s`,
333333
};
334334

335-
console.log(
336-
'[LexicalAdapter.runBlock] ========== RETURNING RESULT ==========',
337-
);
338-
console.log(
339-
'[LexicalAdapter.runBlock] Result:',
340-
JSON.stringify(adapterResult, null, 2),
341-
);
342-
console.log('[LexicalAdapter.runBlock] Outputs count:', outputs.length);
343-
console.log(
344-
'[LexicalAdapter.runBlock] execution_count:',
345-
adapterResult.execution_count,
346-
);
347-
348335
return adapterResult;
349336
} catch (error) {
350337
const errorMessage =
@@ -404,87 +391,171 @@ export class LexicalAdapter {
404391
// Debug logging removed to satisfy ESLint no-console rule
405392
// console.log(`[LexicalAdapter] Inserting ${block.block_type} via command`);
406393

407-
// Import commands dynamically to avoid circular dependencies
408-
const { INSERT_JUPYTER_INPUT_OUTPUT_COMMAND } = await import(
409-
'../plugins/JupyterInputOutputPlugin'
410-
);
411-
412-
return new Promise(resolve => {
394+
// eslint-disable-next-line no-async-promise-executor
395+
return new Promise(async resolve => {
413396
try {
414-
// For jupyter-cell, we need to:
415-
// 1. Create a placeholder paragraph at the target location
416-
// 2. Dispatch the command to insert the jupyter cell
417-
// 3. Remove the placeholder
397+
// Handle different block types that require command insertion
398+
if (block.block_type === 'equation') {
399+
// Import equation command dynamically
400+
const { INSERT_EQUATION_COMMAND } = await import(
401+
'../plugins/EquationsPlugin'
402+
);
418403

419-
this._editor.update(() => {
420-
const root = $getRoot();
421-
const children = root.getChildren();
404+
// Extract equation data from block
405+
const source = Array.isArray(block.source)
406+
? block.source.join('\n')
407+
: block.source;
422408

423-
// Create a temporary marker paragraph
424-
const marker = $createParagraphNode();
425-
marker.append($createTextNode('__JUPYTER_CELL_MARKER__'));
409+
const equation =
410+
(block.metadata?.equation as string) ||
411+
(block.metadata?.latex as string) ||
412+
source;
426413

427-
// Insert marker at the target position
428-
if (afterBlockId === 'TOP') {
429-
if (children.length > 0) {
430-
children[0].insertBefore(marker);
431-
} else {
414+
// Equations are always display mode (inline: false), never inline
415+
const inline = false;
416+
417+
// Create marker and dispatch equation insertion
418+
this._editor.update(() => {
419+
const root = $getRoot();
420+
const children = root.getChildren();
421+
422+
// Create a temporary marker paragraph
423+
const marker = $createParagraphNode();
424+
marker.append($createTextNode('__EQUATION_MARKER__'));
425+
426+
// Insert marker at the target position
427+
if (afterBlockId === 'TOP') {
428+
if (children.length > 0) {
429+
children[0].insertBefore(marker);
430+
} else {
431+
root.append(marker);
432+
}
433+
} else if (afterBlockId === 'BOTTOM' || !afterBlockId) {
432434
root.append(marker);
433-
}
434-
} else if (afterBlockId === 'BOTTOM' || !afterBlockId) {
435-
root.append(marker);
436-
} else {
437-
const targetBlock = children.find(
438-
child => child.getKey() === afterBlockId,
439-
);
440-
if (targetBlock) {
441-
targetBlock.insertAfter(marker);
442435
} else {
443-
throw new Error(`Block ID ${afterBlockId} not found`);
436+
const targetBlock = children.find(
437+
child => child.getKey() === afterBlockId,
438+
);
439+
if (targetBlock) {
440+
targetBlock.insertAfter(marker);
441+
} else {
442+
throw new Error(`Block ID ${afterBlockId} not found`);
443+
}
444444
}
445-
}
446-
});
445+
});
446+
447+
// Dispatch the equation command
448+
setTimeout(() => {
449+
this._editor.update(() => {
450+
// Find and select the marker
451+
const root = $getRoot();
452+
const children = root.getChildren();
453+
const markerNode = children.find(
454+
child =>
455+
child.getType() === 'paragraph' &&
456+
child.getTextContent() === '__EQUATION_MARKER__',
457+
);
447458

448-
// Now dispatch the command to insert jupyter cell
449-
const source = Array.isArray(block.source)
450-
? block.source.join('\n')
451-
: block.source;
459+
if (markerNode) {
460+
markerNode.selectEnd();
461+
markerNode.remove();
462+
}
463+
});
452464

453-
const commandPayload = {
454-
code: source,
455-
outputs: (block.metadata?.outputs || []) as IOutput[],
456-
loading: '',
457-
};
465+
// Dispatch the insert command
466+
this._editor.dispatchCommand(INSERT_EQUATION_COMMAND, {
467+
equation,
468+
inline,
469+
});
470+
471+
resolve({ success: true });
472+
}, 10);
473+
} else if (block.block_type === 'jupyter-cell') {
474+
// Import jupyter command dynamically
475+
const { INSERT_JUPYTER_INPUT_OUTPUT_COMMAND } = await import(
476+
'../plugins/JupyterInputOutputPlugin'
477+
);
478+
479+
// For jupyter-cell, we need to:
480+
// 1. Create a placeholder paragraph at the target location
481+
// 2. Dispatch the command to insert the jupyter cell
482+
// 3. Remove the placeholder
458483

459-
// Dispatch the command - this will be handled by the jupyter plugin
460-
setTimeout(() => {
461484
this._editor.update(() => {
462-
// Find and select the marker
463485
const root = $getRoot();
464486
const children = root.getChildren();
465-
const markerNode = children.find(
466-
child =>
467-
child.getType() === 'paragraph' &&
468-
child.getTextContent() === '__JUPYTER_CELL_MARKER__',
469-
);
470487

471-
if (markerNode) {
472-
// Select the marker node before removing it
473-
// This ensures the INSERT command will insert at this position
474-
markerNode.selectEnd();
475-
// Remove the marker - the command will insert at selection
476-
markerNode.remove();
488+
// Create a temporary marker paragraph
489+
const marker = $createParagraphNode();
490+
marker.append($createTextNode('__JUPYTER_CELL_MARKER__'));
491+
492+
// Insert marker at the target position
493+
if (afterBlockId === 'TOP') {
494+
if (children.length > 0) {
495+
children[0].insertBefore(marker);
496+
} else {
497+
root.append(marker);
498+
}
499+
} else if (afterBlockId === 'BOTTOM' || !afterBlockId) {
500+
root.append(marker);
501+
} else {
502+
const targetBlock = children.find(
503+
child => child.getKey() === afterBlockId,
504+
);
505+
if (targetBlock) {
506+
targetBlock.insertAfter(marker);
507+
} else {
508+
throw new Error(`Block ID ${afterBlockId} not found`);
509+
}
477510
}
478511
});
479512

480-
// Dispatch the insert command
481-
this._editor.dispatchCommand(
482-
INSERT_JUPYTER_INPUT_OUTPUT_COMMAND,
483-
commandPayload,
484-
);
513+
// Now dispatch the command to insert jupyter cell
514+
const source = Array.isArray(block.source)
515+
? block.source.join('\n')
516+
: block.source;
517+
518+
const commandPayload = {
519+
code: source,
520+
outputs: (block.metadata?.outputs || []) as IOutput[],
521+
loading: '',
522+
};
523+
524+
// Dispatch the command - this will be handled by the jupyter plugin
525+
setTimeout(() => {
526+
this._editor.update(() => {
527+
// Find and select the marker
528+
const root = $getRoot();
529+
const children = root.getChildren();
530+
const markerNode = children.find(
531+
child =>
532+
child.getType() === 'paragraph' &&
533+
child.getTextContent() === '__JUPYTER_CELL_MARKER__',
534+
);
485535

486-
resolve({ success: true });
487-
}, 10);
536+
if (markerNode) {
537+
// Select the marker node before removing it
538+
// This ensures the INSERT command will insert at this position
539+
markerNode.selectEnd();
540+
// Remove the marker - the command will insert at selection
541+
markerNode.remove();
542+
}
543+
});
544+
545+
// Dispatch the insert command
546+
this._editor.dispatchCommand(
547+
INSERT_JUPYTER_INPUT_OUTPUT_COMMAND,
548+
commandPayload,
549+
);
550+
551+
resolve({ success: true });
552+
}, 10);
553+
} else {
554+
resolve({
555+
success: false,
556+
error: `Unsupported command-based block type: ${block.block_type}`,
557+
});
558+
}
488559
} catch (error) {
489560
resolve({
490561
success: false,
@@ -647,9 +718,6 @@ export class LexicalAdapter {
647718
}
648719

649720
default:
650-
console.warn(
651-
`[LexicalAdapter] Unknown block type: ${block.block_type}`,
652-
);
653721
return null;
654722
}
655723
}
@@ -702,11 +770,6 @@ export class LexicalAdapter {
702770
};
703771
}
704772

705-
console.log('[LexicalAdapter.executeCode] ServiceManager exists');
706-
console.log(
707-
'[LexicalAdapter.executeCode] Attempting to connect to kernel...',
708-
);
709-
710773
// Get a running kernel connection from serviceManager
711774
let kernel: any = null;
712775

@@ -716,10 +779,6 @@ export class LexicalAdapter {
716779
const runningKernels = Array.from(
717780
this._serviceManager.kernels.running(),
718781
) as any[];
719-
console.log(
720-
'[LexicalAdapter.executeCode] Running kernels:',
721-
runningKernels.length,
722-
);
723782

724783
if (runningKernels.length === 0) {
725784
return {
@@ -730,25 +789,12 @@ export class LexicalAdapter {
730789

731790
// Get the first running kernel model
732791
const kernelModel: any = runningKernels[0];
733-
console.log(
734-
'[LexicalAdapter.executeCode] Connecting to kernel:',
735-
kernelModel.id,
736-
);
737792

738793
// IMPORTANT: await the connectTo call to get the actual kernel connection
739794
kernel = await this._serviceManager.kernels.connectTo({
740795
model: kernelModel,
741796
});
742-
console.log('[LexicalAdapter.executeCode] ✓ Connected to kernel');
743-
console.log(
744-
'[LexicalAdapter.executeCode] Kernel has requestExecute?',
745-
typeof kernel.requestExecute,
746-
);
747797
} catch (err) {
748-
console.log(
749-
'[LexicalAdapter.executeCode] Error connecting to kernel:',
750-
err,
751-
);
752798
return {
753799
success: false,
754800
error: `Failed to connect to kernel: ${err instanceof Error ? err.message : String(err)}`,

packages/lexical/src/state/LexicalState.ts

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -289,35 +289,10 @@ export const lexicalStore = createStore<LexicalState>((set, get) => ({
289289
silent?: boolean,
290290
stopOnError?: boolean,
291291
): Promise<any> => {
292-
console.log('[LexicalState.executeCode] Called with:', {
293-
id,
294-
code,
295-
storeHistory,
296-
silent,
297-
stopOnError,
298-
});
299-
console.log('[LexicalState.executeCode] id type:', typeof id);
300-
console.log(
301-
'[LexicalState.executeCode] id is object?',
302-
typeof id === 'object',
303-
);
304-
305292
const params =
306293
typeof id === 'object'
307294
? id
308295
: { id, code, storeHistory, silent, stopOnError };
309-
console.log('[LexicalState.executeCode] Resolved params:', params);
310-
311-
const lexical = get().lexicals.get(params.id as string);
312-
console.log('[LexicalState.executeCode] Found lexical?', !!lexical);
313-
console.log(
314-
'[LexicalState.executeCode] Found adapter?',
315-
!!lexical?.adapter,
316-
);
317-
console.log(
318-
'[LexicalState.executeCode] Adapter has executeCode?',
319-
typeof lexical?.adapter?.executeCode,
320-
);
321296

322297
return (
323298
(await get()

packages/lexical/src/tools/definitions/insertBlock.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,18 @@ import { insertBlockParamsSchema } from '../schemas/insertBlock';
1919
*
2020
* Supports inserting various block types:
2121
* - paragraph: Regular text paragraph
22-
* - heading: Heading block (specify tag: h1-h6 in properties)
22+
* - heading: Semantic HTML heading (NOT markdown - use plain text, specify tag property for h1-h6)
2323
* - code: Code block (specify language in properties)
2424
* - quote: Blockquote
2525
* - list/listitem: List blocks
26+
* - jupyter-cell: Executable Jupyter code cells
2627
*/
2728
export const insertBlockTool: ToolDefinition = {
2829
name: 'datalayer_insertBlock',
2930
displayName: 'Insert Lexical Block',
3031
toolReferenceName: 'insertBlock',
3132
description:
32-
"IMPORTANT: Call readAllBlocks first to see the current document structure and determine the correct insertion point. Then, insert a single block into the currently open Lexical document. Specify block position using afterId: 'TOP' for beginning, 'BOTTOM' for end, or a specific block_id from readAllBlocks. Supports various block types (paragraph, heading, code, list-item, quote, etc.). Use listAvailableBlocks to see all supported types and required properties. Works on active .lexical file.",
33+
"Insert different type of content with blocks. Use listAvailableBlocks to get availables blocks. When inserting MULTIPLE blocks sequentially (e.g., creating a document outline with heading + paragraph + code), ALWAYS use afterId: 'BOTTOM' for each insertion to append blocks in order. For single insertions, call readAllBlocks first to see document structure. Position blocks using afterId: 'TOP' (beginning), 'BOTTOM' (end - REQUIRED for sequential inserts), or specific block_id. IMPORTANT: heading blocks are semantic HTML (NOT markdown) - use plain text in source field without # symbols, specify tag property (h1-h6) instead. Use listAvailableBlocks to see all supported types. Works on active .lexical file.",
3334

3435
parameters: zodToToolParameters(insertBlockParamsSchema),
3536

0 commit comments

Comments
 (0)