Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Blank pages before the table of contents #172

Open
pranantardhie opened this issue Oct 31, 2023 · 1 comment
Open

Blank pages before the table of contents #172

pranantardhie opened this issue Oct 31, 2023 · 1 comment

Comments

@pranantardhie
Copy link

pranantardhie commented Oct 31, 2023

Introduction

Hi, I am using PagedJS v0.4.3. Using MacOS Sonoma

I have this HTML:

HTML
<html>
  <head>
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link
      href="https://fonts.googleapis.com/css2?family=Nunito:wght@100;300;400;500;700&display=swap"
      rel="stylesheet"
    />
    <link rel="stylesheet" type="text/css" href="../style.css" />
    <script src="../toc.js"></script>
    <script src="../paged.polyfill.js"></script>

    <script>
      class handlers extends Paged.Handler { constructor(chunker, polisher,
      caller) { super(chunker, polisher, caller); } beforeParsed(content) {
      createToc({ content: content, tocElement: "#toc", titleElements:
      ["h2:not(.cover-header)", "h3:not(.cover-header)"], }); } }
      Paged.registerHandlers(handlers);
    </script>
  </head>

  <body>
    <!-- 1.0 Cover Page -->
    <div class="cover-page">
      <h1>Standard Operation Procedures</h1>
      <h3 class="cover-header no-counter">Hosted PBX</h3>
      <h3 class="cover-header no-counter">{{time}}</h3>
      <img src="../0.svg" />
      <img src="../1.png" />
    </div>

    <!-- 2.0 Table of Contents -->
    <div class="table-of-contents">
      <h1 class="toc-header" id="toc-start">Table of Contents</h1>
      <ol id="toc">
        <!-- toc.js will automatically insert TOC here -->
      </ol>
    </div>

    ...rest
  </body>
</html>

The script for generating TOC:

Script
/**
 * Create a table of contents (TOC) based on the title elements within a specified content.
 *
 * @param {Object} config - Configuration object for the function.
 * @param {Element} config.content - The root element where the TOC will be generated from.
 * @param {string} config.tocElement - A CSS selector that specifies the element where the TOC will be appended.
 * @param {Array} config.titleElements - An array of CSS selectors indicating title elements.
 */
function createToc(config) {
  // Destructure the configuration object for easier access
  const { content, tocElement, titleElements } = config;

  // Locate the container where the TOC will be appended
  let tocElementDiv = content.querySelector(tocElement);

  // Create a new unordered list to house the TOC
  let tocUl = document.createElement("ul");
  tocUl.id = "list-toc-generated"; // Give it an ID for potential styling or scripting
  tocElementDiv.appendChild(tocUl); // Append the list to the container

  // Counter to generate unique IDs for title elements (if needed)
  let tocElementNbr = 0;

  // Loop over each title element selector
  for (var i = 0; i < titleElements.length; i++) {
    // Calculate the title hierarchy based on its position in the titleElements array
    let titleHierarchy = i + 1;

    // Select all elements in the content that match the current title selector
    let titleElement = content.querySelectorAll(titleElements[i]);

    titleElement.forEach(function (element) {
      // Add a generic class and data attribute to indicate its hierarchy
      element.classList.add("title-element");
      element.setAttribute("data-title-level", titleHierarchy);

      // If the element doesn't have an ID, create one
      tocElementNbr++;
      idElement = element.id;
      if (idElement == "") {
        element.id = "title-element-" + tocElementNbr;
      }
    });
  }

  // Select all title elements we previously modified
  let tocElements = content.querySelectorAll(".title-element");

  // Loop over each title element to create corresponding TOC list items
  for (var i = 0; i < tocElements.length; i++) {
    let tocElement = tocElements[i];

    // Create a new list item for the TOC
    let tocNewLi = document.createElement("li");

    // Add generic and hierarchy-specific classes
    tocNewLi.classList.add("toc-element");
    tocNewLi.classList.add(
      "toc-element-level-" + tocElement.dataset.titleLevel,
    );

    // Copy over other classes from the original title element (excluding the generic title-element class)
    let classTocElement = tocElement.classList;
    for (var n = 0; n < classTocElement.length; n++) {
      if (classTocElement[n] != "title-element") {
        tocNewLi.classList.add(classTocElement[n]);
      }
    }

    // Set the inner content of the list item to be a link to the original title element
    tocNewLi.innerHTML =
      '<a href="#' + tocElement.id + '">' + tocElement.innerHTML + "</a>";

    // Append the new list item to the TOC list
    tocUl.appendChild(tocNewLi);
  }
}

The CSS:

CSS
/* - * - * - * - * - * - * - * - * - * - */
/* 1.0 CSS to make A4 print preview as default web view */

@media screen {
  .pagedjs_pages {
    display: flex;
    width: calc(var(--pagedjs-width));
    flex: 0;
    flex-wrap: wrap;
    margin: 0 auto;
    justify-content: center;
  }

  .pagedjs_page {
    margin: 10mm;
    border: solid 1px gray;
  }
}

/* - * - * - * - * - * - * - * - * - * - */
/* 2.0 General Formatting */
html {
  font-family: "Nunito", sans-serif;
  height: auto;
}
h1 {
  border-bottom: 1px solid black;
  margin-bottom: 2rem;
  padding-bottom: 1rem;
}
h2 {
  border-bottom: 0.1875rem solid black;
  margin-bottom: 1rem;
  padding-bottom: 0.5rem;
}
p {
  text-align: justify;
  line-height: 1.4rem;
}
a {
  color: #347dbd;
}
a:hover {
  color: #fc814a;
}
mark {
  color: purple;
  background-color: inherit;
}
light-mark {
  color: purple;
}
img {
  max-width: calc(100% - 3rem);
}
.img-75mm {
  height: 75mm;
}

center {
  border: 0.5px solid gray;
  padding: 1.5rem;
}

pre {
  background-color: #f0f0f0;
  font-family: "Custom Mono", monospace;
  padding: 1rem;
  font-size: smaller;
  white-space: pre-wrap;
}
code {
  margin-bottom: 1.5rem;
  display: block;
}
figure {
  margin-block-start: 2rem;
  margin-block-end: 2rem;
  margin-inline-start: 0rem;
  margin-inline-end: 0rem;
}
figcaption {
  caption-side: top;
  padding-bottom: 0.75rem;
  border-bottom: 0.5px solid gray;
  margin-bottom: 1.5rem;
  color: gray;
  font-weight: bold;
}

/* - * - * - * - * - * - * - * - * - * - */
/* 3.1 Page Size */
@page {
  size: A4;
}

/* 3.2 Page Breaks */
.page-break {
  break-after: page;
}
h2:not(.no-break) {
  break-before: page;
  margin-block-start: 0rem;
  margin-block-end: 1.66rem;
}
h2.no-break:not(.top) {
  margin-block-start: 3rem;
  margin-block-end: 1.66rem;
}
h2.top {
  margin-block-start: 0rem;
  margin-block-end: 1.66rem;
}

h3:not(.top) {
  margin-block-start: 2.49rem;
  margin-block-end: 0.83rem;
}
h3.top {
  margin-block-start: 1.66rem;
  margin-block-end: 0.83rem;
}

/* 3.3 Page Numbers */
@page {
  @bottom-right {
    content: counter(page);
  }
}

/* We use the counter-reset class to prevent the page
numbers starting from the cover page, but rather
from the next page (table of contents) */
.counter-reset {
  counter-reset: page 1;
}

/* - * - * - * - * - * - * - * - * - * - */
/* 5.1 Table of Contents */
.table-of-contents {
  page: table-of-contents;
}
@page table-of-contents {
  @top-right {
    content: none;
  }
  @bottom-left {
    content: none;
  }
}

/* Additional CSS: Advanced Styling for TOC */
.toc-header {
  margin-bottom: 1rem;
  border-bottom: 0.375rem solid black;
}
.table-of-contents a,
.table-of-contents a:hover {
  font-family: "Nunito", sans-serif;
}

ol,
ul {
  padding-inline-start: 0px;
}

ol,
ul a {
  text-decoration: none;
}

.toc-element-level-1 a,
.toc-element-level-2 a {
  color: black;
}

/* set the style for the list numbering to none */
#list-toc-generated {
  list-style: none;
}

#list-toc-generated .toc-element a::after {
  content: target-counter(attr(href), page);
  float: right;
}

#list-toc-generated .toc-element-level-1 {
  border-bottom: 0.0625rem solid black;
  margin-top: 2rem;
  margin-bottom: 1rem;
  padding-bottom: 0.5rem;
  font-weight: bold;
}

/* counters */

#list-toc-generated {
  counter-reset: counterTocLevel1;
}

#list-toc-generated .toc-element-level-1 {
  counter-increment: counterTocLevel1;
  counter-reset: counterTocLevel2;
}

#list-toc-generated .toc-element-level-1::before {
  content: counter(counterTocLevel1) ". ";
  padding-right: 5px;
}

#list-toc-generated .toc-element-level-2 {
  counter-increment: counterTocLevel2;
  margin-bottom: 0.5rem;
}

#list-toc-generated .toc-element-level-2::before {
  content: counter(counterTocLevel1) "." counter(counterTocLevel2) " ";
  padding-right: 5px;
}

/* hack for leaders */

#list-toc-generated {
  overflow-x: hidden;
}

/* fake leading */
#list-toc-generated .toc-element-level-2::after {
  content: ".............................................."
    ".............................................."
    ".............................................." "........";
  float: left;
  width: 0;
  padding-left: 5px;
  letter-spacing: 2px;
}

#list-toc-generated .toc-element {
  display: flex;
}

#list-toc-generated .toc-element a::after {
  position: absolute;
  right: 0;
  background-color: white;
  padding-left: 6px;
}

#list-toc-generated .toc-element a {
  right: 0;
}

The Problem

Everything went well if I generate a table of contents worth 1 page:
image

But if there is more than 1 page, I got two blank pages then the full TOC:
image

As you can see, the 3.15 is missing. It is on page 64. You can see that there are number 64 in page 4, which means it renders the page number but not the link.

Any ideas what went wrong?

@julientaq
Copy link
Collaborator

the css for the toc is the culprit. Is it better without any of that css?

I can’t remember exactly, but i had the trouble, and fixed it. I believe i removed the float-right for the page number.
i need to dig a bit that code and see what’s wrong in there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants