@bayonai/rich-text-editor 0.1.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BEHAVIOR.md +396 -0
- package/CHANGELOG.md +22 -0
- package/README.md +25 -6
- package/dist/core/blockTree.d.ts +14 -0
- package/dist/core/blockTree.js +126 -0
- package/dist/core/blockTypes.d.ts +6 -0
- package/dist/core/blockTypes.js +5 -0
- package/dist/core/exportImport.d.ts +59 -0
- package/dist/core/exportImport.js +51 -0
- package/dist/core/features.d.ts +59 -0
- package/dist/core/features.js +57 -0
- package/dist/core/imageBlockDiagnostics.d.ts +4 -0
- package/dist/core/imageBlockDiagnostics.js +19 -0
- package/dist/core/proFeatures.d.ts +60 -0
- package/dist/core/proFeatures.js +64 -0
- package/dist/{richText.d.ts → core/richText.d.ts} +2 -0
- package/dist/core/richText.js +566 -0
- package/dist/core/types.d.ts +78 -0
- package/dist/index.d.ts +14 -8
- package/dist/index.js +8 -5
- package/dist/react/editor/RichTextBody.d.ts +28 -0
- package/dist/react/editor/RichTextBody.js +131 -0
- package/dist/react/editor/RichTextEditor.d.ts +138 -0
- package/dist/react/editor/RichTextEditor.js +2925 -0
- package/dist/react/editor/RichTextRenderedBlock.d.ts +20 -0
- package/dist/react/editor/RichTextRenderedBlock.js +162 -0
- package/dist/react/editor/RichTextRenderer.d.ts +13 -0
- package/dist/react/editor/RichTextRenderer.js +16 -0
- package/dist/react/{RichTextTitleInput.d.ts → editor/RichTextTitleInput.d.ts} +11 -1
- package/dist/react/{RichTextTitleInput.js → editor/RichTextTitleInput.js} +17 -2
- package/dist/react/editor/blockActions.d.ts +48 -0
- package/dist/react/editor/blockActions.js +495 -0
- package/dist/react/editor/editorHistory.d.ts +55 -0
- package/dist/react/editor/editorHistory.js +111 -0
- package/dist/react/{editorNavigation.d.ts → editor/editorNavigation.d.ts} +2 -0
- package/dist/react/{editorNavigation.js → editor/editorNavigation.js} +16 -0
- package/dist/react/editor/editorOperations.d.ts +10 -0
- package/dist/react/editor/editorOperations.js +3 -0
- package/dist/react/editor/editorSelection.d.ts +3 -0
- package/dist/react/editor/editorSelection.js +215 -0
- package/dist/react/{editorShortcuts.d.ts → editor/editorShortcuts.d.ts} +10 -0
- package/dist/react/{editorShortcuts.js → editor/editorShortcuts.js} +17 -1
- package/dist/react/{RichTextIcons.d.ts → icons/RichTextIcons.d.ts} +3 -0
- package/dist/react/{RichTextIcons.js → icons/RichTextIcons.js} +9 -0
- package/dist/react/index.d.ts +12 -9
- package/dist/react/index.js +7 -6
- package/dist/react/{EditorSessionProvider.d.ts → session/EditorSessionProvider.d.ts} +2 -2
- package/dist/react/{EditorSessionProvider.js → session/EditorSessionProvider.js} +3 -3
- package/dist/react/{UnsavedChangesDialog.js → session/UnsavedChangesDialog.js} +1 -1
- package/dist/react/styles/RichTextStyles.js +1362 -0
- package/dist/react/{BlockActionTool.d.ts → tools/BlockActionTool.d.ts} +1 -1
- package/dist/react/{BlockActionTool.js → tools/BlockActionTool.js} +6 -2
- package/dist/react/tools/LinkCreationInput.d.ts +9 -0
- package/dist/react/tools/LinkCreationInput.js +38 -0
- package/dist/react/{SelectionFormatToolbar.d.ts → tools/SelectionFormatToolbar.d.ts} +3 -2
- package/dist/react/{SelectionFormatToolbar.js → tools/SelectionFormatToolbar.js} +3 -3
- package/dist/react/tools/SpecialBlockOption.d.ts +9 -0
- package/dist/react/tools/SpecialBlockOption.js +8 -0
- package/dist/react/tools/SpecialBlockTool.d.ts +91 -0
- package/dist/react/tools/SpecialBlockTool.js +125 -0
- package/dist/react/{TranscriptionControl.d.ts → tools/TranscriptionControl.d.ts} +9 -0
- package/dist/react/{TranscriptionControl.js → tools/TranscriptionControl.js} +70 -9
- package/dist/react/tools/blockActionToolState.d.ts +41 -0
- package/dist/react/tools/blockActionToolState.js +177 -0
- package/dist/react/tools/imageBlockDiagnostics.d.ts +2 -0
- package/dist/react/tools/imageBlockDiagnostics.js +12 -0
- package/dist/{session.d.ts → session/session.d.ts} +1 -1
- package/dist-cjs/core/blockTree.js +137 -0
- package/dist-cjs/core/blockTypes.js +9 -0
- package/dist-cjs/core/exportImport.js +56 -0
- package/dist-cjs/core/features.js +62 -0
- package/dist-cjs/core/proFeatures.js +70 -0
- package/dist-cjs/core/richText.js +578 -0
- package/dist-cjs/index.js +22 -6
- package/dist-cjs/react/editor/RichTextBody.js +134 -0
- package/dist-cjs/react/editor/RichTextEditor.js +2956 -0
- package/dist-cjs/react/editor/RichTextRenderedBlock.js +166 -0
- package/dist-cjs/react/editor/RichTextRenderer.js +20 -0
- package/dist-cjs/react/{RichTextTitleInput.js → editor/RichTextTitleInput.js} +18 -2
- package/dist-cjs/react/editor/blockActions.js +518 -0
- package/dist-cjs/react/editor/editorHistory.js +120 -0
- package/dist-cjs/react/{editorNavigation.js → editor/editorNavigation.js} +17 -0
- package/dist-cjs/react/editor/editorOperations.js +6 -0
- package/dist-cjs/react/editor/editorSelection.js +219 -0
- package/dist-cjs/react/{editorShortcuts.js → editor/editorShortcuts.js} +17 -1
- package/dist-cjs/react/{RichTextIcons.js → icons/RichTextIcons.js} +12 -0
- package/dist-cjs/react/index.js +9 -7
- package/dist-cjs/react/{EditorSessionProvider.js → session/EditorSessionProvider.js} +3 -3
- package/dist-cjs/react/{UnsavedChangesDialog.js → session/UnsavedChangesDialog.js} +1 -1
- package/dist-cjs/react/styles/RichTextStyles.js +1365 -0
- package/dist-cjs/react/{BlockActionTool.js → tools/BlockActionTool.js} +6 -2
- package/dist-cjs/react/tools/LinkCreationInput.js +41 -0
- package/dist-cjs/react/{SelectionFormatToolbar.js → tools/SelectionFormatToolbar.js} +3 -3
- package/dist-cjs/react/tools/SpecialBlockOption.js +11 -0
- package/dist-cjs/react/tools/SpecialBlockTool.js +129 -0
- package/dist-cjs/react/{TranscriptionControl.js → tools/TranscriptionControl.js} +71 -9
- package/dist-cjs/react/tools/blockActionToolState.js +186 -0
- package/package.json +3 -2
- package/dist/react/RichTextBody.d.ts +0 -18
- package/dist/react/RichTextBody.js +0 -66
- package/dist/react/RichTextEditor.d.ts +0 -45
- package/dist/react/RichTextEditor.js +0 -1096
- package/dist/react/RichTextRenderedBlock.d.ts +0 -4
- package/dist/react/RichTextRenderedBlock.js +0 -36
- package/dist/react/RichTextRenderer.d.ts +0 -4
- package/dist/react/RichTextRenderer.js +0 -8
- package/dist/react/RichTextStyles.js +0 -719
- package/dist/react/SpecialBlockOption.d.ts +0 -7
- package/dist/react/SpecialBlockOption.js +0 -7
- package/dist/react/SpecialBlockTool.d.ts +0 -42
- package/dist/react/SpecialBlockTool.js +0 -50
- package/dist/react/blockActionToolState.d.ts +0 -18
- package/dist/react/blockActionToolState.js +0 -53
- package/dist/react/blockActions.d.ts +0 -8
- package/dist/react/blockActions.js +0 -111
- package/dist/richText.js +0 -297
- package/dist/types.d.ts +0 -34
- package/dist-cjs/react/RichTextBody.js +0 -69
- package/dist-cjs/react/RichTextEditor.js +0 -1108
- package/dist-cjs/react/RichTextRenderedBlock.js +0 -39
- package/dist-cjs/react/RichTextRenderer.js +0 -11
- package/dist-cjs/react/RichTextStyles.js +0 -722
- package/dist-cjs/react/SpecialBlockOption.js +0 -10
- package/dist-cjs/react/SpecialBlockTool.js +0 -54
- package/dist-cjs/react/blockActionToolState.js +0 -58
- package/dist-cjs/react/blockActions.js +0 -119
- package/dist-cjs/richText.js +0 -307
- /package/dist/{types.js → core/types.js} +0 -0
- /package/dist/{writingStats.d.ts → core/writingStats.d.ts} +0 -0
- /package/dist/{writingStats.js → core/writingStats.js} +0 -0
- /package/dist/react/{RichTextDocumentSurface.d.ts → editor/RichTextDocumentSurface.d.ts} +0 -0
- /package/dist/react/{RichTextDocumentSurface.js → editor/RichTextDocumentSurface.js} +0 -0
- /package/dist/react/{UnsavedChangesDialog.d.ts → session/UnsavedChangesDialog.d.ts} +0 -0
- /package/dist/react/{RichTextStyles.d.ts → styles/RichTextStyles.d.ts} +0 -0
- /package/dist/react/{richTextBlockStyles.d.ts → styles/richTextBlockStyles.d.ts} +0 -0
- /package/dist/react/{richTextBlockStyles.js → styles/richTextBlockStyles.js} +0 -0
- /package/dist/react/{specialBlockStyles.d.ts → styles/specialBlockStyles.d.ts} +0 -0
- /package/dist/react/{specialBlockStyles.js → styles/specialBlockStyles.js} +0 -0
- /package/dist/{saveControl.d.ts → session/saveControl.d.ts} +0 -0
- /package/dist/{saveControl.js → session/saveControl.js} +0 -0
- /package/dist/{session.js → session/session.js} +0 -0
- /package/dist/{sessionRegistry.d.ts → session/sessionRegistry.d.ts} +0 -0
- /package/dist/{sessionRegistry.js → session/sessionRegistry.js} +0 -0
- /package/dist-cjs/{types.js → core/types.js} +0 -0
- /package/dist-cjs/{writingStats.js → core/writingStats.js} +0 -0
- /package/dist-cjs/react/{RichTextDocumentSurface.js → editor/RichTextDocumentSurface.js} +0 -0
- /package/dist-cjs/react/{richTextBlockStyles.js → styles/richTextBlockStyles.js} +0 -0
- /package/dist-cjs/react/{specialBlockStyles.js → styles/specialBlockStyles.js} +0 -0
- /package/dist-cjs/{saveControl.js → session/saveControl.js} +0 -0
- /package/dist-cjs/{session.js → session/session.js} +0 -0
- /package/dist-cjs/{sessionRegistry.js → session/sessionRegistry.js} +0 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { type RichTextEditorEntitlements, type RichTextFeatureGate } from "./features";
|
|
2
|
+
import type { RichTextBlock } from "./types";
|
|
3
|
+
export type RichTextExportPayload = {
|
|
4
|
+
data: string;
|
|
5
|
+
extension: string;
|
|
6
|
+
filename?: string;
|
|
7
|
+
format: string;
|
|
8
|
+
mimeType: string;
|
|
9
|
+
};
|
|
10
|
+
export type RichTextExportAdapter = {
|
|
11
|
+
exportBlocks: (blocks: RichTextBlock[]) => RichTextExportPayload;
|
|
12
|
+
extension: string;
|
|
13
|
+
id: string;
|
|
14
|
+
label: string;
|
|
15
|
+
mimeType: string;
|
|
16
|
+
};
|
|
17
|
+
export type RichTextImportAdapter = {
|
|
18
|
+
extension: string;
|
|
19
|
+
id: string;
|
|
20
|
+
importData: (data: string) => unknown;
|
|
21
|
+
label: string;
|
|
22
|
+
mimeType: string;
|
|
23
|
+
};
|
|
24
|
+
export type RichTextExportImportResult<Value> = {
|
|
25
|
+
ok: true;
|
|
26
|
+
value: Value;
|
|
27
|
+
} | {
|
|
28
|
+
gate: RichTextFeatureGate;
|
|
29
|
+
ok: false;
|
|
30
|
+
};
|
|
31
|
+
export declare const richTextJsonExportAdapter: {
|
|
32
|
+
extension: string;
|
|
33
|
+
exportBlocks: (blocks: RichTextBlock[]) => {
|
|
34
|
+
data: string;
|
|
35
|
+
extension: string;
|
|
36
|
+
format: string;
|
|
37
|
+
mimeType: string;
|
|
38
|
+
};
|
|
39
|
+
id: string;
|
|
40
|
+
label: string;
|
|
41
|
+
mimeType: string;
|
|
42
|
+
};
|
|
43
|
+
export declare const richTextJsonImportAdapter: {
|
|
44
|
+
extension: string;
|
|
45
|
+
id: string;
|
|
46
|
+
importData: (data: string) => unknown;
|
|
47
|
+
label: string;
|
|
48
|
+
mimeType: string;
|
|
49
|
+
};
|
|
50
|
+
export declare function exportRichTextBlocks({ adapter, blocks, features, }: {
|
|
51
|
+
adapter: RichTextExportAdapter;
|
|
52
|
+
blocks: RichTextBlock[];
|
|
53
|
+
features?: RichTextEditorEntitlements;
|
|
54
|
+
}): Promise<RichTextExportImportResult<RichTextExportPayload>>;
|
|
55
|
+
export declare function importRichTextBlocks({ adapter, data, features, }: {
|
|
56
|
+
adapter: RichTextImportAdapter;
|
|
57
|
+
data: string;
|
|
58
|
+
features?: RichTextEditorEntitlements;
|
|
59
|
+
}): Promise<RichTextExportImportResult<RichTextBlock[]>>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { getRichTextFeatureAccess, } from "./features.js";
|
|
2
|
+
import { sanitizeRichTextBlocks } from "./richText.js";
|
|
3
|
+
export const richTextJsonExportAdapter = {
|
|
4
|
+
extension: "json",
|
|
5
|
+
exportBlocks: (blocks) => ({
|
|
6
|
+
data: JSON.stringify(sanitizeRichTextBlocks(blocks), null, 2),
|
|
7
|
+
extension: "json",
|
|
8
|
+
format: "bayon-rich-text-json",
|
|
9
|
+
mimeType: "application/json",
|
|
10
|
+
}),
|
|
11
|
+
id: "bayon-rich-text-json",
|
|
12
|
+
label: "Bayon rich text JSON",
|
|
13
|
+
mimeType: "application/json",
|
|
14
|
+
};
|
|
15
|
+
export const richTextJsonImportAdapter = {
|
|
16
|
+
extension: "json",
|
|
17
|
+
id: "bayon-rich-text-json",
|
|
18
|
+
importData: (data) => JSON.parse(data),
|
|
19
|
+
label: "Bayon rich text JSON",
|
|
20
|
+
mimeType: "application/json",
|
|
21
|
+
};
|
|
22
|
+
export async function exportRichTextBlocks({ adapter, blocks, features, }) {
|
|
23
|
+
const gate = getExportImportGate(features);
|
|
24
|
+
if (gate) {
|
|
25
|
+
return { gate, ok: false };
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
ok: true,
|
|
29
|
+
value: adapter.exportBlocks(sanitizeRichTextBlocks(blocks)),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export async function importRichTextBlocks({ adapter, data, features, }) {
|
|
33
|
+
const gate = getExportImportGate(features);
|
|
34
|
+
if (gate) {
|
|
35
|
+
return { gate, ok: false };
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
ok: true,
|
|
39
|
+
value: sanitizeRichTextBlocks(adapter.importData(data)),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function getExportImportGate(features) {
|
|
43
|
+
const access = getRichTextFeatureAccess(features, "export-import");
|
|
44
|
+
return access.enabled
|
|
45
|
+
? null
|
|
46
|
+
: {
|
|
47
|
+
featureId: access.featureId,
|
|
48
|
+
label: access.label,
|
|
49
|
+
reason: access.reason,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export type RichTextEditorFeatureId = "image-upload" | "transcription" | "export-import" | "comments" | "review-marks" | "schema-migrations" | "templates" | "collaboration";
|
|
2
|
+
export type RichTextEditorFeatureTier = "free" | "pro";
|
|
3
|
+
export type RichTextEditorEntitlements = Partial<Record<RichTextEditorFeatureId, boolean>>;
|
|
4
|
+
export type RichTextLockedFeatureMode = "disabled" | "hide";
|
|
5
|
+
export type RichTextFeatureGateReason = "disabled" | "premium" | "unavailable";
|
|
6
|
+
export type RichTextFeatureGate = {
|
|
7
|
+
featureId: RichTextEditorFeatureId;
|
|
8
|
+
label: string;
|
|
9
|
+
reason: RichTextFeatureGateReason;
|
|
10
|
+
};
|
|
11
|
+
export type RichTextFeatureAccess = {
|
|
12
|
+
enabled: true;
|
|
13
|
+
featureId: RichTextEditorFeatureId;
|
|
14
|
+
label: string;
|
|
15
|
+
reason?: undefined;
|
|
16
|
+
tier: RichTextEditorFeatureTier;
|
|
17
|
+
} | {
|
|
18
|
+
enabled: false;
|
|
19
|
+
featureId: RichTextEditorFeatureId;
|
|
20
|
+
label: string;
|
|
21
|
+
reason: RichTextFeatureGateReason;
|
|
22
|
+
tier: RichTextEditorFeatureTier;
|
|
23
|
+
};
|
|
24
|
+
export declare const richTextEditorFeatureCatalog: {
|
|
25
|
+
readonly "image-upload": {
|
|
26
|
+
readonly label: "Image upload";
|
|
27
|
+
readonly tier: "free";
|
|
28
|
+
};
|
|
29
|
+
readonly transcription: {
|
|
30
|
+
readonly label: "Transcription";
|
|
31
|
+
readonly tier: "free";
|
|
32
|
+
};
|
|
33
|
+
readonly "export-import": {
|
|
34
|
+
readonly label: "Export and import";
|
|
35
|
+
readonly tier: "pro";
|
|
36
|
+
};
|
|
37
|
+
readonly comments: {
|
|
38
|
+
readonly label: "Comments";
|
|
39
|
+
readonly tier: "pro";
|
|
40
|
+
};
|
|
41
|
+
readonly "review-marks": {
|
|
42
|
+
readonly label: "Review marks";
|
|
43
|
+
readonly tier: "pro";
|
|
44
|
+
};
|
|
45
|
+
readonly "schema-migrations": {
|
|
46
|
+
readonly label: "Schema migrations";
|
|
47
|
+
readonly tier: "pro";
|
|
48
|
+
};
|
|
49
|
+
readonly templates: {
|
|
50
|
+
readonly label: "Templates";
|
|
51
|
+
readonly tier: "pro";
|
|
52
|
+
};
|
|
53
|
+
readonly collaboration: {
|
|
54
|
+
readonly label: "Collaboration";
|
|
55
|
+
readonly tier: "pro";
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
export declare function getRichTextFeatureAccess(features: RichTextEditorEntitlements | undefined, featureId: RichTextEditorFeatureId): RichTextFeatureAccess;
|
|
59
|
+
export declare function isRichTextFeatureEnabled(features: RichTextEditorEntitlements | undefined, featureId: RichTextEditorFeatureId): boolean;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export const richTextEditorFeatureCatalog = {
|
|
2
|
+
"image-upload": {
|
|
3
|
+
label: "Image upload",
|
|
4
|
+
tier: "free",
|
|
5
|
+
},
|
|
6
|
+
transcription: {
|
|
7
|
+
label: "Transcription",
|
|
8
|
+
tier: "free",
|
|
9
|
+
},
|
|
10
|
+
"export-import": {
|
|
11
|
+
label: "Export and import",
|
|
12
|
+
tier: "pro",
|
|
13
|
+
},
|
|
14
|
+
comments: {
|
|
15
|
+
label: "Comments",
|
|
16
|
+
tier: "pro",
|
|
17
|
+
},
|
|
18
|
+
"review-marks": {
|
|
19
|
+
label: "Review marks",
|
|
20
|
+
tier: "pro",
|
|
21
|
+
},
|
|
22
|
+
"schema-migrations": {
|
|
23
|
+
label: "Schema migrations",
|
|
24
|
+
tier: "pro",
|
|
25
|
+
},
|
|
26
|
+
templates: {
|
|
27
|
+
label: "Templates",
|
|
28
|
+
tier: "pro",
|
|
29
|
+
},
|
|
30
|
+
collaboration: {
|
|
31
|
+
label: "Collaboration",
|
|
32
|
+
tier: "pro",
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
export function getRichTextFeatureAccess(features, featureId) {
|
|
36
|
+
const feature = richTextEditorFeatureCatalog[featureId];
|
|
37
|
+
const enabled = features?.[featureId] ?? true;
|
|
38
|
+
if (enabled) {
|
|
39
|
+
return {
|
|
40
|
+
enabled: true,
|
|
41
|
+
featureId,
|
|
42
|
+
label: feature.label,
|
|
43
|
+
reason: undefined,
|
|
44
|
+
tier: feature.tier,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
enabled: false,
|
|
49
|
+
featureId,
|
|
50
|
+
label: feature.label,
|
|
51
|
+
reason: feature.tier === "pro" ? "premium" : "disabled",
|
|
52
|
+
tier: feature.tier,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
export function isRichTextFeatureEnabled(features, featureId) {
|
|
56
|
+
return getRichTextFeatureAccess(features, featureId).enabled;
|
|
57
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { RichTextBlock } from "./types";
|
|
2
|
+
export type MissingImageBlockMetadata = "alt" | "url";
|
|
3
|
+
export declare function getMissingImageBlockMetadata(block: RichTextBlock): MissingImageBlockMetadata[];
|
|
4
|
+
export declare function warnIfImageBlockMissingDisplayUrl(block: RichTextBlock): void;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export function getMissingImageBlockMetadata(block) {
|
|
2
|
+
if (block.type !== "image") {
|
|
3
|
+
return [];
|
|
4
|
+
}
|
|
5
|
+
return [
|
|
6
|
+
block.url?.trim() ? null : "url",
|
|
7
|
+
block.alt?.trim() ? null : "alt",
|
|
8
|
+
].filter((field) => field !== null);
|
|
9
|
+
}
|
|
10
|
+
export function warnIfImageBlockMissingDisplayUrl(block) {
|
|
11
|
+
const missing = getMissingImageBlockMetadata(block);
|
|
12
|
+
if (block.type !== "image" ||
|
|
13
|
+
typeof block.uploadProgress === "number" ||
|
|
14
|
+
!missing.includes("url") ||
|
|
15
|
+
missing.includes("alt")) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
console.warn("Rich text image block is missing a display URL.", { block });
|
|
19
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { type RichTextEditorEntitlements, type RichTextFeatureGate } from "./features";
|
|
2
|
+
import type { RichTextBlock } from "./types";
|
|
3
|
+
type RichTextProResult<Value> = {
|
|
4
|
+
ok: true;
|
|
5
|
+
value: Value;
|
|
6
|
+
} | {
|
|
7
|
+
gate: RichTextFeatureGate;
|
|
8
|
+
ok: false;
|
|
9
|
+
};
|
|
10
|
+
export type RichTextSchemaMigration = {
|
|
11
|
+
id: string;
|
|
12
|
+
migrate: (blocks: RichTextBlock[]) => unknown;
|
|
13
|
+
};
|
|
14
|
+
export type RichTextSchemaMigrationResult = {
|
|
15
|
+
appliedMigrationIds: string[];
|
|
16
|
+
blocks: RichTextBlock[];
|
|
17
|
+
};
|
|
18
|
+
export type RichTextTemplate<Variables = Record<string, unknown>> = {
|
|
19
|
+
createBlocks: (variables: Variables) => unknown;
|
|
20
|
+
id: string;
|
|
21
|
+
label: string;
|
|
22
|
+
};
|
|
23
|
+
export type RichTextCollaborationAdapter<Session = unknown> = {
|
|
24
|
+
connect: (input: {
|
|
25
|
+
blocks: RichTextBlock[];
|
|
26
|
+
}) => Promise<Session> | Session;
|
|
27
|
+
id: string;
|
|
28
|
+
label: string;
|
|
29
|
+
};
|
|
30
|
+
export type RichTextAnnotation = {
|
|
31
|
+
blockId: string;
|
|
32
|
+
id: string;
|
|
33
|
+
kind: "comment";
|
|
34
|
+
text?: string;
|
|
35
|
+
} | {
|
|
36
|
+
blockId: string;
|
|
37
|
+
id: string;
|
|
38
|
+
kind: "review-mark";
|
|
39
|
+
text?: string;
|
|
40
|
+
};
|
|
41
|
+
export declare function runRichTextSchemaMigrations({ blocks, features, migrations, }: {
|
|
42
|
+
blocks: RichTextBlock[];
|
|
43
|
+
features?: RichTextEditorEntitlements;
|
|
44
|
+
migrations: RichTextSchemaMigration[];
|
|
45
|
+
}): Promise<RichTextProResult<RichTextSchemaMigrationResult>>;
|
|
46
|
+
export declare function instantiateRichTextTemplate<Variables>({ features, template, variables, }: {
|
|
47
|
+
features?: RichTextEditorEntitlements;
|
|
48
|
+
template: RichTextTemplate<Variables>;
|
|
49
|
+
variables: Variables;
|
|
50
|
+
}): Promise<RichTextProResult<RichTextBlock[]>>;
|
|
51
|
+
export declare function connectRichTextCollaboration<Session>({ adapter, blocks, features, }: {
|
|
52
|
+
adapter: RichTextCollaborationAdapter<Session>;
|
|
53
|
+
blocks: RichTextBlock[];
|
|
54
|
+
features?: RichTextEditorEntitlements;
|
|
55
|
+
}): Promise<RichTextProResult<Session>>;
|
|
56
|
+
export declare function createRichTextAnnotations({ annotations, features, }: {
|
|
57
|
+
annotations: RichTextAnnotation[];
|
|
58
|
+
features?: RichTextEditorEntitlements;
|
|
59
|
+
}): RichTextProResult<RichTextAnnotation[]>;
|
|
60
|
+
export {};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { getRichTextFeatureAccess, } from "./features.js";
|
|
2
|
+
import { sanitizeRichTextBlocks } from "./richText.js";
|
|
3
|
+
export async function runRichTextSchemaMigrations({ blocks, features, migrations, }) {
|
|
4
|
+
const gate = getProFeatureGate(features, "schema-migrations");
|
|
5
|
+
if (gate) {
|
|
6
|
+
return { gate, ok: false };
|
|
7
|
+
}
|
|
8
|
+
let nextBlocks = sanitizeRichTextBlocks(blocks);
|
|
9
|
+
const appliedMigrationIds = [];
|
|
10
|
+
for (const migration of migrations) {
|
|
11
|
+
nextBlocks = sanitizeRichTextBlocks(migration.migrate(nextBlocks));
|
|
12
|
+
appliedMigrationIds.push(migration.id);
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
ok: true,
|
|
16
|
+
value: { appliedMigrationIds, blocks: nextBlocks },
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export async function instantiateRichTextTemplate({ features, template, variables, }) {
|
|
20
|
+
const gate = getProFeatureGate(features, "templates");
|
|
21
|
+
if (gate) {
|
|
22
|
+
return { gate, ok: false };
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
ok: true,
|
|
26
|
+
value: sanitizeRichTextBlocks(template.createBlocks(variables)),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export async function connectRichTextCollaboration({ adapter, blocks, features, }) {
|
|
30
|
+
const gate = getProFeatureGate(features, "collaboration");
|
|
31
|
+
if (gate) {
|
|
32
|
+
return { gate, ok: false };
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
ok: true,
|
|
36
|
+
value: await adapter.connect({ blocks: sanitizeRichTextBlocks(blocks) }),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export function createRichTextAnnotations({ annotations, features, }) {
|
|
40
|
+
const reviewGate = annotations.some((annotation) => annotation.kind === "review-mark")
|
|
41
|
+
? getProFeatureGate(features, "review-marks")
|
|
42
|
+
: null;
|
|
43
|
+
const commentGate = annotations.some((annotation) => annotation.kind === "comment")
|
|
44
|
+
? getProFeatureGate(features, "comments")
|
|
45
|
+
: null;
|
|
46
|
+
const gate = reviewGate ?? commentGate;
|
|
47
|
+
if (gate) {
|
|
48
|
+
return { gate, ok: false };
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
ok: true,
|
|
52
|
+
value: annotations.filter((annotation) => annotation.id.trim() && annotation.blockId.trim()),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function getProFeatureGate(features, featureId) {
|
|
56
|
+
const access = getRichTextFeatureAccess(features, featureId);
|
|
57
|
+
return access.enabled
|
|
58
|
+
? null
|
|
59
|
+
: {
|
|
60
|
+
featureId: access.featureId,
|
|
61
|
+
label: access.label,
|
|
62
|
+
reason: access.reason,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
@@ -10,6 +10,8 @@ export declare function createRichTextBlockId(): string;
|
|
|
10
10
|
export declare function sanitizeRichTextBlocks(value: unknown): RichTextBlock[];
|
|
11
11
|
export declare function isRichTextBlocksEmpty(blocks: RichTextBlock[]): boolean;
|
|
12
12
|
export declare function richTextBlocksToPlainText(blocks: RichTextBlock[]): string;
|
|
13
|
+
export declare function encodeRichTextBlocksForClipboard(blocks: RichTextBlock[]): string;
|
|
14
|
+
export declare function decodeRichTextBlocksFromClipboardText(value: string): RichTextBlock[] | null;
|
|
13
15
|
export declare function editorHtmlToMarkdown(html: string): string;
|
|
14
16
|
export declare function markdownToEditorHtml(markdown: string): string;
|
|
15
17
|
export declare function sanitizeRichTextHtml(html: string): string;
|