Files
Reactive-Resume/packages/docx/src/html-to-docx.test.ts
T
JamesGoslingsandAmruth Pillai e96a51f31c feat(editor): add multicolor highlight with auto-contrast text (#3110)
* feat(editor): add multicolor highlight with auto-contrast text

Enable the Tiptap Highlight extension in multicolor mode, replacing the
single-color yellow toggle with a full color picker (16 presets + custom).
When the chosen highlight color is perceptually dark, text inside the mark
automatically renders white for readability.

Changes span the full pipeline:
- Editor: ColorPicker UI, extended renderHTML for contrast detection
- PDF: normalizeMarkElements preserves data-color as inline style
- DOCX: mergeStyle reads actual background-color from <mark>
- Utils: new isDarkColor() luminance helper

Backward-compatible: legacy <mark> without data-color still renders yellow.

Resolves #3109

* fix: handle multicolor highlight edge cases

---------

Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
2026-06-01 14:58:15 +02:00

72 lines
2.6 KiB
TypeScript

// @vitest-environment happy-dom
import { describe, expect, it } from "vitest";
import { htmlToParagraphs } from "./html-to-docx";
describe("htmlToParagraphs", () => {
it("returns [] for empty / whitespace-only input", () => {
expect(htmlToParagraphs("")).toEqual([]);
expect(htmlToParagraphs(" \n ")).toEqual([]);
});
it("returns at least one paragraph for a simple <p> element", () => {
const result = htmlToParagraphs("<p>Hello world</p>");
expect(result.length).toBeGreaterThanOrEqual(1);
});
it("converts plain text nodes at the body root into a paragraph", () => {
const result = htmlToParagraphs("Just some plain text");
expect(result.length).toBe(1);
});
it("emits separate paragraphs for multiple top-level blocks", () => {
const result = htmlToParagraphs("<p>One</p><p>Two</p><p>Three</p>");
expect(result.length).toBeGreaterThanOrEqual(3);
});
it("treats <h1>..<h6> as block-level paragraphs (one per heading)", () => {
const result = htmlToParagraphs("<h1>A</h1><h2>B</h2><h3>C</h3>");
expect(result.length).toBe(3);
});
it("renders nested <strong>, <em>, <u>, <s> inline styling without throwing", () => {
const result = htmlToParagraphs("<p><strong>Bold</strong> <em>italic</em> <u>under</u> <s>strike</s></p>");
expect(result.length).toBe(1);
});
it("renders links and lists without throwing", () => {
const html = '<p><a href="https://example.com">link</a></p><ul><li>One</li><li>Two</li></ul>';
const result = htmlToParagraphs(html);
expect(result.length).toBeGreaterThanOrEqual(2);
});
it("accepts custom font + size config without throwing", () => {
const result = htmlToParagraphs("<p>Hello</p>", {
font: "Roboto",
size: 22,
color: "111111",
linkColor: "0563C1",
});
expect(result.length).toBe(1);
});
it("ignores HTML comments and script/style tags at the root", () => {
// Comments at root and script tags don't add paragraph output.
const result = htmlToParagraphs("<!--c--><script>x</script><p>Hello</p>");
expect(result.length).toBeGreaterThanOrEqual(1);
});
it("applies default yellow shading for <mark> without background-color", () => {
const result = htmlToParagraphs("<p><mark>highlighted</mark></p>");
const json = JSON.stringify(result[0]);
// TextRun with shading should contain "FFFF00" in serialized output
expect(json).toContain("FFFF00");
});
it("reads custom background-color from <mark> style for shading fill", () => {
const result = htmlToParagraphs('<p><mark style="background-color: rgba(204, 255, 204, 1)">green</mark></p>');
const json = JSON.stringify(result[0]);
expect(json).toContain("CCFFCC");
});
});