Files
edentext/src/lib/editor/extensions/blockFontSize.ts
T
Steffen Becker c82a78cc6a feat: character spacing, and a line box that multiplies its two halves
Word's Title style tightens by -0.5pt, so a title came out ~3mm wide of
LibreOffice's. letterSpacingPt joins TextProps and rides both formats
(w:spacing, fo:letter-spacing).

Line spacing needed the same care: it is proportional to the font's natural
line height, so the factor and that height are now separate CSS variables and
editor.css multiplies them in one place. Before, whichever of the two was
declared nearer simply overwrote the other — a block carrying its own font
silently dropped the style's spacing.
2026-08-08 08:30:05 +00:00

73 lines
2.3 KiB
TypeScript

import { Extension } from '@tiptap/core';
import { cssFontFamily, singleLineHeight } from '../../styles/styleSheet';
// Font of the paragraph mark (Word's w:pPr/w:rPr, ODF the paragraph's own text
// properties): the block's CSS strut, so it sets every line's minimum height and what
// text typed into an empty one looks like. Size is a CSS length; null = style default.
declare module '@tiptap/core' {
interface Commands<ReturnType> {
blockFontSize: {
setBlockFontSize: (size: string | null) => ReturnType;
};
}
}
export const BlockFontSize = Extension.create({
name: 'blockFontSize',
addOptions() {
return {
types: ['paragraph', 'heading'] as string[],
};
},
addGlobalAttributes() {
return [
{
types: this.options.types,
attributes: {
fontSize: {
default: null,
parseHTML: (element: HTMLElement) =>
element.getAttribute('data-block-font-size') || null,
renderHTML: (attributes: Record<string, unknown>) => {
if (!attributes.fontSize) return {};
const size = String(attributes.fontSize);
return {
'data-block-font-size': size,
style: `font-size: ${size}`,
};
},
},
fontFamily: {
default: null,
parseHTML: (element: HTMLElement) =>
element.getAttribute('data-block-font-family') || null,
renderHTML: (attributes: Record<string, unknown>) => {
if (!attributes.fontFamily) return {};
const family = String(attributes.fontFamily);
// Single spacing is this family's natural line height; the paragraph's own
// spacing factor multiplies it (editor.css).
return {
'data-block-font-family': family,
style: `font-family: ${cssFontFamily(family)}; --natural-line: ${singleLineHeight(family)}`,
};
},
},
},
},
];
},
addCommands() {
return {
setBlockFontSize: (size: string | null) => ({ commands }) => {
return this.options.types
.map((type) => commands.updateAttributes(type, { fontSize: size }))
.some((r) => r);
},
};
},
});