// Imposition for booklet(s) // // This script re-arrange the pages of your document in order to make an imposed sheet layouts for printing. // Two pages per sheet, double-sided // modified from: https://gitlab.com/pagedjs-plugins/booklet-imposition/-/blob/master/imposition.js?ref_type=heads class Booklet extends Paged.Handler { constructor(chunker, polisher, caller) { super(chunker, polisher, caller); this.pagedbooklet; this.sourceSize; this.pageStart; this.pageEnd; } onAtPage(node, item, list) { } onDeclaration(declaration, dItem, dList, rule) { if (declaration.property == "--paged-layout") { if (declaration.value.value.includes("booklet")) { console.log('BOOKLET'); // console.log(declaration.property, declaration, rule); this.pagedbooklet = true; let valuesBooklet = declaration.value.value.trim().split(/\s+/); let index = valuesBooklet.indexOf("booklet"); /* Set first page of the imposition */ const rawStart = valuesBooklet[index + 1]; if (rawStart) { const parsedStart = parseInt(rawStart, 10); this.pageStart = Number.isNaN(parsedStart) ? 1 : parsedStart; } else { this.pageStart = 1; } /* Set last page of the imposition */ const rawEnd = valuesBooklet[index + 2]; if (rawEnd) { const parsedEnd = parseInt(rawEnd, 10); this.pageEnd = Number.isNaN(parsedEnd) ? undefined : parsedEnd; } else { this.pageEnd = undefined; } console.log(`START: ${this.pageStart} END: ${this.pageEnd}`); } } } afterRendered(pages) { /* Verify this.pageEnd */ if (!this.pageEnd) { let allPagesBefore = document.querySelectorAll(".pagedjs_page").length; this.pageEnd = allPagesBefore; } /* Verify this.pageStart */ if (this.pageStart == 0) { this.pageStart = 1; } else if (this.pageStart % 2 == 0) { this.pageStart = this.pageStart - 1; } /* Launch when printing */ //window.addEventListener("beforeprint", (evenement) => { const reorder = (pages) => { let containerPages = document.querySelector(".pagedjs_pages"); /* Delete pages we don't want*/ pages.forEach(page => { let id = parseInt(page.id.replace('page-', '')); if (id < this.pageStart || id > this.pageEnd) { let pageSelect = document.querySelector('#' + page.id); pageSelect.remove(); } }); /* Reset page counter */ let reset = parseInt(this.pageStart) - 1; containerPages.style.counterReset = "page " + reset; let format = document.querySelector(".pagedjs_page"); /* Width of page without bleed, extract the first number of calc() function */ let width = getCSSCustomProp("--pagedjs-width", format); let numbers = width .match(/[0-9]+/g) .map(function (n) { return + (n); }); width = parseInt(numbers[0]); /* Height of page with bleed, addition of all the numbers of calc() function*/ let height = getCSSCustomProp("--pagedjs-height", format); numbers = height .match(/[0-9]+/g) .map(function (n) { return + (n); }); const reducer = (previousValue, currentValue) => previousValue + currentValue; height = numbers.reduce(reducer); /* Bleed of the page */ let bleed = getCSSCustomProp("--pagedjs-bleed-top", format); let bleedNum = parseInt(bleed); /* Spread and half-spread*/ let spread = width * 2 + bleedNum * 2; let spreadHalf = width + bleedNum; // Add CSS to have pages in spread // // - change size of the page when printing (actually, sheet size) // - flex properties // - delete bleeds inside spread */ var newSize = `@media print{ @page{ size: ${spread}mm ${height}mm; } .pagedjs_pages { width: auto; } } @media screen{ .pagedjs_pages{ max-width: calc(var(--pagedjs-width) * 2); } } .pagedjs_pages { display: flex !important; flex-wrap: wrap; transform: none !important; height: 100% !important; min-height: 100%; max-height: 100%; overflow: visible; } .pagedjs_page { margin: 0; padding: 0; max-height: 100%; min-height: 100%; height: 100% !important; } .pagedjs_sheet { margin: 0; padding: 0; max-height: 100%; min-height: 100%; height: 100% !important; } body{ --pagedjs-bleed-right-left: 0mm; } .pagedjs_left_page{ z-index: 20; width: calc(var(--pagedjs-bleed-left) + var(--pagedjs-pagebox-width))!important; } .pagedjs_left_page .pagedjs_bleed-right .pagedjs_marks-crop { border-color: transparent; } .pagedjs_right_page, .pagedjs_right_page .pagedjs_sheet{ width: calc(var(--pagedjs-bleed-right-right) + var(--pagedjs-pagebox-width))!important; } .pagedjs_right_page .pagedjs_sheet{ grid-template-columns: [bleed-left] var(--pagedjs-bleed-right-left) [sheet-center] 1fr [bleed-right] var(--pagedjs-bleed-right-right); } .pagedjs_right_page .pagedjs_bleed-left{ display: none; } .pagedjs_right_page .pagedjs_bleed-top .pagedjs_marks-crop:nth-child(1), .pagedjs_right_page .pagedjs_bleed-bottom .pagedjs_marks-crop:nth-child(1){ width: 0!important; } .pagedjs_first_page { margin-left: 0; } body{ margin: 0 } .pagedjs_page:nth-of-type(even){ break-after: always; } .pagedjs_page, .pagedjs_sheet{ width: ${spreadHalf - 0.1}mm!important; } `; // Add style for the arrangement of the pages if (this.pagedbooklet == true) { let style = document.createElement("style"); style.textContent = newSize; document .head .appendChild(style); var number_of_pages = document.getElementsByClassName("pagedjs_page").length; var pages_array = []; // If the page count isn't a multiple of 4, we need to pad the array with blank // pages so we have the correct number of pages for a booklet. // // ex. [1, 2, 3, 4, 5, 6, 7, 8, 9, blank, blank, blank] let modulo = number_of_pages % 4; let additional_pages = 0; if (modulo != 0) { additional_pages = 4 - modulo; } for (i = 0; i < additional_pages; i++) { let added_page = document.createElement("div"); added_page .classList .add("pagedjs_page", "added"); added_page.id = `page-${this.pageEnd + i + 1}`; added_page.innerHTML = `