Commit 5dadba71 authored by Fred Chasen's avatar Fred Chasen

Merge branch 'update_target_counters' into 'master'

Update target counters

Closes #74

See merge request tools/pagedjs!32
parents ee171cbb f88af9d5
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>
Reset counter page
</title>
<script src="../../../dist/paged.polyfill.js"></script>
<style>
:root{
font-size: 18px;
}
@page {
size: 6in 8in;
margin: 20mm 20mm;
}
@page frontmatter {
@bottom-right {
content: counter(page, lower-roman);
}
}
@page main {
@top-right {
content: counter(page);
}
}
/* @page main:first {
counter-reset: page;
} */
.front-matter, .toc {
page: frontmatter;
}
.chapter {
page: main;
}
#first-chapter {
counter-reset: page 1;
}
p {
line-height: 22px;
}
h1 {
font-size: 24px;
margin-top: 0;
}
a {
text-decoration: none;
color: currentColor;
}
nav a::after {
content: target-counter(attr(href), page);
float: right;
}
nav a.roman::after {
float: right;
content: target-counter(attr(href), page, lower-roman);
}
</style>
<style>
/* interface */
@media screen {
body {
background: whitesmoke;
}
.pagedjs_page {
background: white;
margin-bottom: 10px;
box-shadow: 0 0 0 1px rgba(0, 0,0,0.2);
}
.pagedjs_pages {
width: calc(var(--width) * 2);
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
margin: 0 auto;
}
.pagedjs_first_page {
margin-left: 50%;
}
}
</style>
</head>
<body>
<section class="front-matter" id="foreword">
<h1>Foreword</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean eros sapien, iaculis eget
egestas eu, tempus eu tellus. Aliquam in facilisis sapien. Nulla blandit, ligula vel auctor
facilisis, quam felis rhoncus arcu, non rhoncus nulla felis sed est. Pellentesque ac velit
arcu, placerat dignissim augue. Nulla vitae tortor in elit ultrices dictum. Quisque eget
massa at nisl malesuada sodales sed id est. Pellentesque vehicula venenatis justo, sit amet
vehicula leo laoreet eget. Donec vel urna quis metus feugiat vulputate eget ut urna. In
tristique semper diam ut adipiscing. Fusce sagittis congue purus scelerisque hendrerit.
Donec sit amet interdum massa.</p>
</section>
<section class="toc" id="TOC">
<nav>
<h1>Table of contents</h1>
<ul>
<li><a id="toc-preface" href="#preface" class="roman">Preface</a></li>
<li><a id="toc-first-chapter" href="#first-chapter">First Chapter</a></li>
<li><a href="#second-chapter">Second Chapter</a></li>
</ul>
</nav>
</section>
<section class="front-matter" id="preface">
<h1>Preface</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean eros sapien, iaculis eget
egestas eu, tempus eu tellus. Aliquam in facilisis sapien. Nulla blandit, ligula vel auctor
facilisis, quam felis rhoncus arcu, non rhoncus nulla felis sed est. Pellentesque ac velit
arcu, placerat dignissim augue. Nulla vitae tortor in elit ultrices dictum. Quisque eget
massa at nisl malesuada sodales sed id est. Pellentesque vehicula venenatis justo, sit amet
vehicula leo laoreet eget. Donec vel urna quis metus feugiat vulputate eget ut urna. In
tristique semper diam ut adipiscing. Fusce sagittis congue purus scelerisque hendrerit.
Donec sit amet interdum massa.</p>
</section>
<section class="chapter" id="first-chapter">
<h1>First Chapter</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean eros sapien, iaculis eget
egestas eu, tempus eu tellus. Aliquam in facilisis sapien. Nulla blandit, ligula vel auctor
facilisis, quam felis rhoncus arcu, non rhoncus nulla felis sed est. Pellentesque ac velit
arcu, placerat dignissim augue. Nulla vitae tortor in elit ultrices dictum. Quisque eget
massa at nisl malesuada sodales sed id est. Pellentesque vehicula venenatis justo, sit amet
vehicula leo laoreet eget. Donec vel urna quis metus feugiat vulputate eget ut urna. In
tristique semper diam ut adipiscing. Fusce sagittis congue purus scelerisque hendrerit.
Donec sit amet interdum massa.</p>
</section>
<section class="chapter" id="second-chapter">
<h1>Second Chapter</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean eros sapien, iaculis eget
egestas eu, tempus eu tellus. Aliquam in facilisis sapien. Nulla blandit, ligula vel auctor
facilisis, quam felis rhoncus arcu, non rhoncus nulla felis sed est. Pellentesque ac velit
arcu, placerat dignissim augue. Nulla vitae tortor in elit ultrices dictum. Quisque eget
massa at nisl malesuada sodales sed id est. Pellentesque vehicula venenatis justo, sit amet
vehicula leo laoreet eget. Donec vel urna quis metus feugiat vulputate eget ut urna. In
tristique semper diam ut adipiscing. Fusce sagittis congue purus scelerisque hendrerit.
Donec sit amet interdum massa.</p>
</section>
</body>
</html>
const TIMEOUT = 10000;
describe('roman-numerals', async () => {
let page;
let rendered;
beforeAll(async () => {
page = await loadPage('issues/roman-numerals/roman-numerals.html')
return page.rendered;
}, TIMEOUT)
afterAll(async () => {
if (!DEBUG) {
await page.close();
}
})
it('should render 5 pages', async () => {
let pages = await page.$$eval(".pagedjs_page", (r) => {
return r.length;
});
console.log("pages", pages)
expect(pages).toEqual(5);
})
it('Preface should be in Roman numerals', async () => {
let text = await page.$eval("#toc-preface", (r) => window.getComputedStyle(r, '::after').content);
expect(text).toContain("lower-roman");
})
it('First Chapter should be 1', async () => {
let text = await page.$eval("#toc-first-chapter", (r) => window.getComputedStyle(r, '::after').content);
expect(text).toContain("counter(target-counter");
})
if (!DEBUG) {
it('should create a pdf', async () => {
let pdf = await page.pdf(PDF_SETTINGS);
expect(pdf).toMatchPDFSnapshot(1);
expect(pdf).toMatchPDFSnapshot(4);
})
}
}
)
...@@ -45,15 +45,26 @@ class PuppeteerEnvironment extends NodeEnvironment { ...@@ -45,15 +45,26 @@ class PuppeteerEnvironment extends NodeEnvironment {
async loadPage(path) { async loadPage(path) {
let page = await this.global.browser.newPage(); let page = await this.global.browser.newPage();
page.addListener('pageerror', this.handleError);
page.addListener('error', this.handleError);
let renderedResolve, renderedReject; let renderedResolve, renderedReject;
page.rendered = new Promise(function(resolve, reject) { page.rendered = new Promise(function(resolve, reject) {
renderedResolve = resolve; renderedResolve = resolve;
renderedReject = reject; renderedReject = reject;
}); });
page.addListener('pageerror', (error) => {
this.handleError(error);
renderedReject(error);
});
page.addListener('error', (error) => {
this.handleError(error);
renderedReject(error);
});
// await page.exposeFunction('PuppeteerLogger', (msg, counter) => {
// console.log(msg, counter);
// });
await page.exposeFunction('onPagesRendered', (msg, width, height, orientation) => { await page.exposeFunction('onPagesRendered', (msg, width, height, orientation) => {
renderedResolve(msg, width, height, orientation); renderedResolve(msg, width, height, orientation);
}); });
......
...@@ -29,11 +29,21 @@ class TargetCounters extends Handler { ...@@ -29,11 +29,21 @@ class TargetCounters extends Handler {
}); });
let counter; let counter;
if (last !== first) { let style;
counter = last.name; let styleIdentifier;
}
funcNode.children.forEach((child) => {
if (child.type === "Identifier") {
if (!counter) {
counter = child.name;
} else if (!style) {
styleIdentifier = csstree.clone(child);
style = child.name;
}
}
})
let variable = "--" + UUID(); let variable = "target-counter-" + UUID();
selector.split(",").forEach((s) => { selector.split(",").forEach((s) => {
this.counterTargets[s] = { this.counterTargets[s] = {
...@@ -41,20 +51,25 @@ class TargetCounters extends Handler { ...@@ -41,20 +51,25 @@ class TargetCounters extends Handler {
args: args, args: args,
value: value, value: value,
counter: counter, counter: counter,
style: style,
selector: s, selector: s,
fullSelector: selector, fullSelector: selector,
variable: variable variable: variable
} }
}); });
// Replace with variable // Replace with counter
funcNode.name = "var"; funcNode.name = "counter";
funcNode.children = new csstree.List() funcNode.children = new csstree.List()
funcNode.children.appendData({ funcNode.children.appendData({
type: "Identifier", type: "Identifier",
loc: 0, loc: 0,
name: variable name: variable
}); });
if (styleIdentifier) {
funcNode.children.appendData({type: "Operator", loc: null, value: ","});
funcNode.children.appendData(styleIdentifier);
}
} }
} }
...@@ -63,7 +78,8 @@ class TargetCounters extends Handler { ...@@ -63,7 +78,8 @@ class TargetCounters extends Handler {
let target = this.counterTargets[name]; let target = this.counterTargets[name];
let split = target.selector.split("::"); let split = target.selector.split("::");
let query = split[0]; let query = split[0];
let queried = chunker.pagesArea.querySelectorAll(query + ":not([data-target-counter])");
let queried = chunker.pagesArea.querySelectorAll(query + ":not([data-" + target.variable + "])");
queried.forEach((selected, index) => { queried.forEach((selected, index) => {
// TODO: handle func other than attr // TODO: handle func other than attr
...@@ -75,13 +91,20 @@ class TargetCounters extends Handler { ...@@ -75,13 +91,20 @@ class TargetCounters extends Handler {
if (element) { if (element) {
let selector = UUID(); let selector = UUID();
selected.setAttribute("data-target-counter", selector); selected.setAttribute("data-" + target.variable, selector);
// TODO: handle other counter types (by query) // TODO: handle other counter types (by query)
if (target.counter === "page") { if (target.counter === "page") {
let pages = chunker.pagesArea.querySelectorAll(".pagedjs_page"); let pages = chunker.pagesArea.querySelectorAll(".pagedjs_page");
let pg = 0; let pg = 0;
for (var i = 0; i < pages.length; i++) { for (var i = 0; i < pages.length; i++) {
let styles = window.getComputedStyle(pages[i]);
let reset = styles["counter-reset"].replace("page", "").trim();
if (reset !== "none") {
pg = parseInt(reset);
}
pg += 1; pg += 1;
if (pages[i].contains( element )){ if (pages[i].contains( element )){
break; break;
} }
...@@ -92,8 +115,12 @@ class TargetCounters extends Handler { ...@@ -92,8 +115,12 @@ class TargetCounters extends Handler {
psuedo += "::" + split[1]; psuedo += "::" + split[1];
} }
// this.styleSheet.insertRule(`[data-target-counter="${selector}"]${psuedo} { content: "${pg}"; }`, this.styleSheet.cssRules.length); this.styleSheet.insertRule(`[data-${target.variable}="${selector}"] { counter-increment: ${target.variable} ${pg}; }`, this.styleSheet.cssRules.length);
this.styleSheet.insertRule(`[data-target-counter="${selector}"]${psuedo} { ${target.variable}: "${pg}" }`, this.styleSheet.cssRules.length); } else {
let value = element.getAttribute(`data-counter-${target.counter}-value`);
if (value) {
this.styleSheet.insertRule(`[data-${target.variable}="${selector}"] { counter-increment: ${target.variable} ${parseInt(value)}; }`, this.styleSheet.cssRules.length);
}
} }
} }
}); });
......
...@@ -790,6 +790,7 @@ class AtPage extends Handler { ...@@ -790,6 +790,7 @@ class AtPage extends Handler {
addPageAttributes(page, start, pages) { addPageAttributes(page, start, pages) {
let named = start.dataset.page; let named = start.dataset.page;
let index = pages.indexOf(page);
if (named) { if (named) {
page.name = named; page.name = named;
......
...@@ -117,28 +117,28 @@ class Breaks extends Handler { ...@@ -117,28 +117,28 @@ class Breaks extends Handler {
return pageBreaks; return pageBreaks;
} }
addBreakAttributes(page) { addBreakAttributes(pageElement, page) {
let before = page.wrapper.querySelector("[data-break-before]"); let before = pageElement.querySelector("[data-break-before]");
let after = page.wrapper.querySelector("[data-break-after]"); let after = pageElement.querySelector("[data-break-after]");
let previousBreakAfter = page.wrapper.querySelector("[data-previous-break-after]"); let previousBreakAfter = pageElement.querySelector("[data-previous-break-after]");
if (before) { if (before) {
if (before.dataset.splitFrom) { if (before.dataset.splitFrom) {
page.splitFrom = before.dataset.splitFrom; page.splitFrom = before.dataset.splitFrom;
page.element.setAttribute("data-split-from", before.dataset.splitFrom); pageElement.setAttribute("data-split-from", before.dataset.splitFrom);
} else if (before.dataset.breakBefore && before.dataset.breakBefore !== "avoid") { } else if (before.dataset.breakBefore && before.dataset.breakBefore !== "avoid") {
page.breakBefore = before.dataset.breakBefore; page.breakBefore = before.dataset.breakBefore;
page.element.setAttribute("data-break-before", before.dataset.breakBefore); pageElement.setAttribute("data-break-before", before.dataset.breakBefore);
} }
} }
if (after && after.dataset) { if (after && after.dataset) {
if (after.dataset.splitTo) { if (after.dataset.splitTo) {
page.splitTo = after.dataset.splitTo; page.splitTo = after.dataset.splitTo;
page.element.setAttribute("data-split-to", after.dataset.splitTo); pageElement.setAttribute("data-split-to", after.dataset.splitTo);
} else if (after.dataset.breakAfter && after.dataset.breakAfter !== "avoid") { } else if (after.dataset.breakAfter && after.dataset.breakAfter !== "avoid") {
page.breakAfter = after.dataset.breakAfter; page.breakAfter = after.dataset.breakAfter;
page.element.setAttribute("data-break-after", after.dataset.breakAfter); pageElement.setAttribute("data-break-after", after.dataset.breakAfter);
} }
} }
...@@ -149,8 +149,8 @@ class Breaks extends Handler { ...@@ -149,8 +149,8 @@ class Breaks extends Handler {
} }
} }
afterLayout(pageElement, page) { afterPageLayout(pageElement, page) {
this.addBreakAttributes(page); this.addBreakAttributes(pageElement, page);
} }
} }
......
...@@ -14,11 +14,15 @@ class Counters extends Handler { ...@@ -14,11 +14,15 @@ class Counters extends Handler {
let property = declaration.property; let property = declaration.property;
if (property === "counter-increment") { if (property === "counter-increment") {
this.handleIncrement(declaration, rule); let inc = this.handleIncrement(declaration, rule);
dList.remove(dItem); if (inc) {
dList.remove(dItem);
}
} else if (property === "counter-reset") { } else if (property === "counter-reset") {
this.handleReset(declaration, rule); let reset = this.handleReset(declaration, rule);
dList.remove(dItem); if (reset) {
dList.remove(dItem);
}
} }
} }
...@@ -51,6 +55,11 @@ class Counters extends Handler { ...@@ -51,6 +55,11 @@ class Counters extends Handler {
let number = declaration.value.children.getSize() > 1 let number = declaration.value.children.getSize() > 1
&& declaration.value.children.last().value; && declaration.value.children.last().value;
let name = identifier && identifier.name; let name = identifier && identifier.name;
if (name === "page" || name.indexOf("target-counter-") === 0) {
return;
}
let selector = csstree.generate(rule.ruleNode.prelude); let selector = csstree.generate(rule.ruleNode.prelude);
let counter; let counter;
...@@ -60,7 +69,7 @@ class Counters extends Handler { ...@@ -60,7 +69,7 @@ class Counters extends Handler {
counter = this.counters[name]; counter = this.counters[name];
} }
counter.increments[selector] = { return counter.increments[selector] = {
selector: selector, selector: selector,
number: number || 1 number: number || 1
}; };
...@@ -72,15 +81,15 @@ class Counters extends Handler { ...@@ -72,15 +81,15 @@ class Counters extends Handler {
&& declaration.value.children.last().value; && declaration.value.children.last().value;
let name = identifier && identifier.name; let name = identifier && identifier.name;
let selector = csstree.generate(rule.ruleNode.prelude); let selector = csstree.generate(rule.ruleNode.prelude);
let counter; let counter;
if (!(name in this.counters)) { if (!(name in this.counters)) {
counter = this.addCounter(name); counter = this.addCounter(name);
} else { } else {
counter = this.counters[name]; counter = this.counters[name];
} }
counter.resets[selector] = { return counter.resets[selector] = {
selector: selector, selector: selector,
number: number || 0 number: number || 0
}; };
...@@ -153,6 +162,14 @@ class Counters extends Handler { ...@@ -153,6 +162,14 @@ class Counters extends Handler {
} }
} }
afterPageLayout(pageElement, page) {
let pgreset = pageElement.querySelectorAll("[data-counter-page-reset]");
pgreset.forEach((reset) => {
let value = reset.datasetCounterPageReset;
this.styleSheet.insertRule(`[data-page-number="${pageElement.dataset.pageNumber}"] { counter-reset: page ${value} }`, this.styleSheet.cssRules.length);
});
}
} }
export default Counters; export default Counters;
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