Signal drop!
Relay (operand.online) is unreachable.
Usually, a dropped signal means an upgrade is happening. Hold on!
Sorry, no connección.
Hang in there while we get back on track
gram: docs
> ./packages/core/src/prosemirror/styles/resolvedStyleAttrs.ts
/**
* Shared helper for projecting a resolved paragraph style onto ProseMirror
* paragraph node attrs.
*
* Both `applyStyle` (toolbar style picker) and the Enter handler's
* next-style switch need to write the same set of style-controlled attrs.
* Keeping the projection in one place ensures the two paths stay in sync —
* a style applied via the picker and a style applied on Enter produce
* identical paragraph attrs.
*/
import type { ResolvedParagraphStyle } from './styleResolver';
import { computeListRendering, type NumberingMap } from '../../docx/numberingParser';
/**
* The paragraph attrs a style definition controls. Applying a style resets
* every one of these to the style's value (or `null` to clear), so a prior
* style's properties (e.g. a heading's spacing) never leak through. Returns
* a partial attrs object to merge over the paragraph's existing attrs.
*/
export function paragraphAttrsFromResolvedStyle(
resolved: ResolvedParagraphStyle
): Record<string, unknown> {
const ppr = resolved.paragraphFormatting;
const runFormatting = resolved.runFormatting;
const hasRunFormatting = !!runFormatting && Object.keys(runFormatting).length > 0;
return {
alignment: ppr?.alignment ?? null,
spaceBefore: ppr?.spaceBefore ?? null,
spaceAfter: ppr?.spaceAfter ?? null,
lineSpacing: ppr?.lineSpacing ?? null,
lineSpacingRule: ppr?.lineSpacingRule ?? null,
indentLeft: ppr?.indentLeft ?? null,
indentRight: ppr?.indentRight ?? null,
indentFirstLine: ppr?.indentFirstLine ?? null,
hangingIndent: ppr?.hangingIndent ?? null,
contextualSpacing: ppr?.contextualSpacing ?? null,
keepNext: ppr?.keepNext ?? null,
keepLines: ppr?.keepLines ?? null,
pageBreakBefore: ppr?.pageBreakBefore ?? null,
outlineLevel: ppr?.outlineLevel ?? null,
// The style's run defaults drive the caret height in an empty paragraph
// and the formatting typed text inherits (see EmptyParagraphFormatExtension).
defaultTextFormatting: hasRunFormatting ? runFormatting : null,
};
}
/**
* The list attrs a style's `w:pPr/w:numPr` controls (numbering reference plus
* the baked marker-rendering attrs that `toProseDoc` normally derives from
* `listRendering` at load time). Returns null when the style defines no
* numbering — applying such a style leaves any existing list attrs alone, so
* directly-applied (toolbar) lists survive a style switch the way they do in
* Word, where numbering is not cleared by applying an unnumbered style.
*
* When the style does define numbering, the full attr group is reset so a
* previous list's marker attrs never leak into the new one. Without the
* numbering definitions the marker template can't be resolved and the painter
* falls back to a plain decimal marker.
*/
export function listAttrsFromResolvedStyle(
resolved: ResolvedParagraphStyle,
numbering: NumberingMap | null | undefined
): Record<string, unknown> | null {
const numPr = resolved.paragraphFormatting?.numPr;
if (!numPr || numPr.numId === undefined || numPr.numId === 0) return null;
const rendering = numbering ? computeListRendering(numPr, numbering) : null;
const level = numbering?.getLevel(numPr.numId, numPr.ilvl ?? 0);
const attrs: Record<string, unknown> = {
numPr: { numId: numPr.numId, ilvl: numPr.ilvl ?? 0 },
// The numbering belongs to the style — mark it so a save doesn't
// materialize a direct <w:numPr> (see ParagraphAttrs.numPrFromStyle).
numPrFromStyle: { numId: numPr.numId, ilvl: numPr.ilvl ?? 0 },
listNumFmt: rendering?.numFmt ?? null,
listIsBullet: rendering?.isBullet ?? null,
listMarker: rendering?.marker ?? null,
listMarkerHidden: rendering?.markerHidden ?? null,
listMarkerFontFamily: rendering?.markerFontFamily ?? null,
listMarkerFontSize: rendering?.markerFontSize ?? null,
listMarkerSuffix: rendering?.markerSuffix ?? null,
listLevelNumFmts: rendering?.levelNumFmts ?? null,
listAbstractNumId: rendering?.abstractNumId ?? null,
listStartOverride: rendering?.startOverride ?? null,
};
// The numbering level's own indents apply beneath the style's (ECMA-376
// numbering pPr sits below the style in the cascade) — use them only where
// the style doesn't specify its own indentation.
const ppr = resolved.paragraphFormatting;
if (level?.pPr) {
if (ppr?.indentLeft === undefined && level.pPr.indentLeft !== undefined) {
attrs.indentLeft = level.pPr.indentLeft;
}
const styleHasFirstLine =
ppr?.indentFirstLine !== undefined || ppr?.hangingIndent !== undefined;
if (!styleHasFirstLine) {
if (level.pPr.indentFirstLine !== undefined) {
attrs.indentFirstLine = level.pPr.indentFirstLine;
}
if (level.pPr.hangingIndent !== undefined) {
attrs.hangingIndent = level.pPr.hangingIndent;
}
}
}
return attrs;
}