diff --git a/specs/issues/roman-numerals/__image_snapshots__/roman-numerals-spec-js-roman-numerals-should-create-a-pdf-1-snap.png b/specs/issues/roman-numerals/__image_snapshots__/roman-numerals-spec-js-roman-numerals-should-create-a-pdf-1-snap.png new file mode 100644 index 0000000000000000000000000000000000000000..b056963a7ba87d1c07104198deae1f4670d8a0d2 Binary files /dev/null and b/specs/issues/roman-numerals/__image_snapshots__/roman-numerals-spec-js-roman-numerals-should-create-a-pdf-1-snap.png differ diff --git a/specs/issues/roman-numerals/__image_snapshots__/roman-numerals-spec-js-roman-numerals-should-create-a-pdf-2-snap.png b/specs/issues/roman-numerals/__image_snapshots__/roman-numerals-spec-js-roman-numerals-should-create-a-pdf-2-snap.png new file mode 100644 index 0000000000000000000000000000000000000000..eb736ee5ab1b574097d63915f38833c6f2f411ba Binary files /dev/null and b/specs/issues/roman-numerals/__image_snapshots__/roman-numerals-spec-js-roman-numerals-should-create-a-pdf-2-snap.png differ diff --git a/specs/issues/roman-numerals/roman-numerals.html b/specs/issues/roman-numerals/roman-numerals.html new file mode 100644 index 0000000000000000000000000000000000000000..85a9aeefd74e0e43f26d5eecefe815bd3c69f224 --- /dev/null +++ b/specs/issues/roman-numerals/roman-numerals.html @@ -0,0 +1,163 @@ + + + + + + + + Reset counter page + + + + + + + + + +
+

Foreword

+

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.

+
+
+ +
+
+

Preface

+

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.

+
+
+

First Chapter

+

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.

+
+
+

Second Chapter

+

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.

+
+ + diff --git a/specs/issues/roman-numerals/roman-numerals.spec.js b/specs/issues/roman-numerals/roman-numerals.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..84c45de0c18fec4153902992966f38b946f33604 --- /dev/null +++ b/specs/issues/roman-numerals/roman-numerals.spec.js @@ -0,0 +1,45 @@ +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); + }) + } + } +) diff --git a/specs/jest_helpers/puppeteer_environment.js b/specs/jest_helpers/puppeteer_environment.js index f93d9c1ef2802eee83918d35c5b5413cdf436221..d1aae06ce5628cd68cd2234c0fbacbe3e3b38f9e 100755 --- a/specs/jest_helpers/puppeteer_environment.js +++ b/specs/jest_helpers/puppeteer_environment.js @@ -45,15 +45,26 @@ class PuppeteerEnvironment extends NodeEnvironment { async loadPage(path) { let page = await this.global.browser.newPage(); - page.addListener('pageerror', this.handleError); - page.addListener('error', this.handleError); - let renderedResolve, renderedReject; page.rendered = new Promise(function(resolve, reject) { renderedResolve = resolve; 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) => { renderedResolve(msg, width, height, orientation); }); diff --git a/src/modules/generated-content/target-counters.js b/src/modules/generated-content/target-counters.js index a2e2b6117bb02a6f134dd909c5cf2ffaf25ead9f..601faca77919063b3fc0d81b4d10906bef1199d4 100644 --- a/src/modules/generated-content/target-counters.js +++ b/src/modules/generated-content/target-counters.js @@ -29,11 +29,21 @@ class TargetCounters extends Handler { }); let counter; - if (last !== first) { - counter = last.name; - } + let style; + 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) => { this.counterTargets[s] = { @@ -41,20 +51,25 @@ class TargetCounters extends Handler { args: args, value: value, counter: counter, + style: style, selector: s, fullSelector: selector, variable: variable } }); - // Replace with variable - funcNode.name = "var"; + // Replace with counter + funcNode.name = "counter"; funcNode.children = new csstree.List() funcNode.children.appendData({ type: "Identifier", loc: 0, name: variable }); + if (styleIdentifier) { + funcNode.children.appendData({type: "Operator", loc: null, value: ","}); + funcNode.children.appendData(styleIdentifier); + } } } @@ -63,7 +78,8 @@ class TargetCounters extends Handler { let target = this.counterTargets[name]; let split = target.selector.split("::"); 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) => { // TODO: handle func other than attr @@ -75,13 +91,20 @@ class TargetCounters extends Handler { if (element) { let selector = UUID(); - selected.setAttribute("data-target-counter", selector); + selected.setAttribute("data-" + target.variable, selector); // TODO: handle other counter types (by query) if (target.counter === "page") { let pages = chunker.pagesArea.querySelectorAll(".pagedjs_page"); let pg = 0; 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; + if (pages[i].contains( element )){ break; } @@ -92,8 +115,12 @@ class TargetCounters extends Handler { psuedo += "::" + split[1]; } - // this.styleSheet.insertRule(`[data-target-counter="${selector}"]${psuedo} { content: "${pg}"; }`, this.styleSheet.cssRules.length); - this.styleSheet.insertRule(`[data-target-counter="${selector}"]${psuedo} { ${target.variable}: "${pg}" }`, this.styleSheet.cssRules.length); + this.styleSheet.insertRule(`[data-${target.variable}="${selector}"] { counter-increment: ${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); + } } } }); diff --git a/src/modules/paged-media/atpage.js b/src/modules/paged-media/atpage.js index 05f3ed5e8e50cdeda2ba19375a85ec172538b8e4..f9203aef041e932d80529a162f11c71046c626ba 100644 --- a/src/modules/paged-media/atpage.js +++ b/src/modules/paged-media/atpage.js @@ -790,6 +790,7 @@ class AtPage extends Handler { addPageAttributes(page, start, pages) { let named = start.dataset.page; + let index = pages.indexOf(page); if (named) { page.name = named; diff --git a/src/modules/paged-media/breaks.js b/src/modules/paged-media/breaks.js index 240d8327fa97888bd87ea0cdb7c35c226e8c6226..851da2a72d433a693b805bf508c516837df97d0a 100644 --- a/src/modules/paged-media/breaks.js +++ b/src/modules/paged-media/breaks.js @@ -117,28 +117,28 @@ class Breaks extends Handler { return pageBreaks; } - addBreakAttributes(page) { - let before = page.wrapper.querySelector("[data-break-before]"); - let after = page.wrapper.querySelector("[data-break-after]"); - let previousBreakAfter = page.wrapper.querySelector("[data-previous-break-after]"); + addBreakAttributes(pageElement, page) { + let before = pageElement.querySelector("[data-break-before]"); + let after = pageElement.querySelector("[data-break-after]"); + let previousBreakAfter = pageElement.querySelector("[data-previous-break-after]"); if (before) { if (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") { 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.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") { 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 { } } - afterLayout(pageElement, page) { - this.addBreakAttributes(page); + afterPageLayout(pageElement, page) { + this.addBreakAttributes(pageElement, page); } } diff --git a/src/modules/paged-media/counters.js b/src/modules/paged-media/counters.js index b24f8625b759fc936e7f0694a5d962080b031b7d..f50ce97554a3619f3d333b03a394874ee05897a5 100644 --- a/src/modules/paged-media/counters.js +++ b/src/modules/paged-media/counters.js @@ -14,11 +14,15 @@ class Counters extends Handler { let property = declaration.property; if (property === "counter-increment") { - this.handleIncrement(declaration, rule); - dList.remove(dItem); + let inc = this.handleIncrement(declaration, rule); + if (inc) { + dList.remove(dItem); + } } else if (property === "counter-reset") { - this.handleReset(declaration, rule); - dList.remove(dItem); + let reset = this.handleReset(declaration, rule); + if (reset) { + dList.remove(dItem); + } } } @@ -51,6 +55,11 @@ class Counters extends Handler { let number = declaration.value.children.getSize() > 1 && declaration.value.children.last().value; let name = identifier && identifier.name; + + if (name === "page" || name.indexOf("target-counter-") === 0) { + return; + } + let selector = csstree.generate(rule.ruleNode.prelude); let counter; @@ -60,7 +69,7 @@ class Counters extends Handler { counter = this.counters[name]; } - counter.increments[selector] = { + return counter.increments[selector] = { selector: selector, number: number || 1 }; @@ -72,15 +81,15 @@ class Counters extends Handler { && declaration.value.children.last().value; let name = identifier && identifier.name; let selector = csstree.generate(rule.ruleNode.prelude); - let counter; + if (!(name in this.counters)) { counter = this.addCounter(name); } else { counter = this.counters[name]; } - counter.resets[selector] = { + return counter.resets[selector] = { selector: selector, number: number || 0 }; @@ -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;