test: a decorated section, a run under an underlining style, a wider sweep
Three regression tests for what a 5000-seed sweep turned up, each checked to fail without its fix. A run repeating its style's own plain underline is lossy by design, so the generator no longer puts one under a named style.
This commit is contained in:
1 parent
ab133f7966
commit
7e2eb53ddc
4 files changed
+92
-1
No files matched your search
+4
-1
@@ -41,7 +41,10 @@ function marks(r: Rng, heading = false): N[] | undefined {
|
||||
const attrs: N = {};
|
||||
if (maybe(r, 0.3)) attrs.lineStyle = pick(r, ['dotted', 'double', 'dashed']);
|
||||
if (maybe(r, 0.2)) attrs.lineColor = '#FF0000';
|
||||
out.push({ type: 'underline', ...(Object.keys(attrs).length ? { attrs } : {}) });
|
||||
// A user style may underline plainly, and a run repeating exactly that is suppressed
|
||||
// on import — under a named style a run underlines only in its own shape or colour.
|
||||
const line = Object.keys(attrs).length ? { attrs } : null;
|
||||
if (line || !heading) out.push({ type: 'underline', ...(line ?? {}) });
|
||||
}
|
||||
if (maybe(r, 0.1)) {
|
||||
out.push(maybe(r, 0.25) ? { type: 'strike', attrs: { lineStyle: 'double' } } : { type: 'strike' });
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
// A document whose first master page carries no header at all: the watermark and the fold
|
||||
// marks mint one, and a section break puts a second master page after it.
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { buildOdt } from '../../src/lib/export/odt';
|
||||
import { importOdt } from '../../src/lib/import/odt';
|
||||
import { EMPTY_PAGE_DECOR, DEFAULT_WATERMARK } from '../../src/lib/storage/pageDecor';
|
||||
|
||||
const doc = {
|
||||
type: 'doc',
|
||||
content: [
|
||||
{ type: 'paragraph', content: [{ type: 'text', text: 'one' }] },
|
||||
{ type: 'paragraph', attrs: { sectionBreak: true, breakBefore: 'page' }, content: [{ type: 'text', text: 'two' }] },
|
||||
],
|
||||
} as any;
|
||||
|
||||
// The first section has no zone of its own and the second does, so the first master page
|
||||
// is written self-closing while the second carries a header.
|
||||
const hf = {
|
||||
header: null, footer: null, pageCount: 2,
|
||||
sections: [{ header: null, footer: null },
|
||||
{ header: { type: 'paragraph', content: [{ type: 'text', text: 'zwei' }] }, footer: null }],
|
||||
} as never;
|
||||
|
||||
const build = (decor: unknown, foldMarks = false) => buildOdt(doc, undefined, undefined, hf, undefined,
|
||||
undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined,
|
||||
decor as never, undefined, undefined, foldMarks);
|
||||
|
||||
describe('page decor across a section break', () => {
|
||||
const watermark = { ...DEFAULT_WATERMARK, text: 'DRAFT', angle: 135 };
|
||||
|
||||
it('reads the watermark back off the first page', async () => {
|
||||
const res = importOdt(await build({ ...EMPTY_PAGE_DECOR, watermark }));
|
||||
expect(res.decor.watermark).toEqual(watermark);
|
||||
});
|
||||
|
||||
it('gives every master page the shape', async () => {
|
||||
const res = importOdt(await build({ ...EMPTY_PAGE_DECOR, watermark }, true));
|
||||
expect(res.decor.watermark?.text).toBe('DRAFT');
|
||||
expect(res.foldMarks).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -33,6 +33,16 @@ describe('the side a section opens on', () => {
|
||||
expect(sides(importOdt(bytes))).toEqual([null, 'odd']);
|
||||
});
|
||||
|
||||
// The page layout takes the header band off the margin for the whole section, so a
|
||||
// master of it that writes no running zone puts its body up into the reserved band.
|
||||
it('keeps the band it reserved on every master of the section', async () => {
|
||||
const second = { ...EMPTY_HF_SET, headerFirst: zone, differentFirstPage: true,
|
||||
startsOn: 'odd' as const, margins: { top: 1.5, bottom: 2, left: 2, right: 2 } };
|
||||
const bytes = await buildOdt(doc, margins, 'portrait',
|
||||
{ ...hf, sections: [{ ...EMPTY_HF_SET, header: zone }, second] } as never);
|
||||
expect((importOdt(bytes).hfSections ?? [])[1]?.margins).toEqual(second.margins);
|
||||
});
|
||||
|
||||
it('round-trips through DOCX as w:type', async () => {
|
||||
const bytes = await buildDocx(doc, margins, 'portrait', hf as never);
|
||||
expect(strFromU8(unzipSync(bytes)['word/document.xml'])).toContain('<w:type w:val="oddPage"');
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
// A run underlining differently from the style it sits under: both importers suppress a
|
||||
// run that only repeats its style, and the shape and colour ride along with it.
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { buildOdt } from '../../src/lib/export/odt';
|
||||
import { importOdt } from '../../src/lib/import/odt';
|
||||
import { buildDocx } from '../../src/lib/export/docx';
|
||||
import { importDocx } from '../../src/lib/import/docx';
|
||||
import { builtinStyleSheet } from '../../src/lib/styles/styleSheet';
|
||||
|
||||
const sheet = builtinStyleSheet();
|
||||
sheet.paragraph['Unterstrichen'] = {
|
||||
name: 'Unterstrichen', parent: 'Standard', next: 'Standard', para: {}, text: { underline: true },
|
||||
};
|
||||
|
||||
const doc = {
|
||||
type: 'doc',
|
||||
content: [{
|
||||
type: 'paragraph',
|
||||
attrs: { styleName: 'Unterstrichen' },
|
||||
content: [
|
||||
{ type: 'text', text: 'rot', marks: [{ type: 'underline', attrs: { lineColor: '#FF0000' } }] },
|
||||
{ type: 'text', text: 'wellig', marks: [{ type: 'underline', attrs: { lineStyle: 'wavy' } }] },
|
||||
{ type: 'text', text: 'wie der Stil', marks: [{ type: 'underline' }] },
|
||||
],
|
||||
}],
|
||||
} as any;
|
||||
|
||||
const runs = (n: any) => n.content[0].content.map((c: any) => c.marks?.find((m: any) => m.type === 'underline')?.attrs ?? null);
|
||||
|
||||
describe.each([
|
||||
['odt', async () => importOdt(await buildOdt(doc, undefined, undefined, undefined, undefined, undefined, sheet)).content],
|
||||
['docx', async () => importDocx(await buildDocx(doc, undefined, undefined, undefined, undefined, undefined, sheet)).content],
|
||||
] as const)('a run under an underlining style (%s)', (_fmt, read) => {
|
||||
it('keeps its own colour and shape, and drops what the style already draws', async () => {
|
||||
expect(runs(await read())).toEqual([{ lineColor: '#FF0000' }, { lineStyle: 'wavy' }, null]);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user