-
Notifications
You must be signed in to change notification settings - Fork 0
Extension Development
github-actions[bot] edited this page Mar 10, 2026
·
1 revision
Implement editor features as reusable extensions in packages/starter-kit or the relevant premium package.
Put a feature in packages/starter-kit when it is part of the baseline community editing experience.
Put a feature in a premium package when it is commercially licensed, depends on entitlement checks, or is part of a paid workflow such as AI, collaboration, comments, revision history, or admin tooling.
Keep neutral contracts in @lexion-rte/core only when they are reusable across both tracks without embedding pricing or licensing behavior.
A LexionExtension can provide:
-
key: unique id. -
schema: schema instance or factory. -
commands(context): command map. -
prosemirrorPlugins(context): ProseMirror plugins. -
onCreate/onDestroy: lifecycle hooks.
import type { LexionExtension } from "@lexion-rte/core";
export const myExtension: LexionExtension = {
key: "my-extension",
commands: () => ({
myCommand: ({ state, dispatch }) => {
dispatch(state.tr);
return true;
}
}),
prosemirrorPlugins: () => []
};import { LexionEditor } from "@lexion-rte/core";
import { starterKitExtension } from "@lexion-rte/starter-kit";
import { myExtension } from "./my-extension";
const editor = new LexionEditor({
extensions: [starterKitExtension, myExtension]
});import { useMemo } from "react";
import { LexionEditor } from "@lexion-rte/core";
import { starterKitExtension } from "@lexion-rte/starter-kit";
import { LexionEditorView } from "@lexion-rte/react";
import { myExtension } from "./my-extension";
export const EditorScreen = () => {
const editor = useMemo(
() => new LexionEditor({ extensions: [starterKitExtension, myExtension] }),
[]
);
return <LexionEditorView editor={editor} />;
};<template>
<LexionEditorView :editor="editor" />
</template>
<script setup lang="ts">
import { onBeforeUnmount } from "vue";
import { LexionEditor } from "@lexion-rte/core";
import { starterKitExtension } from "@lexion-rte/starter-kit";
import { LexionEditorView } from "@lexion-rte/vue";
import { myExtension } from "./my-extension";
const editor = new LexionEditor({
extensions: [starterKitExtension, myExtension]
});
onBeforeUnmount(() => {
editor.destroy();
});
</script>import { AfterViewInit, Component, ElementRef, OnDestroy, ViewChild } from "@angular/core";
import { createLexionAngularAdapter } from "@lexion-rte/angular";
@Component({
selector: "app-editor",
template: `<div #editorHost></div>`
})
export class EditorComponent implements AfterViewInit, OnDestroy {
@ViewChild("editorHost", { static: true })
private editorHost!: ElementRef<HTMLElement>;
private readonly adapter = createLexionAngularAdapter();
ngAfterViewInit(): void {
this.adapter.attach(this.editorHost.nativeElement);
}
ngOnDestroy(): void {
this.adapter.destroy();
}
}- Put feature logic in
packages/starter-kitor the relevant premium package, not adapters. - Keep extension command names stable and explicit.
- Avoid side effects in extension module scope.
- Keep schema ownership clear: use one schema-providing extension per editor instance.
- Do not add entitlement or plan logic to adapters or
@lexion-rte/core.
pnpm buildpnpm lint- Verify behavior in relevant adapter sample apps under
apps/*-sampleand inapps/playground.