Skip to content

Commit f39f127

Browse files
committed
feat(super-editor): resolve default fontSize in get_content blocks response
1 parent e61a515 commit f39f127

3 files changed

Lines changed: 38 additions & 18 deletions

File tree

packages/document-api/src/contract/operation-definitions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ export const INTENT_GROUP_META: Record<string, IntentGroupMeta> = {
151151
'IMPORTANT: After a markdown insert, analyze the document context (what kind of document, how titles and body text are styled) and follow up with ONE superdoc_mutations call to format inserted blocks so they look like they belong. ' +
152152
'Each format.apply step accepts "inline" (fontFamily, fontSize, bold, underline, color), "alignment", and "scope" in the same step. ' +
153153
'Use scope: "block" so formatting covers the entire paragraph. ' +
154-
'ONLY set inline properties that are explicitly shown in the existing get_content blocks. If blocks do not show fontSize, do NOT set fontSize (it inherits the document default). Do NOT invent values — mirror exactly what the document blocks show. ' +
154+
'Copy the exact property values from the existing get_content blocks (fontFamily, fontSize, color, alignment, bold, underline). Do NOT invent values — use what the blocks show. ' +
155155
'Also supports replace, delete, and undo/redo. For replace and delete, pass a "ref" from superdoc_search or superdoc_get_content blocks. ' +
156156
'A search ref covers only the matched substring; a block ref covers the entire block text, so use block refs when rewriting or shortening whole paragraphs. ' +
157157
'Refs expire after any mutation; always re-search before the next edit. ' +

packages/sdk/tools/prompt-templates/system-prompt-core.md

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -151,23 +151,13 @@ superdoc_edit({action: "insert", type: "markdown",
151151

152152
**Step 3: Format ALL inserted blocks in ONE superdoc_mutations call.** Each format.apply step accepts `inline`, `alignment`, and `scope: "block"`.
153153

154-
Use `scope: "block"` so the formatting covers the entire paragraph (not just the matched text). The text pattern only needs to identify which block.
154+
Use `scope: "block"` so formatting covers the entire paragraph (not just the matched text). The text pattern only needs to identify which block. Copy the exact property values from the existing blocks in the get_content response. Do NOT invent values.
155155

156-
ONLY include inline properties that are explicitly present in the existing blocks. If the document blocks don't show `fontSize`, do NOT set fontSize (it will inherit the document's default, which is correct). If they don't show `bold`, don't set bold. Mirror exactly what you see, nothing more. Inventing values (like assuming fontSize: 12) causes mismatches.
157-
158-
Example: document blocks show fontFamily and color but NO fontSize, titles are centered:
159-
```
160-
superdoc_mutations({action: "apply", atomic: true, steps: [
161-
{id: "f1", op: "format.apply", where: {by: "select", select: {type: "text", pattern: "Executive Summary"}, require: "first"}, args: {inline: {fontFamily: "Times New Roman, serif", color: "#000000"}, alignment: "center", scope: "block"}},
162-
{id: "f2", op: "format.apply", where: {by: "select", select: {type: "text", pattern: "This agreement sets forth"}, require: "first"}, args: {inline: {fontFamily: "Times New Roman, serif", color: "#000000"}, scope: "block"}}
163-
]})
164-
```
165-
166-
Example: document blocks explicitly show fontSize: 12, titles are centered and underlined:
156+
Example: document blocks show fontFamily, fontSize: 10, color, titles centered:
167157
```
168158
superdoc_mutations({action: "apply", atomic: true, steps: [
169-
{id: "f1", op: "format.apply", where: {by: "select", select: {type: "text", pattern: "Executive Summary"}, require: "first"}, args: {inline: {fontFamily: "Times New Roman, serif", fontSize: 12, underline: true}, alignment: "center", scope: "block"}},
170-
{id: "f2", op: "format.apply", where: {by: "select", select: {type: "text", pattern: "This agreement sets forth"}, require: "first"}, args: {inline: {fontFamily: "Times New Roman, serif", fontSize: 12, color: "#000000"}, alignment: "justify", scope: "block"}}
159+
{id: "f1", op: "format.apply", where: {by: "select", select: {type: "text", pattern: "Executive Summary"}, require: "first"}, args: {inline: {fontFamily: "Times New Roman, serif", fontSize: 10, color: "#000000"}, alignment: "center", scope: "block"}},
160+
{id: "f2", op: "format.apply", where: {by: "select", select: {type: "text", pattern: "This agreement sets forth"}, require: "first"}, args: {inline: {fontFamily: "Times New Roman, serif", fontSize: 10, color: "#000000"}, scope: "block"}}
171161
]})
172162
```
173163

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

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import { requireEditorCommand, rejectTrackedMode } from '../helpers/mutation-hel
3535
import { executeDomainCommand } from './plan-wrappers.js';
3636
import { getRevision } from './revision-tracker.js';
3737
import { encodeV4Ref } from '../story-runtime/story-ref-codec.js';
38+
import { readTranslatedLinkedStyles } from '../../core/parts/adapters/styles-read.js';
3839

3940
// ---------------------------------------------------------------------------
4041
// Constants
@@ -66,10 +67,36 @@ function extractTextPreview(node: ProseMirrorNode): string | null {
6667

6768
const HEADING_PATTERN = /^Heading(\d)$/;
6869

70+
/**
71+
* Resolve the document's default font size (in points) from the style catalog.
72+
* Falls back through: Normal style rPr → docDefaults rPr → undefined.
73+
* OOXML stores fontSize as half-points (w:sz val), so we divide by 2.
74+
*/
75+
function resolveDefaultFontSizePt(editor: Editor): number | undefined {
76+
const styleProps = readTranslatedLinkedStyles(editor);
77+
if (!styleProps) return undefined;
78+
79+
// Try Normal style first
80+
const normalStyle = styleProps.styles?.['Normal'];
81+
const normalFontSize = normalStyle?.runProperties?.fontSize;
82+
if (typeof normalFontSize === 'number') return normalFontSize / 2;
83+
84+
// Fall back to docDefaults
85+
const defaultFontSize = styleProps.docDefaults?.runProperties?.fontSize;
86+
if (typeof defaultFontSize === 'number') return defaultFontSize / 2;
87+
88+
return undefined;
89+
}
90+
6991
/**
7092
* Extract key formatting from a block node's first text run marks.
93+
* When defaultFontSizePt is provided, it's used as fallback when the
94+
* inline marks don't specify a fontSize (common for inherited styles).
7195
*/
72-
function extractBlockFormatting(node: ProseMirrorNode): {
96+
function extractBlockFormatting(
97+
node: ProseMirrorNode,
98+
defaultFontSizePt?: number,
99+
): {
73100
styleId?: string | null;
74101
fontFamily?: string;
75102
fontSize?: number;
@@ -126,7 +153,7 @@ function extractBlockFormatting(node: ProseMirrorNode): {
126153
return {
127154
...(styleId ? { styleId } : {}),
128155
...(fontFamily ? { fontFamily } : {}),
129-
...(fontSize !== undefined ? { fontSize } : {}),
156+
...((fontSize ?? defaultFontSizePt) !== undefined ? { fontSize: fontSize ?? defaultFontSizePt } : {}),
130157
...(bold ? { bold } : {}),
131158
...(underline ? { underline } : {}),
132159
...(color ? { color } : {}),
@@ -240,6 +267,9 @@ export function blocksListWrapper(editor: Editor, input?: BlocksListInput): Bloc
240267

241268
const rev = getRevision(editor);
242269

270+
// Resolve document's default fontSize once for all blocks
271+
const defaultFontSizePt = resolveDefaultFontSizePt(editor);
272+
243273
const blocks: BlockListEntry[] = paged.map((candidate, i) => {
244274
const textLength = computeTextContentLength(candidate.node);
245275
const ref =
@@ -261,7 +291,7 @@ export function blocksListWrapper(editor: Editor, input?: BlocksListInput): Bloc
261291
nodeType: candidate.nodeType,
262292
textPreview: extractTextPreview(candidate.node),
263293
isEmpty: textLength === 0,
264-
...extractBlockFormatting(candidate.node),
294+
...extractBlockFormatting(candidate.node, defaultFontSizePt),
265295
...(ref ? { ref } : {}),
266296
};
267297
});

0 commit comments

Comments
 (0)