This project aims to create a simple alternative to cut up content into pages for printing and PDF generation in browsers.
6 | Paginate for Print is available as ES6 modules, as CommonJS modules and as the simplest version as a bundled JavaScript file that can be used directly in a browser.
11 | For examples on how to use it, check the source code of the above mentioned examples. The available configuration options can be found in the list of default config options.
12 |
27 |
28 |
The Malay Archipelago
29 |
37 |
The Malay Archipelago is a book by the British naturalist Alfred Russel Wallace that chronicles his scientific exploration, during the eight-year period 1854 to 1862, of the southern portion of the Malay Archipelago including Malaysia, Singapore,
38 | the islands of Indonesia, then known as the Dutch East Indies, and the island of New Guinea. It was published in two volumes in 1869, delayed by Wallace's ill health and the work needed to describe the many specimens he brought
39 | home. The book went through ten editions in the nineteenth century; it has been reprinted many times since, and has been translated into at least eight languages.
40 |
The book described each island that he visited in turn, giving a detailed account of its physical and human geography, its volcanoes, and the variety of animals of plants that he found and collected. At the same time, he describes his
41 | experiences, the difficulties of travel, and the help he received from the different peoples that he met. The preface notes that he travelled over 14,000 miles and collected 125,660 natural history specimens, mostly of insects though
42 | also with thousands of molluscs, birds, mammals and reptiles.
43 |
The Malay Archipelago attracted many reviews, with interest from scientific, geographic, church and general periodicals. Reviewers noted and sometimes disagreed with various of his theories, especially the division of fauna and flora along
44 | what soon became known as the Wallace line, natural selection and uniformitarianism. Nearly all agreed that he had provided an interesting and comprehensive account of the geography, natural history, and peoples of the
45 | archipelago, which was little known to their readers at the time, and that he had collected an astonishing number of specimens. The book is much cited, and is Wallace's most successful, both commercially and as a piece of literature.
46 |
Context
47 |
In 1847, Wallace and his friend Henry Walter Bates, both in their early twenties,agreed that they would jointly make a collecting trip to the Amazon "towards solving the problem of origin of species"; Charles Darwin's book on the Origin of Species was not published until 11 years later, in 1859, itself precipitated by a famous letter from Wallace which described the theory in outline.They had been inspired by reading the American entomologist William Henry Edwards's pioneering 1847 book A Voyage Up the River Amazon, with a residency at Pará.Bates stayed in the Amazons for 11 years, going on to write The Naturalist on the River Amazons (1863); Wallace, ill with fever, went home in 1852 with thousands of specimens, some for science and some for sale. The ship and his collection
52 | were destroyed by fire at sea near the Guianas. Rather than giving up, Wallace wrote about the Amazon in both prose and poetry, and then set sail again, this time for the Malay Archipelago.
54 |
55 |
Publication
56 |
The Malay Archipelago was first published in 1869 in two volumes by Macmillan (London), and the same year in one volume by Harper & Brothers (New York). Wallace returned to England in 1862, but explains in the Preface that given the
57 | large quantity of specimens and his poor health after his stay in the tropics, it took a long time. He noted that he could at once have printed his notes and journals, but felt that doing that would have been disappointing and unhelpful. Instead,
58 | therefore, he waited until he had published papers on his discoveries, and other scientists had described and named as new species some 2,000 of his beetles (Coleoptera), and over 900 Hymenoptera including 200 new species of ant.
59 | The book went through 10 editions, with the last published in 1890.
62 |
Overview
63 |
71 |
The preface summarizes Wallace’s travels, the thousands of specimens he collected, and some of the results from their analysis after his return to England. In the preface he notes that he travelled over 14,000 miles and collected 125,660
72 | specimens, mostly of insects: 83,200 beetles, 13,100 butterflies and moths, 13,400 other insects. He also returned to England 7,500 "shells" (such as molluscs), 8,050 birds, 310 mammals and 100 reptiles.
73 |
76 |
77 |
The book is dedicated to Charles Darwin, but as Wallace explains in the preface, he has chosen to avoid discussing the evolutionary implications of his discoveries. Instead he confines himself to the "interesting facts of the problem,
78 | whose solution is to be found in the principles developed by Mr. Darwin",so from a scientific point of view, the book is largely a descriptive natural history. This modesty belies the fact that while in Sarawak in 1855 Wallace wrote the paper On the Law which has Regulated the Introduction of New Species,
80 | concluding with the evolutionary "Sarawak Law", "Every species has come into existence coincident both in space and time with a closely allied species", three years before he fatefully wrote to Darwin proposing the concept of natural selection.
81 |
84 |
85 |
The first chapter describes the physical geography and geology of the islands with particular attention to the role of volcanoes and earthquakes. It also discusses the overall pattern of the flora and fauna including the fact that
86 | the islands can be divided, by what would eventually become known as the Wallace line, into two parts, those whose animals are more closely related to those of Asia and those whose fauna is closer to that of Australia.
87 |
The following chapters describe in detail the places Wallace visited. Wallace includes numerous observations on the people, their languages, ways of living, and social organization, as well as on the plants and animals found in each location.
88 | He talks about the biogeographic patterns he observes and their implications for natural history, in terms both of the movement of speciesand of the geologic history of the region. He also narrates some of his personal experiences during his travels. The final chapter is an overview of the ethnic, linguistic, and cultural divisions among the people who live in the region and
90 | speculation about what such divisions might indicate about their history.
91 |
Illustrations
92 |
100 |
The illustrations are, according to the Preface, made from Wallace's own sketches, photographs, or specimens. Wallace thanks Walter and Henry Woodbury for some photographs of scenery and native people. He acknowledges William Wilson Saunders
101 | and Mr Pascoe for horned flies and very rare Longhorn beetles: all the rest were from his own enormous collection.
102 |
103 |
104 |
105 |
106 |
107 |
--------------------------------------------------------------------------------
/demo/paginate-for-print-two-column.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
35 |
36 |
The Malay Archipelago
37 |
45 |
The Malay Archipelago is a book by the British naturalist Alfred Russel Wallace that chronicles his scientific exploration, during the eight-year period 1854 to 1862, of the southern portion of the Malay Archipelago including Malaysia, Singapore,
46 | the islands of Indonesia, then known as the Dutch East Indies, and the island of New Guinea. It was published in two volumes in 1869, delayed by Wallace's ill health and the work needed to describe the many specimens he brought
47 | home. The book went through ten editions in the nineteenth century; it has been reprinted many times since, and has been translated into at least eight languages.
48 |
The book described each island that he visited in turn, giving a detailed account of its physical and human geography, its volcanoes, and the variety of animals of plants that he found and collected. At the same time, he describes his
49 | experiences, the difficulties of travel, and the help he received from the different peoples that he met. The preface notes that he travelled over 14,000 miles and collected 125,660 natural history specimens, mostly of insects though
50 | also with thousands of molluscs, birds, mammals and reptiles.
51 |
The Malay Archipelago attracted many reviews, with interest from scientific, geographic, church and general periodicals. Reviewers noted and sometimes disagreed with various of his theories, especially the division of fauna and flora along
52 | what soon became known as the Wallace line, natural selection and uniformitarianism. Nearly all agreed that he had provided an interesting and comprehensive account of the geography, natural history, and peoples of the
53 | archipelago, which was little known to their readers at the time, and that he had collected an astonishing number of specimens. The book is much cited, and is Wallace's most successful, both commercially and as a piece of literature.
54 |
Context
55 |
In 1847, Wallace and his friend Henry Walter Bates, both in their early twenties,agreed that they would jointly make a collecting trip to the Amazon "towards solving the problem of origin of species"; Charles Darwin's book on the Origin of Species was not published until 11 years later, in 1859, itself precipitated by a famous letter from Wallace which described the theory in outline.They had been inspired by reading the American entomologist William Henry Edwards's pioneering 1847 book A Voyage Up the River Amazon, with a residency at Pará.Bates stayed in the Amazons for 11 years, going on to write The Naturalist on the River Amazons (1863); Wallace, ill with fever, went home in 1852 with thousands of specimens, some for science and some for sale. The ship and his collection
60 | were destroyed by fire at sea near the Guianas. Rather than giving up, Wallace wrote about the Amazon in both prose and poetry, and then set sail again, this time for the Malay Archipelago.
62 |
63 |
Publication
64 |
The Malay Archipelago was first published in 1869 in two volumes by Macmillan (London), and the same year in one volume by Harper & Brothers (New York). Wallace returned to England in 1862, but explains in the Preface that given the
65 | large quantity of specimens and his poor health after his stay in the tropics, it took a long time. He noted that he could at once have printed his notes and journals, but felt that doing that would have been disappointing and unhelpful. Instead,
66 | therefore, he waited until he had published papers on his discoveries, and other scientists had described and named as new species some 2,000 of his beetles (Coleoptera), and over 900 Hymenoptera including 200 new species of ant.
67 | The book went through 10 editions, with the last published in 1890.
70 |
Overview
71 |
79 |
The preface summarizes Wallace’s travels, the thousands of specimens he collected, and some of the results from their analysis after his return to England. In the preface he notes that he travelled over 14,000 miles and collected 125,660
80 | specimens, mostly of insects: 83,200 beetles, 13,100 butterflies and moths, 13,400 other insects. He also returned to England 7,500 "shells" (such as molluscs), 8,050 birds, 310 mammals and 100 reptiles.
81 |
84 |
85 |
The book is dedicated to Charles Darwin, but as Wallace explains in the preface, he has chosen to avoid discussing the evolutionary implications of his discoveries. Instead he confines himself to the "interesting facts of the problem,
86 | whose solution is to be found in the principles developed by Mr. Darwin",so from a scientific point of view, the book is largely a descriptive natural history. This modesty belies the fact that while in Sarawak in 1855 Wallace wrote the paper On the Law which has Regulated the Introduction of New Species,
88 | concluding with the evolutionary "Sarawak Law", "Every species has come into existence coincident both in space and time with a closely allied species", three years before he fatefully wrote to Darwin proposing the concept of natural selection.
89 |
92 |
93 |
The first chapter describes the physical geography and geology of the islands with particular attention to the role of volcanoes and earthquakes. It also discusses the overall pattern of the flora and fauna including the fact that
94 | the islands can be divided, by what would eventually become known as the Wallace line, into two parts, those whose animals are more closely related to those of Asia and those whose fauna is closer to that of Australia.
95 |
The following chapters describe in detail the places Wallace visited. Wallace includes numerous observations on the people, their languages, ways of living, and social organization, as well as on the plants and animals found in each location.
96 | He talks about the biogeographic patterns he observes and their implications for natural history, in terms both of the movement of speciesand of the geologic history of the region. He also narrates some of his personal experiences during his travels. The final chapter is an overview of the ethnic, linguistic, and cultural divisions among the people who live in the region and
98 | speculation about what such divisions might indicate about their history.
99 |
Illustrations
100 |
108 |
The illustrations are, according to the Preface, made from Wallace's own sketches, photographs, or specimens. Wallace thanks Walter and Henry Woodbury for some photographs of scenery and native people. He acknowledges William Wilson Saunders
109 | and Mr Pascoe for horned flies and very rare Longhorn beetles: all the rest were from his own enormous collection.
110 |
111 |
112 |
113 |
114 |
115 |
--------------------------------------------------------------------------------
/src/apply-layout.js:
--------------------------------------------------------------------------------
1 | import {matchesSelector} from "./matches-selector"
2 | import {ContentCutter} from "./cut-content"
3 | import {PageCounterArab, PageCounterRoman} from "./page-counters"
4 | import {createToc} from "./create-toc"
5 |
6 | export class LayoutApplier {
7 |
8 | constructor(config) {
9 | this.config = config
10 | this.bodyFlowObjects = []
11 | //this.currentChapter = false
12 | //this.currentSection = false
13 | this.currentFragment = -1
14 |
15 | /* pageCounters contains all the page counters we use in a book --
16 | * typically these are two -- roman for the frontmatter and arab for the main
17 | * body contents.
18 | */
19 | this.pageCounters = {
20 | arab: new PageCounterArab(),
21 | roman: new PageCounterRoman()
22 | }
23 |
24 | this.cutter = new ContentCutter(this.config)
25 |
26 | }
27 |
28 | initiate() {
29 | // Create div for layout
30 | let layoutDiv = document.createElement('div'),
31 | flowedElement = this.config['flowFromElement'] ? this.config['flowFromElement'] : document.body,
32 | chapterStartSelector = this.config['chapterStartSelector'],
33 | sectionStartSelector = this.config['sectionStartSelector'],
34 | dividerSelector = chapterStartSelector + ',' + sectionStartSelector,
35 | dividers = flowedElement.querySelectorAll(dividerSelector),
36 | range = document.createRange(), nextChapter = false,
37 | nextSection = false,
38 | flowTo = this.config['flowToElement'] ? this.config['flowToElement'] : document.body
39 |
40 | layoutDiv.id = 'pagination-layout'
41 | for (let i = 0; i < dividers.length; i++) {
42 | let flowObject = {
43 | chapter: false,
44 | section: false
45 | }
46 | if (nextChapter) {
47 | flowObject.chapter = nextChapter
48 | nextChapter = false
49 | }
50 | if (nextSection) {
51 | flowObject.section = nextSection
52 | nextSection = false
53 | }
54 | range.setStart(flowedElement.firstChild, 0)
55 | range.setEnd(dividers[i], 0)
56 | flowObject.fragment = range.extractContents()
57 | this.bodyFlowObjects.push(flowObject)
58 |
59 | let extraElement = flowObject.fragment.querySelectorAll(
60 | dividerSelector)[1]
61 | if (extraElement && extraElement.parentElement) {
62 | extraElement.parentElement.removeChild(extraElement)
63 | }
64 | if (matchesSelector(dividers[i],
65 | chapterStartSelector)) {
66 | let tempNode = flowedElement.querySelector(this.config['chapterTitleSelector'])
67 | if (!tempNode) {
68 | tempNode = document.createElement('div')
69 | }
70 | tempNode = tempNode.cloneNode(true)
71 | nextChapter = document.createDocumentFragment()
72 | while (tempNode.firstChild) {
73 | nextChapter.appendChild(tempNode.firstChild)
74 | }
75 | } else {
76 | let tempNode = flowedElement.querySelector(this.config['sectionTitleSelector']).cloneNode(true)
77 | nextSection = document.createDocumentFragment()
78 | while (tempNode.firstChild) {
79 | nextSection.appendChild(tempNode.firstChild)
80 | }
81 | }
82 |
83 | if (i === 0) {
84 | if (flowObject.fragment.textContent.trim().length ===
85 | 0 && flowObject.fragment.querySelectorAll(
86 | 'img,svg,canvas,hr').length === 0) {
87 | this.bodyFlowObjects.pop()
88 | }
89 | }
90 | }
91 |
92 | let flowObject = {
93 | chapter: false,
94 | section: false
95 | }
96 | if (nextChapter) {
97 | flowObject.chapter = nextChapter
98 | }
99 | if (nextSection) {
100 | flowObject.section = nextSection
101 | }
102 |
103 | flowObject.fragment = document.createDocumentFragment()
104 |
105 | while (flowedElement.firstChild) {
106 | flowObject.fragment.appendChild(flowedElement.firstChild)
107 | }
108 |
109 |
110 | this.bodyFlowObjects.push(flowObject)
111 |
112 | flowTo.appendChild(layoutDiv)
113 |
114 | this.paginateDivision(layoutDiv, 'arab')
115 |
116 | }
117 |
118 | paginateDivision(layoutDiv, pageCounterStyle) {
119 | if (++this.currentFragment < this.bodyFlowObjects.length) {
120 | let newContainer = document.createElement('div')
121 | layoutDiv.appendChild(newContainer)
122 | newContainer.classList.add('pagination-body')
123 | newContainer.classList.add('pagination-body-' + this.currentFragment)
124 | if (this.bodyFlowObjects[this.currentFragment].section) {
125 | this.currentSection = this.bodyFlowObjects[
126 | this.currentFragment].section
127 | newContainer.classList.add('pagination-section')
128 | }
129 | if (this.bodyFlowObjects[this.currentFragment].chapter) {
130 | this.currentChapter = this.bodyFlowObjects[
131 | this.currentFragment].chapter
132 | newContainer.classList.add('pagination-chapter')
133 | }
134 | this.flowElement(this.bodyFlowObjects[
135 | this.currentFragment].fragment,
136 | newContainer, pageCounterStyle, this.bodyFlowObjects[
137 | this.currentFragment].section,
138 | this.bodyFlowObjects[this.currentFragment].chapter
139 | )
140 | } else {
141 | this.currentChapter = false
142 | this.currentSection = false
143 | this.pageCounters[pageCounterStyle].numberPages()
144 | if (this.config['enableFrontmatter']) {
145 | layoutDiv.insertBefore(document.createElement('div'),
146 | layoutDiv.firstChild)
147 | layoutDiv.firstChild.classList.add(
148 | 'pagination-frontmatter')
149 | let flowObject = {
150 | fragment: document.createDocumentFragment()
151 | }
152 | if (this.config['frontmatterFlowFromElement']) {
153 | let fmNode = this.config['frontmatterFlowFromElement']
154 | while (fmNode.firstChild) {
155 | flowObject.fragment.appendChild(fmNode.firstChild)
156 | }
157 | }
158 | if (this.config['numberPages']) {
159 | flowObject.fragment.appendChild(createToc())
160 | }
161 | this.flowElement(flowObject.fragment, layoutDiv.firstChild,
162 | 'roman')
163 | }
164 | }
165 |
166 | }
167 |
168 | fillPage(node, container, pageCounterStyle) {
169 |
170 | let lastPage = this.createPage(container, pageCounterStyle),
171 | clonedNode = node.cloneNode(true),
172 | footnoteSelector = this.config['footnoteSelector'],
173 | topfloatSelector = this.config['topfloatSelector'],
174 | that = this
175 |
176 | lastPage.appendChild(node)
177 |
178 | let overflow = this.cutter.cutToFit(lastPage)
179 |
180 | let topfloatsLength = lastPage.querySelectorAll(topfloatSelector).length
181 |
182 | if (topfloatsLength > 0) {
183 | let topfloats = clonedNode.querySelectorAll(topfloatSelector)
184 |
185 | for (let i = 0; i < topfloatsLength; i++) {
186 | lastPage.previousSibling.appendChild(topfloats[i])
187 | }
188 | while (lastPage.firstChild) {
189 | lastPage.removeChild(lastPage.firstChild)
190 | }
191 | node = clonedNode.cloneNode(true)
192 | lastPage.appendChild(node)
193 | overflow = this.cutter.cutToFit(lastPage)
194 | }
195 |
196 | let footnotes = lastPage.querySelectorAll(footnoteSelector)
197 | let footnotesLength = footnotes.length
198 | if (footnotesLength > 0) {
199 |
200 | while (lastPage.nextSibling.firstChild) {
201 | lastPage.nextSibling.removeChild(lastPage.nextSibling.firstChild)
202 | }
203 |
204 | for (let i = 0; i < footnotesLength; i++) {
205 | let clonedFootnote = footnotes[i].cloneNode(true)
206 | lastPage.nextSibling.appendChild(clonedFootnote)
207 | }
208 |
209 | while (lastPage.firstChild) {
210 | lastPage.removeChild(lastPage.firstChild)
211 | }
212 |
213 | lastPage.appendChild(clonedNode)
214 |
215 | overflow = this.cutter.cutToFit(lastPage)
216 | for (let i = lastPage.querySelectorAll(footnoteSelector).length; i <
217 | footnotesLength; i++) {
218 | let oldFn = lastPage.nextSibling.children[i]
219 |
220 | while (oldFn.firstChild) {
221 | oldFn.removeChild(oldFn.firstChild)
222 | }
223 | }
224 | }
225 |
226 |
227 | if (overflow.firstChild && overflow.firstChild.textContent.trim()
228 | .length === 0 && ['P','DIV'].indexOf(overflow.firstChild.nodeName) !== -1) {
229 | overflow.removeChild(overflow.firstChild)
230 | }
231 |
232 | if (lastPage.firstChild &&
233 | lastPage.firstChild.nodeType != 3 &&
234 | lastPage.firstChild.textContent.trim().length === 0 &&
235 | lastPage.firstChild.querySelectorAll('img,svg,canvas').length ===
236 | 0) {
237 | lastPage.removeChild(lastPage.firstChild)
238 |
239 |
240 | } else if (overflow.firstChild && lastPage.firstChild) {
241 | setTimeout(function() {
242 | that.fillPage(overflow, container,
243 | pageCounterStyle)
244 | }, 1)
245 | } else {
246 | this.finish(container, pageCounterStyle)
247 | }
248 | }
249 |
250 | createPage(container, pageCounterClass) {
251 | let page = document.createElement('div'),
252 | contentsContainer = document.createElement('div'),
253 | mainContentsContainer = document.createElement('div'),
254 | topfloats = document.createElement('div'),
255 | contents = document.createElement('div'),
256 | footnotes = document.createElement('div')
257 |
258 |
259 | page.classList.add('pagination-page')
260 | contentsContainer.classList.add('pagination-contents-container')
261 | mainContentsContainer.classList.add(
262 | 'pagination-main-contents-container')
263 |
264 | if (this.currentChapter || this.currentSection) {
265 |
266 | let header = document.createElement('div')
267 |
268 | header.classList.add('pagination-header')
269 |
270 | if (this.currentChapter) {
271 |
272 | let chapterHeader = document.createElement('span')
273 |
274 | chapterHeader.classList.add('pagination-header-chapter')
275 | chapterHeader.appendChild(this.currentChapter.cloneNode(
276 | true))
277 | header.appendChild(chapterHeader)
278 | }
279 |
280 | if (this.currentSection) {
281 |
282 | let sectionHeader = document.createElement('span')
283 | sectionHeader.classList.add('pagination-header-section')
284 | sectionHeader.appendChild(this.currentSection.cloneNode(
285 | true))
286 | header.appendChild(sectionHeader)
287 | }
288 | page.appendChild(header)
289 | }
290 |
291 | topfloats.classList.add('pagination-topfloats')
292 | //topfloats.appendChild(document.createElement('p'))
293 |
294 | contents.classList.add('pagination-contents')
295 |
296 | footnotes.classList.add('pagination-footnotes')
297 | footnotes.appendChild(document.createElement('p'))
298 |
299 | mainContentsContainer.appendChild(topfloats)
300 | mainContentsContainer.appendChild(contents)
301 | mainContentsContainer.appendChild(footnotes)
302 |
303 | page.appendChild(mainContentsContainer)
304 |
305 | if (this.config['numberPages']) {
306 |
307 | let pagenumberField = document.createElement('div')
308 | pagenumberField.classList.add('pagination-pagenumber')
309 | pagenumberField.classList.add('pagination-' +
310 | pageCounterClass)
311 |
312 | page.appendChild(pagenumberField)
313 | }
314 |
315 | container.appendChild(page)
316 | return contents
317 | }
318 |
319 | flowElement(overflow, container, pageCounterStyle) {
320 | let that = this
321 | setTimeout(function() {
322 | that.fillPage(overflow, container,
323 | pageCounterStyle)
324 | }, 1)
325 | }
326 |
327 | finish(container, pageCounterStyle) {
328 | let layoutDiv = container.parentElement
329 | if (this.config['alwaysEven'] && container.querySelectorAll(
330 | '.pagination-page').length % 2 === 1) {
331 | this.createPage(container, pageCounterStyle)
332 | }
333 | if (container.classList.contains('pagination-body')) {
334 | this.paginateDivision(layoutDiv, pageCounterStyle)
335 | if (this.bodyFlowObjects.length===this.currentFragment && this.config['enableFrontmatter']===false) {
336 | this.config['callback']()
337 | }
338 | } else {
339 | this.pageCounters[pageCounterStyle].numberPages()
340 | this.config['callback']()
341 | }
342 | }
343 |
344 | }
345 |
--------------------------------------------------------------------------------
/bundle/paginate-for-print.js:
--------------------------------------------------------------------------------
1 | (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.paginateForPrint = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o