import assert from "node:assert/strict" import { describe, it } from "node:test" import { normalizeImportedGraphics, normalizeLegacyImageAttrs, } from "./docs-graphic-import.ts" import { extractGraphicPositionsFromDocx } from "./docx-position-import.ts" import { computeCropImageStyle } from "./docs-graphic-types.ts" function normalizeImportedTipTap(content: Record) { return normalizeImportedGraphics(normalizeLegacyImageAttrs(content)) } describe("richtext-import chain", () => { it("preserves placement and rotation through full chain", () => { const result = normalizeImportedTipTap({ type: "doc", content: [ { type: "paragraph", content: [ { type: "image", attrs: { src: "data:image/png;base64,abc", width: 200, height: 120, placement: "absolute", wrap: "square", x: 40, y: 20, rotationDeg: 15, floatSide: "right", }, }, ], }, ], }) const node = result.content?.[0] as { type?: string; attrs?: Record } assert.equal(node.type, "docsGraphic") assert.equal(node.attrs?.placement, "absolute") assert.equal(node.attrs?.x, 40) assert.equal(node.attrs?.y, 20) assert.equal(node.attrs?.rotationDeg, 15) assert.equal(node.attrs?.floatSide, "right") }) it("preserves crop attrs through full chain", () => { const result = normalizeImportedTipTap({ type: "doc", content: [ { type: "image", attrs: { src: "data:image/png;base64,abc", cropX: 0.1, cropY: 0.2, cropWidth: 0.8, cropHeight: 0.7, }, }, ], }) const node = result.content?.[0] as { attrs?: Record } assert.equal(node.attrs?.cropX, 0.1) assert.equal(node.attrs?.cropY, 0.2) assert.equal(node.attrs?.cropWidth, 0.8) assert.equal(node.attrs?.cropHeight, 0.7) }) }) describe("docx-position-import", () => { it("extractGraphicPositionsFromDocx parses inline extent", () => { const archive = { "word/document.xml": new TextEncoder().encode(` `), } const positions = extractGraphicPositionsFromDocx(archive) assert.equal(positions.length, 1) assert.equal(positions[0]?.width, 96) assert.equal(positions[0]?.height, 48) assert.equal(positions[0]?.placement, "inline") assert.equal(positions[0]?.wrap, "inline") }) }) describe("docs-graphic-types crop", () => { it("computeCropImageStyle returns styles when crop active", () => { const style = computeCropImageStyle( { cropX: 0.1, cropY: 0, cropWidth: 0.8, cropHeight: 1, cropShape: "rect", }, 240, 160, 800, 600 ) assert.ok(style.img.width) assert.equal(style.clipPath, undefined) }) })