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.
73 lines
2.3 KiB
TypeScript
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);
|
|
},
|
|
};
|
|
},
|
|
});
|