The corpus leg out of one format and into the other compared block types and text, so anything the trip dropped below that passed. It now compares every attribute each node carries, with the values a format states in its own units excluded: proportional vs absolute column widths, and a formula's inline flag, which ODF has no place for. Two the stricter leg caught: a note lost the paragraph style it names and fell to the stock 10pt, and a link stored an attribute equal to its default.
29 lines
1.3 KiB
TypeScript
29 lines
1.3 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { importDocx } from '../../src/lib/import/docx';
|
|
import { buildDocx } from '../../src/lib/export/docx';
|
|
|
|
// Word paints a hyperlink through its Hyperlink character style, so a run carrying none
|
|
// is drawn like the text around it. `plain` carries that; ODF links are never plain
|
|
// (LibreOffice paints every text:a — probed).
|
|
type N = { type: string; attrs?: any; content?: N[]; marks?: any[]; text?: string };
|
|
|
|
function texts(node: N, out: N[] = []): N[] {
|
|
if (node.type === 'text') out.push(node);
|
|
for (const c of node.content ?? []) texts(c, out);
|
|
return out;
|
|
}
|
|
|
|
describe('an editor link round-trips as an editor link', () => {
|
|
it('keeps its blue through DOCX', async () => {
|
|
const doc: N = { type: 'doc', content: [{ type: 'paragraph', content: [
|
|
{ type: 'text', text: 'site', marks: [{ type: 'link', attrs: { href: 'https://example.com' } }] },
|
|
] }] };
|
|
const bytes = await buildDocx(doc as any, { top: 2, bottom: 2, left: 2, right: 2 }, 'portrait');
|
|
const back = importDocx(bytes).content as unknown as N;
|
|
const link = texts(back)[0]?.marks?.find((m: any) => m.type === 'link');
|
|
expect(link?.attrs.href).toBe('https://example.com');
|
|
// Absent is the attribute's default: not plain, the same as an explicit false.
|
|
expect(link?.attrs.plain).toBeFalsy();
|
|
});
|
|
});
|