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
6 changes: 3 additions & 3 deletions demos/platform/src/app/PlatformToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,15 +100,15 @@ export const PlatformToolbar = forwardRef<HTMLDivElement, PlatformToolbarProps>(
ref,
): ReactElement {
const handleInsertFootnote = () => {
editorRef.current?.insertNote("f");
editorRef.current?.insertMarker("f");
};

const handleInsertCrossReference = () => {
editorRef.current?.insertNote("x");
editorRef.current?.insertMarker("x");
};

const handleInsertEndnote = () => {
editorRef.current?.insertNote("fe");
editorRef.current?.insertMarker("fe");
};

const onSelectProjectMenuItem: SelectMenuItemHandler = (selectedMenuItem) => {
Expand Down
3 changes: 0 additions & 3 deletions libs/shared-react/src/nodes/usj/node-react.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,6 @@ export function $insertNoteWithSelect(
}
}

// When this function is modified, also update the same logic in
// `packages/platform/src/editor/adaptors/usj-marker-action.utils.ts` > `footnoteMarkerAction`
// and `crossReferenceMarkerAction`
export function $createNoteChildren(
selection: RangeSelection,
marker: string,
Expand Down
2 changes: 2 additions & 0 deletions packages/platform/etc/platform-editor.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ export interface EditorRef {
getNoteOps(noteKeyOrIndex: string | number): DeltaOp[] | undefined;
getSelection(): SelectionRange | undefined;
getUsj(): Usj | undefined;
insertMarker(marker: string): void;
// @deprecated
insertNote(marker: string, caller?: string, selection?: SelectionRange): void;
paste(): void;
pastePlainText(): void;
Expand Down
22 changes: 19 additions & 3 deletions packages/platform/src/editor/Editor.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import editorUsjAdaptor from "./adaptors/editor-usj.adaptor";
import usjEditorAdaptor from "./adaptors/usj-editor.adaptor";
import { getUsjMarkerAction } from "./adaptors/usj-marker-action.utils";
import { getUsjMarkerAction, isUsjMarkerSupported } from "./adaptors/usj-marker-action.utils";
import { EditorOptions, EditorProps, EditorRef } from "./editor.model";
import editorTheme from "./editor.theme";
import ScriptureReferencePlugin from "./ScriptureReferencePlugin";
Expand Down Expand Up @@ -256,6 +256,22 @@ const Editor = forwardRef(function Editor<TLogger extends LoggerBasic>(
() => editorRef.current?.getElementByKey(nodeKey) ?? undefined,
);
},
insertMarker(marker) {
if (isReadonly) throw new Error("Cannot insert marker in readonly mode");
if (!scrRef) throw new Error("Cannot insert marker without a scripture reference (scrRef)");
if (!editorRef.current) return;

if (!isUsjMarkerSupported(marker)) throw new Error(`Unsupported marker '${marker}'`);

const markerAction = getUsjMarkerAction(
marker,
expandedNoteKeyRef,
viewOptions,
nodeOptions,
logger,
);
markerAction.action({ editor: editorRef.current, reference: scrRef });
},
insertNote(marker, caller, selection) {
editorRef.current?.update(() => {
const noteNode = $insertNote(
Expand Down Expand Up @@ -355,8 +371,8 @@ const Editor = forwardRef(function Editor<TLogger extends LoggerBasic>(
trigger={markerMenuTrigger}
scrRef={scrRef}
contextMarker={contextMarker}
getMarkerAction={(marker, markerData) =>
getUsjMarkerAction(marker, expandedNoteKeyRef, markerData, viewOptions)
getMarkerAction={(marker) =>
getUsjMarkerAction(marker, expandedNoteKeyRef, viewOptions, nodeOptions, logger)
}
/>
)}
Expand Down
191 changes: 151 additions & 40 deletions packages/platform/src/editor/adaptors/usj-marker-action-utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
createBasicTestEnvironment,
updateSelection,
} from "../../../../../libs/shared/src/nodes/usj/test.utils";
import { getUsjMarkerAction } from "./usj-marker-action.utils";
import { getUsjMarkerAction, isUsjMarkerSupported } from "./usj-marker-action.utils";
import { $createTextNode, $getRoot, $isTextNode, TextNode } from "lexical";
import { $createImmutableVerseNode, $isImmutableVerseNode, usjReactNodes } from "shared-react";
import {
Expand Down Expand Up @@ -50,9 +50,16 @@ describe("USJ Marker Action Utils", () => {

it("should insert a chapter", () => {
const { editor } = createBasicTestEnvironment(nodes, $defaultInitialEditorState);
const markerAction = getUsjMarkerAction("c", expandedNoteKeyRef, undefined, undefined, {
discrete: true,
});
const markerAction = getUsjMarkerAction(
"c",
expandedNoteKeyRef,
undefined,
undefined,
undefined,
{
discrete: true,
},
);
updateSelection(editor, secondVerseTextNode);

markerAction.action({ editor, reference });
Expand All @@ -70,9 +77,16 @@ describe("USJ Marker Action Utils", () => {
describe("should insert a verse", () => {
it("with no leading space", () => {
const { editor } = createBasicTestEnvironment(nodes, $defaultInitialEditorState);
const markerAction = getUsjMarkerAction("v", expandedNoteKeyRef, undefined, undefined, {
discrete: true,
});
const markerAction = getUsjMarkerAction(
"v",
expandedNoteKeyRef,
undefined,
undefined,
undefined,
{
discrete: true,
},
);
updateSelection(editor, secondVerseTextNode, 7);

markerAction.action({ editor, reference });
Expand All @@ -93,9 +107,16 @@ describe("USJ Marker Action Utils", () => {

it("but move leading space to previous node", () => {
const { editor } = createBasicTestEnvironment(nodes, $defaultInitialEditorState);
const markerAction = getUsjMarkerAction("v", expandedNoteKeyRef, undefined, undefined, {
discrete: true,
});
const markerAction = getUsjMarkerAction(
"v",
expandedNoteKeyRef,
undefined,
undefined,
undefined,
{
discrete: true,
},
);
updateSelection(editor, secondVerseTextNode, 6);

markerAction.action({ editor, reference });
Expand All @@ -118,9 +139,16 @@ describe("USJ Marker Action Utils", () => {
describe("should insert a char", () => {
it("with no leading space", () => {
const { editor } = createBasicTestEnvironment(nodes, $defaultInitialEditorState);
const markerAction = getUsjMarkerAction("wj", expandedNoteKeyRef, undefined, undefined, {
discrete: true,
});
const markerAction = getUsjMarkerAction(
"wj",
expandedNoteKeyRef,
undefined,
undefined,
undefined,
{
discrete: true,
},
);
updateSelection(editor, secondVerseTextNode, 7);

markerAction.action({ editor, reference });
Expand All @@ -140,9 +168,16 @@ describe("USJ Marker Action Utils", () => {

it("with leading space", () => {
const { editor } = createBasicTestEnvironment(nodes, $defaultInitialEditorState);
const markerAction = getUsjMarkerAction("wj", expandedNoteKeyRef, undefined, undefined, {
discrete: true,
});
const markerAction = getUsjMarkerAction(
"wj",
expandedNoteKeyRef,
undefined,
undefined,
undefined,
{
discrete: true,
},
);
updateSelection(editor, secondVerseTextNode, 6);

markerAction.action({ editor, reference });
Expand All @@ -162,9 +197,16 @@ describe("USJ Marker Action Utils", () => {

it("at end of para", () => {
const { editor } = createBasicTestEnvironment(nodes, $defaultInitialEditorState);
const markerAction = getUsjMarkerAction("wj", expandedNoteKeyRef, undefined, undefined, {
discrete: true,
});
const markerAction = getUsjMarkerAction(
"wj",
expandedNoteKeyRef,
undefined,
undefined,
undefined,
{
discrete: true,
},
);
updateSelection(editor, secondVerseTextNode);

markerAction.action({ editor, reference });
Expand All @@ -186,9 +228,16 @@ describe("USJ Marker Action Utils", () => {
describe("should wrap selection in char", () => {
it("with no leading space", () => {
const { editor } = createBasicTestEnvironment(nodes, $defaultInitialEditorState);
const markerAction = getUsjMarkerAction("wj", expandedNoteKeyRef, undefined, undefined, {
discrete: true,
});
const markerAction = getUsjMarkerAction(
"wj",
expandedNoteKeyRef,
undefined,
undefined,
undefined,
{
discrete: true,
},
);
updateSelection(editor, secondVerseTextNode, 7, secondVerseTextNode, 12);

markerAction.action({ editor, reference });
Expand All @@ -211,9 +260,16 @@ describe("USJ Marker Action Utils", () => {

it("but move leading space to previous node", () => {
const { editor } = createBasicTestEnvironment(nodes, $defaultInitialEditorState);
const markerAction = getUsjMarkerAction("wj", expandedNoteKeyRef, undefined, undefined, {
discrete: true,
});
const markerAction = getUsjMarkerAction(
"wj",
expandedNoteKeyRef,
undefined,
undefined,
undefined,
{
discrete: true,
},
);
updateSelection(editor, secondVerseTextNode, 6, secondVerseTextNode, 12);

markerAction.action({ editor, reference });
Expand All @@ -240,9 +296,16 @@ describe("USJ Marker Action Utils", () => {

it("of type footnote", () => {
const { editor } = createBasicTestEnvironment(nodes, $defaultInitialEditorState);
const markerAction = getUsjMarkerAction("f", expandedNoteKeyRef, undefined, undefined, {
discrete: true,
});
const markerAction = getUsjMarkerAction(
"f",
expandedNoteKeyRef,
undefined,
undefined,
undefined,
{
discrete: true,
},
);
// caret after the word "second"
updateSelection(editor, secondVerseTextNode, 6);

Expand All @@ -266,9 +329,16 @@ describe("USJ Marker Action Utils", () => {

it("of type endnote", () => {
const { editor } = createBasicTestEnvironment(nodes, $defaultInitialEditorState);
const markerAction = getUsjMarkerAction("fe", expandedNoteKeyRef, undefined, undefined, {
discrete: true,
});
const markerAction = getUsjMarkerAction(
"fe",
expandedNoteKeyRef,
undefined,
undefined,
undefined,
{
discrete: true,
},
);
// caret after the word "second"
updateSelection(editor, secondVerseTextNode, 6);

Expand All @@ -287,9 +357,16 @@ describe("USJ Marker Action Utils", () => {

it("of type extended note", () => {
const { editor } = createBasicTestEnvironment(nodes, $defaultInitialEditorState);
const markerAction = getUsjMarkerAction("ef", expandedNoteKeyRef, undefined, undefined, {
discrete: true,
});
const markerAction = getUsjMarkerAction(
"ef",
expandedNoteKeyRef,
undefined,
undefined,
undefined,
{
discrete: true,
},
);
// caret after the word "second"
updateSelection(editor, secondVerseTextNode, 6);

Expand All @@ -308,9 +385,16 @@ describe("USJ Marker Action Utils", () => {

it("of type cross reference", () => {
const { editor } = createBasicTestEnvironment(nodes, $defaultInitialEditorState);
const markerAction = getUsjMarkerAction("x", expandedNoteKeyRef, undefined, undefined, {
discrete: true,
});
const markerAction = getUsjMarkerAction(
"x",
expandedNoteKeyRef,
undefined,
undefined,
undefined,
{
discrete: true,
},
);
// caret after the word "second"
updateSelection(editor, secondVerseTextNode, 6);

Expand All @@ -334,9 +418,16 @@ describe("USJ Marker Action Utils", () => {

it("of type extended cross reference", () => {
const { editor } = createBasicTestEnvironment(nodes, $defaultInitialEditorState);
const markerAction = getUsjMarkerAction("ex", expandedNoteKeyRef, undefined, undefined, {
discrete: true,
});
const markerAction = getUsjMarkerAction(
"ex",
expandedNoteKeyRef,
undefined,
undefined,
undefined,
{
discrete: true,
},
);
// caret after the word "second"
updateSelection(editor, secondVerseTextNode, 6);

Expand All @@ -353,4 +444,24 @@ describe("USJ Marker Action Utils", () => {
});
});
});

describe("unsupported markers", () => {
it("should return a no-op action for an unknown marker", () => {
const result = getUsjMarkerAction("zzz", expandedNoteKeyRef);
expect(result.label).toBeUndefined();
expect(typeof result.action).toBe("function");
});

it.each(["p", "wj", "f", "v", "c"])("should not throw for supported marker '%s'", (marker) => {
expect(() => getUsjMarkerAction(marker, expandedNoteKeyRef)).not.toThrow();
});

it("isUsjMarkerSupported returns false for unknown markers", () => {
expect(isUsjMarkerSupported("zzz")).toBe(false);
});

it.each(["p", "wj", "f", "v", "c"])("isUsjMarkerSupported returns true for '%s'", (marker) => {
expect(isUsjMarkerSupported(marker)).toBe(true);
});
});
});
Loading
Loading