Commit 05d121f3 authored by Guillaume's avatar Guillaume

resolves #248 avoid break inside table cell

parent f0943b9b
Pipeline #615 passed with stage
in 4 minutes and 35 seconds
<!DOCTYPE html PUBLIC>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>break-inside-avoid-table-cell</title>
<script src="../../../../dist/paged.polyfill.js"></script>
<style>
@page {
size: 210mm 100mm;
border: 1px solid #cfc2c2;
}
table {
border-collapse: collapse;
}
table, th, td {
border: 1px solid black;
}
tr, td {
break-inside: avoid;
}
</style>
</head>
<body>
<table>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>a</td>
<td>b</td>
<td>c</td>
<td>d</td>
<td>e</td>
</tr>
<tr>
<td>f</td>
<td>g</td>
<td>h</td>
<td>i</td>
<td>j</td>
</tr>
<tr>
<td>k</td>
<td>l</td>
<td>m</td>
<td>n</td>
<td>o</td>
</tr>
<tr>
<td>
<p>Sed sollicitudin ac neque at tincidunt. Proin gravida neque sit amet euismod imperdiet.</p>
<p>Nunc eu faucibus mi, nec tincidunt turpis. In mi lacus, sagittis et <em>iaculis</em> id, tincidunt vitae dui. Sed <strong>aliquet ornare ornare</strong>.</p>
<p>Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Vivamus iaculis finibus nisl in pharetra.</p>
</td>
<td><p>Lorem ipsum dolor sit amet</p></td>
<td><p>Lorem ipsum dolor sit amet</p></td>
<td><p>Lorem ipsum dolor sit amet</p></td>
<td><p>Lorem ipsum dolor sit amet</p></td>
</tr>
</tbody>
</table>
</body>
</html>
const TIMEOUT = 10000; // Some book might take longer than this to renderer
describe("break-inside-avoid-table-cell", () => {
let page;
beforeAll(async () => {
page = await loadPage("breaks/break-inside/break-inside-avoid/break-inside-avoid-table-cell.html");
return page.rendered;
}, TIMEOUT);
afterAll(async () => {
if (!DEBUG) {
await page.close();
}
});
it("should render 2 pages", async () => {
let pages = await page.$$eval(".pagedjs_page", (r) => {
return r.length;
});
expect(pages).toEqual(2);
});
if (!DEBUG) {
it("should create a pdf", async () => {
let pdf = await page.pdf(PDF_SETTINGS);
expect(pdf).toMatchPDFSnapshot(1);
expect(pdf).toMatchPDFSnapshot(2);
});
}
});
......@@ -112,7 +112,7 @@ class Chunker {
this.content = content;
this.charsPerBreak = [];
this.maxChars;
this.maxChars = this.settings.maxChars;
if (content) {
this.flow(content, renderTo);
......
import {getBoundingClientRect, getClientRects} from "../utils/utils";
import {
breakInsideAvoidParentNode,
child,
cloneNode,
findElement,
......@@ -15,6 +16,7 @@ import {
needsPreviousBreakAfter,
nodeAfter,
nodeBefore,
parentOf,
previousSignificantNode,
prevValidNode,
rebuildAncestors,
......@@ -480,7 +482,12 @@ class Layout {
// Check if it is a float
let isFloat = false;
if (isElement(node)) {
// Check if the node is inside a break-inside: avoid table cell
const insideTableCell = parentOf(node, "TD", rendered);
if (insideTableCell && window.getComputedStyle(insideTableCell)["break-inside"] === "avoid") {
// breaking inside a table cell produces unexpected result, as a workaround, we forcibly avoid break inside in a cell.
prev = insideTableCell;
} else if (isElement(node)) {
let styles = window.getComputedStyle(node);
isFloat = styles.getPropertyValue("float") !== "none";
skip = styles.getPropertyValue("break-inside") === "avoid";
......@@ -511,7 +518,7 @@ class Layout {
if (!range && isText(node) &&
node.textContent.trim().length &&
window.getComputedStyle(node.parentNode)["break-inside"] !== "avoid") {
!breakInsideAvoidParentNode(node.parentNode)) {
let rects = getClientRects(node);
let rect;
......
......@@ -601,6 +601,40 @@ export function previousSignificantNode(sib) {
return null;
}
export function breakInsideAvoidParentNode(node) {
while ((node = node.parentNode)) {
if (node && node.dataset && node.dataset.breakInside === "avoid") {
return node;
}
}
return null;
}
/**
* Find a parent with a given node name.
* @param {Node} node - initial Node
* @param {string} nodeName - node name (eg. "TD", "TABLE", "STRONG"...)
* @param {Node} limiter - go up to the parent until there's no more parent or the current node is equals to the limiter
* @returns {Node|undefined} - Either:
* 1) The closest parent for a the given node name, or
* 2) undefined if no such node exists.
*/
export function parentOf(node, nodeName, limiter) {
if (limiter && node === limiter) {
return;
}
if (node.parentNode) {
while ((node = node.parentNode)) {
if (limiter && node === limiter) {
return;
}
if (node.nodeName === nodeName) {
return node;
}
}
}
}
/**
* Version of |nextSibling| that skips nodes that are entirely
* whitespace or comments.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment