feat : i dont even know what am i doing right now
CI / Verify (push) Successful in 2m20s
CI / Build immutable images and deploy (push) Successful in 2m57s

This commit is contained in:
2026-10-10 04:33:08 +07:00 Unverified
parent e723471707
commit 35f9dc40ba
10 changed files with 994 additions and 63 deletions
@@ -0,0 +1,54 @@
// @vitest-environment happy-dom
import type { ReactNode } from "react";
import { renderToStaticMarkup } from "react-dom/server";
import { describe, expect, it, vi } from "vitest";
import { createExtraSheet, mergeExtraSheetRange, updateExtraSheetCells } from "@/lib/guides/extra-sheet";
import type { PublicGuide } from "@/lib/guides/queries";
vi.mock("next/font/local", () => ({ default: () => ({ className: "font" }) }));
vi.mock("./guide-page-shell", () => ({
GuidePageShell: ({ children }: { children: ReactNode }) => <main>{children}</main>,
publicSectionTitle: (title: string) => title,
}));
vi.mock("./guide-image-export", () => ({
GuideImageExport: ({ children }: { children: ReactNode }) => <aside data-export>{children}</aside>,
}));
vi.mock("./guide-export-branding", () => ({ GuideExportBranding: () => null }));
const { StructuredGuideShell } = await import("./structured-guide");
describe("extra sheet public rendering", () => {
it("renders full merged bounds and vertical alignment in both the guide and export", () => {
let sequence = 0;
let sheet = createExtraSheet((prefix) => `${prefix}-${++sequence}`);
sheet = mergeExtraSheetRange(sheet, { start: { row: 1, column: 1 }, end: { row: 2, column: 3 } });
sheet = updateExtraSheetCells(sheet, [{ row: 1, column: 1 }], {
value: "<p><strong>Merged text</strong></p>", alignment: "center", verticalAlignment: "middle", backgroundColor: "#123456",
});
const guide = {
id: "guide", slug: "guide", coverUrl: "/cover.png", character: { splashImageUrl: null },
availableSections: [{ id: "extra", slug: "notes", title: "Notes" }],
extras: [{ id: "extra", slug: "notes", title: "Notes", rows: [{
id: "row", heading: "Details", body: "", percent: null, highlights: [], catalogItems: [],
imageUrl: null, backgroundColor: null, sheet,
}] }],
} as unknown as PublicGuide;
const container = document.createElement("div");
container.innerHTML = renderToStaticMarkup(<StructuredGuideShell guide={guide} section="notes" />);
const tables = container.querySelectorAll("table");
expect(tables).toHaveLength(2);
for (const table of tables) {
expect(table.querySelectorAll("col")).toHaveLength(3);
expect(table.querySelectorAll("tbody tr")).toHaveLength(2);
expect(table.querySelectorAll("td")).toHaveLength(1);
const cell = table.querySelector("td")!;
expect(cell.rowSpan).toBe(2);
expect(cell.colSpan).toBe(3);
expect(cell.style.verticalAlign).toBe("middle");
expect(cell.style.textAlign).toBe("center");
expect(cell.querySelector("strong")?.textContent).toBe("Merged text");
}
});
});
+25 -16
View File
@@ -57,6 +57,7 @@ import { normalizeExtraRichText } from "@/lib/rich-text";
import {
DEFAULT_EXTRA_SHEET_COLUMN_WIDTH,
extraSheetUsedRange,
extraSheetMergeMap,
} from "@/lib/guides/extra-sheet";
import { publicGuideSections } from "@/lib/guides/public-sections";
import { cn } from "@/lib/utils";
@@ -1231,6 +1232,7 @@ function ExtraSectionContent({
<div className={cn("relative z-10 grid gap-5 md:grid-cols-2", exporting && "grid-cols-2")}>
{extra.rows.map((row) => {
const displaySheet = row.sheet ? extraSheetUsedRange(row.sheet) : null;
const merges = displaySheet ? extraSheetMergeMap(displaySheet) : null;
return (
<Card
key={row.id}
@@ -1325,23 +1327,30 @@ function ExtraSectionContent({
</TableRow>
</TableHeader>
<TableBody>
{displaySheet.rows.map((sheetRow) => (
{displaySheet.rows.map((sheetRow, rowIndex) => (
<TableRow key={sheetRow.id}>
{displaySheet.columns.map((column) => (
<TableCell
key={column.id}
className="border-l first:border-l-0 whitespace-normal"
style={{
backgroundColor: sheetRow.backgrounds?.[column.id],
textAlign: sheetRow.alignments?.[column.id] ?? "left",
}}
>
<RichTextContent
html={normalizeExtraRichText(sheetRow.cells[column.id] ?? "")}
className="extra-sheet-text extra-sheet-text--public"
/>
</TableCell>
))}
{displaySheet.columns.map((column, columnIndex) => {
const merge = merges?.get(`${rowIndex}:${columnIndex}`);
if (merge && (merge.start.row !== rowIndex || merge.start.column !== columnIndex)) return null;
return (
<TableCell
rowSpan={merge ? merge.end.row - rowIndex + 1 : undefined}
colSpan={merge ? merge.end.column - columnIndex + 1 : undefined}
key={column.id}
className="border-l first:border-l-0 whitespace-normal"
style={{
backgroundColor: sheetRow.backgrounds?.[column.id],
textAlign: sheetRow.alignments?.[column.id] ?? "left",
verticalAlign: sheetRow.verticalAlignments?.[column.id] ?? "top",
}}
>
<RichTextContent
html={normalizeExtraRichText(sheetRow.cells[column.id] ?? "")}
className="extra-sheet-text extra-sheet-text--public"
/>
</TableCell>
);
})}
</TableRow>
))}
</TableBody>