Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@
"types": "./es/headless.d.ts",
"import": "./es/headless.js"
},
"./litexml-commands": {
"types": "./es/plugins/litexml/command/symbols.d.ts",
"import": "./es/plugins/litexml/command/symbols.js"
},
"./react": {
"types": "./es/react.d.ts",
"import": "./es/react.js"
Expand Down
26 changes: 6 additions & 20 deletions src/plugins/litexml/command/diffCommand.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,8 @@
import { mergeRegister } from '@lexical/utils';
import {
$getNodeByKey,
$isElementNode,
COMMAND_PRIORITY_EDITOR,
LexicalEditor,
createCommand,
} from 'lexical';
import { $getNodeByKey, $isElementNode, COMMAND_PRIORITY_EDITOR, LexicalEditor } from 'lexical';

import { DiffNode } from '../node/DiffNode';

export enum DiffAction {
Reject,
Accept,
}

export const LITEXML_DIFFNODE_COMMAND = createCommand<{ action: DiffAction; nodeKey: string }>(
'LITEXML_DIFFNODE_COMMAND',
);

export const LITEXML_DIFFNODE_ALL_COMMAND = createCommand<{ action: DiffAction }>(
'LITEXML_DIFFNODE_ALL_COMMAND',
);
import { DiffAction, LITEXML_DIFFNODE_ALL_COMMAND, LITEXML_DIFFNODE_COMMAND } from './symbols';

function doAction(node: DiffNode, action: DiffAction) {
if (node.diffType === 'modify') {
Expand Down Expand Up @@ -146,3 +128,7 @@ export function registerLiteXMLDiffCommand(editor: LexicalEditor) {
),
);
}

// Command identities and the `DiffAction` enum live in the side-effect-free
// `./symbols` module so they stay single-instance across the package bundles.
export { DiffAction, LITEXML_DIFFNODE_ALL_COMMAND, LITEXML_DIFFNODE_COMMAND } from './symbols';
58 changes: 15 additions & 43 deletions src/plugins/litexml/command/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
COMMAND_PRIORITY_EDITOR,
LexicalEditor,
LexicalNode,
createCommand,
} from 'lexical';

import { $closest } from '@/editor-kernel';
Expand All @@ -19,6 +18,12 @@ import { createDebugLogger } from '@/utils/debug';
import type LitexmlDataSource from '../data-source/litexml-data-source';
import { $createDiffNode, DiffNode } from '../node/DiffNode';
import { $cloneNode, $parseSerializedNodeImpl, charToId } from '../utils';
import {
LITEXML_APPLY_COMMAND,
LITEXML_INSERT_COMMAND,
LITEXML_MODIFY_COMMAND,
LITEXML_REMOVE_COMMAND,
} from './symbols';

const logger = createDebugLogger('plugin', 'litexml');

Expand Down Expand Up @@ -138,48 +143,6 @@ function wrapBlockModify(oldBlock: LexicalNode, editor: LexicalEditor, changeFn:
newBlock.replace(diffNode, false);
}

export const LITEXML_MODIFY_COMMAND = createCommand<
Array<
| {
action: 'insert';
beforeId: string;
litexml: string;
}
| {
action: 'insert';
afterId: string;
litexml: string;
}
| {
action: 'remove';
id: string;
}
| {
action: 'modify';
litexml: string | string[];
}
>
>('LITEXML_MODIFY_COMMAND');

export const LITEXML_APPLY_COMMAND = createCommand<{ delay?: boolean; litexml: string | string[] }>(
'LITEXML_APPLY_COMMAND',
);
export const LITEXML_REMOVE_COMMAND = createCommand<{ delay?: boolean; id: string }>(
'LITEXML_REMOVE_COMMAND',
);
export const LITEXML_INSERT_COMMAND = createCommand<
| {
beforeId: string;
delay?: boolean;
litexml: string;
}
| {
afterId: string;
delay?: boolean;
litexml: string;
}
>('LITEXML_INSERT_COMMAND');

export function registerLiteXMLCommand(editor: LexicalEditor, dataSource: LitexmlDataSource) {
return mergeRegister(
editor.registerCommand(
Expand Down Expand Up @@ -570,3 +533,12 @@ function handleInsert(
}
});
}

// Command identities live in the side-effect-free `./symbols` module so they
// keep a single runtime identity across the package's browser/node bundles.
export {
LITEXML_APPLY_COMMAND,
LITEXML_INSERT_COMMAND,
LITEXML_MODIFY_COMMAND,
LITEXML_REMOVE_COMMAND,
} from './symbols';
78 changes: 78 additions & 0 deletions src/plugins/litexml/command/symbols.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { createCommand } from 'lexical';

/**
* LiteXML command identities.
*
* These symbols are intentionally isolated in a side-effect-free module so they
* keep a SINGLE runtime identity across every entry of this package.
*
* Lexical's `dispatchCommand` matches command listeners by object reference, not
* by the string label. The package ships two independently-bundled entries — the
* browser build (`index` / `react` / `renderer`) and the node build (`headless`)
* — and if each entry inlined its own `createCommand(...)` call, dispatching a
* command obtained from one entry onto an editor registered by the other would
* silently no-op (different object identities, same label).
*
* By keeping every command in this one module — exposed verbatim through
* `@lobehub/editor/litexml-commands` and emitted as a shared chunk by both
* builds — a single object backs the command in any runtime, and the module is
* pure enough to be imported on the server without pulling in the DOM-dependent
* editor bundle.
*/

export enum DiffAction {
Reject,
Accept,
}

export const LITEXML_MODIFY_COMMAND = createCommand<
Array<
| {
action: 'insert';
beforeId: string;
litexml: string;
}
| {
action: 'insert';
afterId: string;
litexml: string;
}
| {
action: 'remove';
id: string;
}
| {
action: 'modify';
litexml: string | string[];
}
>
>('LITEXML_MODIFY_COMMAND');

export const LITEXML_APPLY_COMMAND = createCommand<{ delay?: boolean; litexml: string | string[] }>(
'LITEXML_APPLY_COMMAND',
);

export const LITEXML_REMOVE_COMMAND = createCommand<{ delay?: boolean; id: string }>(
'LITEXML_REMOVE_COMMAND',
);

export const LITEXML_INSERT_COMMAND = createCommand<
| {
beforeId: string;
delay?: boolean;
litexml: string;
}
| {
afterId: string;
delay?: boolean;
litexml: string;
}
>('LITEXML_INSERT_COMMAND');

export const LITEXML_DIFFNODE_COMMAND = createCommand<{ action: DiffAction; nodeKey: string }>(
'LITEXML_DIFFNODE_COMMAND',
);

export const LITEXML_DIFFNODE_ALL_COMMAND = createCommand<{ action: DiffAction }>(
'LITEXML_DIFFNODE_ALL_COMMAND',
);
8 changes: 7 additions & 1 deletion tsdown.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@ export default defineConfig([
...commonConfig,
clean: true,
entry: {
headless: 'src/headless/index.ts',
'headless': 'src/headless/index.ts',
// Emit the LiteXML command identities as their own chunk so the bundled
// node build references them instead of inlining a second copy. Both this
// entry and the unbundled browser build resolve to the same emitted
// `es/plugins/litexml/command/symbols.js`, giving the commands a single
// runtime identity (and a DOM-free import via `./litexml-commands`).
'plugins/litexml/command/symbols': 'src/plugins/litexml/command/symbols.ts',
},
outExtensions: () => ({ dts: '.d.ts', js: '.js' }),
platform: 'node',
Expand Down
Loading