Skip to content

Commit e95f430

Browse files
committed
fix(document-api): add minProperties, type export, shared alignment constant
1 parent ee17a46 commit e95f430

4 files changed

Lines changed: 40 additions & 27 deletions

File tree

packages/document-api/src/contract/schemas.ts

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4869,24 +4869,27 @@ const operationSchemas: Record<OperationId, OperationSchemaSet> = {
48694869
id: { type: 'string' },
48704870
op: { const: 'format.apply', type: 'string' },
48714871
where: stepWhereSchema,
4872-
args: objectSchema(
4873-
{
4874-
inline: buildInlineRunPatchSchema(),
4875-
alignment: {
4876-
type: 'string',
4877-
enum: ['left', 'center', 'right', 'justify'],
4878-
description:
4879-
'Set paragraph alignment on the target block(s). Can be combined with inline formatting in the same step.',
4880-
},
4881-
scope: {
4882-
type: 'string',
4883-
enum: ['match', 'block'],
4884-
description:
4885-
'When "block", inline formatting expands to cover the entire parent paragraph(s), not just the matched text. Use "block" after markdown inserts to format whole paragraphs with a short identifying pattern. Default: "match".',
4872+
args: {
4873+
...objectSchema(
4874+
{
4875+
inline: buildInlineRunPatchSchema(),
4876+
alignment: {
4877+
type: 'string',
4878+
enum: ['left', 'center', 'right', 'justify'],
4879+
description:
4880+
'Set paragraph alignment on the target block(s). Can be combined with inline formatting in the same step.',
4881+
},
4882+
scope: {
4883+
type: 'string',
4884+
enum: ['match', 'block'],
4885+
description:
4886+
'When "block", inline formatting expands to cover the entire parent paragraph(s), not just the matched text. Use "block" after markdown inserts to format whole paragraphs with a short identifying pattern. Default: "match".',
4887+
},
48864888
},
4887-
},
4888-
[], // No individual field is required — at least one must be present
4889-
),
4889+
[],
4890+
),
4891+
minProperties: 1,
4892+
},
48904893
},
48914894
['id', 'op', 'where', 'args'],
48924895
);

packages/document-api/src/insert/insert.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import type { SelectionTarget, TargetLocator, SDMutationReceipt } from '../types
33
import type { SDInsertInput } from '../types/structural-input.js';
44
import type { SDFragment } from '../types/fragment.js';
55
import type { StoryLocator } from '../types/story.types.js';
6-
import { PLACEMENT_VALUES } from '../types/placement.js';
6+
import { type BlockNodeAddress } from '../types/base.js';
7+
import { PLACEMENT_VALUES, type Placement } from '../types/placement.js';
78
import { DocumentApiValidationError } from '../errors.js';
89
import {
910
isRecord,
@@ -40,6 +41,20 @@ export type TextInsertInput = OptionalInsertLocator & {
4041
in?: StoryLocator;
4142
};
4243

44+
/**
45+
* Type-safe input for markdown/html inserts with block-level positioning.
46+
* Accepts BlockNodeAddress targets and placement (routed through the structural insert path).
47+
* Standalone export — not part of the InsertInput union to avoid type narrowing issues in the runtime.
48+
*/
49+
export type RichContentInsertInput = {
50+
target?: SelectionTarget | BlockNodeAddress;
51+
ref?: string;
52+
value: string;
53+
type: 'markdown' | 'html';
54+
placement?: Placement;
55+
in?: StoryLocator;
56+
};
57+
4358
/** @deprecated Use {@link TextInsertInput} instead. */
4459
export type LegacyInsertInput = TextInsertInput;
4560

packages/super-editor/src/editors/v1/document-api-adapters/plan-engine/executor.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import type {
3939
} from './executor-registry.types.js';
4040
import { getStepExecutor } from './executor-registry.js';
4141
import { planError } from './errors.js';
42+
import { ALIGNMENT_TO_JUSTIFICATION } from './paragraphs-wrappers.js';
4243
import { closeHistory } from 'prosemirror-history';
4344
import { yUndoPluginKey } from 'y-prosemirror';
4445
import { checkRevision, getRevision } from './revision-tracker.js';
@@ -804,21 +805,15 @@ export function executeTextDelete(
804805
return { changed: true };
805806
}
806807

807-
/** Alignment API value → OOXML justification value */
808-
const ALIGNMENT_TO_JUSTIFICATION: Record<string, string> = {
809-
left: 'left',
810-
center: 'center',
811-
right: 'right',
812-
justify: 'both',
813-
};
808+
// ALIGNMENT_TO_JUSTIFICATION imported from paragraphs-wrappers.js
814809

815810
/**
816811
* Applies alignment to the paragraph node(s) that contain the given range.
817812
* Uses the same mechanism as paragraphsSetAlignmentWrapper: updates
818813
* paragraphProperties.justification via tr.setNodeMarkup.
819814
*/
820815
function applyAlignmentToRange(tr: Transaction, absFrom: number, absTo: number, alignment: string): boolean {
821-
const justification = ALIGNMENT_TO_JUSTIFICATION[alignment];
816+
const justification = ALIGNMENT_TO_JUSTIFICATION[alignment as keyof typeof ALIGNMENT_TO_JUSTIFICATION];
822817
if (!justification) return false;
823818

824819
let changed = false;

packages/super-editor/src/editors/v1/document-api-adapters/plan-engine/paragraphs-wrappers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ function mutateParagraphProperties(
238238
// Alignment mapping — external API → OOXML justification value
239239
// ---------------------------------------------------------------------------
240240

241-
const ALIGNMENT_TO_JUSTIFICATION: Record<ParagraphAlignment, string> = {
241+
export const ALIGNMENT_TO_JUSTIFICATION: Record<ParagraphAlignment, string> = {
242242
left: 'left',
243243
center: 'center',
244244
right: 'right',

0 commit comments

Comments
 (0)