import { describe, it, expect } from 'vitest';
import { zipSync, strToU8 } from 'fflate';
import { styleCss, builtinStyleSheet, resolveStyle } from '../../src/lib/styles/styleSheet';
import { importDocx } from '../../src/lib/import/docx';
import { buildDocx } from '../../src/lib/export/docx';
// ODF kerns by default and Word does not, so only the off state is ever stored.
describe('pair kerning', () => {
it('renders font-kerning only where a style turns it off', () => {
const sheet = builtinStyleSheet();
expect(styleCss(sheet)).not.toContain('font-kerning');
sheet.paragraph.Standard.text = { ...sheet.paragraph.Standard.text, kerning: false };
expect(styleCss(sheet)).toContain('font-kerning: none');
});
it('inherits the off state down the parent chain', () => {
const sheet = builtinStyleSheet();
sheet.paragraph.Standard.text = { ...sheet.paragraph.Standard.text, kerning: false };
const css = styleCss(sheet);
const heading = css.slice(css.indexOf('[data-style="Heading 1"]'));
expect(heading.slice(0, heading.indexOf('}'))).toContain('font-kerning: none');
});
it('lets a style turn it back on under one that turns it off', () => {
const sheet = builtinStyleSheet();
sheet.paragraph.Standard.text = { ...sheet.paragraph.Standard.text, kerning: false };
sheet.paragraph.Title.text = { ...sheet.paragraph.Title.text, kerning: true };
const css = styleCss(sheet);
const title = css.slice(css.indexOf('[data-style="Title"]'));
expect(title.slice(0, title.indexOf('}'))).toContain('font-kerning: normal');
});
});
// w:kern names the smallest size pair kerning applies to. A file that declares it on the
// Title style alone kerns the title and nothing else — LibreOffice sets that title 0.34mm
// narrower, which is a line break where the text fills its column.
const W = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
const STYLES = `
`;
const docx = () =>
zipSync({
'word/document.xml': strToU8(`` +
`Title` +
`small` +
`body`),
'word/styles.xml': strToU8(STYLES),
});
describe('a Word style’s own w:kern', () => {
const sheet = importDocx(docx()).styles!;
it('kerns a style set at or above the size it names', () => {
expect(sheet.paragraph.Title.text.kerning).toBe(true);
});
it('leaves the body and a style set below that size unkerned', () => {
expect(sheet.paragraph.Standard.text.kerning).toBe(false);
expect(resolveStyle(sheet, 'Small').text.kerning).toBe(false);
});
it('survives a round trip through the DOCX export', async () => {
const doc = importDocx(docx());
const out = await buildDocx(doc.content as never, undefined, 'portrait', undefined, null, 'A4', doc.styles);
const again = importDocx(out).styles!;
expect(again.paragraph.Title.text.kerning).toBe(true);
expect(again.paragraph.Standard.text.kerning).toBe(false);
});
});