Commit 9fc20fcf authored by Fred Chasen's avatar Fred Chasen
Browse files

Merge branch 'eslint' into 'master'

Track average length of text for checking for overflow & Eslint

See merge request !35
parents f7ba5416 6c883e30
module.exports = {
"env": {
"browser": true,
"commonjs": true,
"es6": true,
"node": true
},
"globals": {
},
"extends": "eslint:recommended",
"parserOptions": {
"sourceType": "module",
"ecmaVersion": 9
},
"rules": {
"indent": [
"error",
"tab",
{
"VariableDeclarator": { "var": 2, "let": 2, "const": 3 },
"SwitchCase" : 1
}
],
"linebreak-style": [
"error",
"unix"
],
"quotes": [
"warn",
"double"
],
"semi": [
"error",
"always"
],
"no-unused-vars" : ["warn"],
"no-console" : ["error", { allow: ["warn", "error"] }],
"no-unused-vars": [
"error",
{ "vars": "all", "args": "none" }
],
"no-mixed-spaces-and-tabs": ["error", "smart-tabs"],
"valid-jsdoc": ["warn"]
}
};
......@@ -9,6 +9,11 @@
 
<link rel="coverpage" href="assets/aurorae/images/cover.jpg" />
 
<script>
window.PagedConfig = {
after: (flow) => console.log(flow.performance)
}
</script>
<script src="../dist/paged.polyfill.js"></script>
 
<link href="assets/aurorae/book.css" rel="stylesheet" type='text/css'>
......
This diff is collapsed.
......@@ -24,6 +24,7 @@
"babel-core": "^7.0.0-bridge.0",
"babel-jest": "^23.6.0",
"chalk": "^2.4.1",
"eslint": "^5.9.0",
"express": "^4.16.3",
"ghostscript4js": "^3.0.0",
"jest": "^23.4.1",
......@@ -48,7 +49,8 @@
"compile": "./node_modules/.bin/babel src/ -d lib/",
"pretest": "npm run build",
"prepublishOnly": "npm run build && npm run compile && npm run legacy",
"watch": "./node_modules/.bin/rollup -w -c"
"watch": "./node_modules/.bin/rollup -w -c",
"lint": "./node_modules/.bin/eslint -c .eslintrc.js src; exit 0"
},
"repository": {
"type": "git",
......
......@@ -4,12 +4,7 @@ import EventEmitter from "event-emitter";
import Hook from "../utils/hook";
import Queue from "../utils/queue";
import {
needsBreakBefore,
needsBreakAfter
} from "../utils/dom";
import {
requestIdleCallback,
defer
requestIdleCallback
} from "../utils/utils";
const MAX_PAGES = false;
......@@ -81,6 +76,9 @@ class Chunker {
this.content = content;
this.charsPerBreak = [];
this.maxChars;
if (content) {
this.flow(content, renderTo);
}
......@@ -174,7 +172,7 @@ class Chunker {
let result;
while (!done) {
result = await this.q.enqueue(async () => { return this.renderOnIdle(renderer) });
result = await this.q.enqueue(() => { return this.renderAsync(renderer); });
done = result.done;
}
......@@ -207,6 +205,18 @@ class Chunker {
});
}
async renderAsync(renderer) {
if (this.stopped) {
return { done: true, canceled: true };
}
let result = await renderer.next();
if (this.stopped) {
return { done: true, canceled: true };
} else {
return result;
}
}
async handleBreaks(node) {
let currentPage = this.total + 1;
let currentPosition = currentPage % 2 === 0 ? "left" : "right";
......@@ -276,17 +286,34 @@ class Chunker {
this.emit("page", page);
// Layout content in the page, starting from the breakToken
breakToken = await page.layout(content, breakToken);
breakToken = await page.layout(content, breakToken, this.maxChars);
await this.hooks.afterPageLayout.trigger(page.element, page, breakToken, this);
this.emit("renderedPage", page);
this.recoredCharLength(page.wrapper.textContent.length);
yield breakToken;
// Stop if we get undefined, showing we have reached the end of the content
}
}
recoredCharLength(length) {
if (length === 0) {
return;
}
this.charsPerBreak.push(length);
// Keep the length of the last few breaks
if (this.charsPerBreak.length > 4) {
this.charsPerBreak.shift();
}
this.maxChars = this.charsPerBreak.reduce((a, b) => a + b, 0) / (this.charsPerBreak.length);
}
removePages(fromIndex=0) {
if (fromIndex >= this.pages.length) {
......@@ -309,7 +336,8 @@ class Chunker {
let lastPage = this.pages[this.pages.length - 1];
// Create a new page from the template
let page = new Page(this.pagesArea, this.pageTemplate, blank, this.hooks);
let total = this.pages.push(page);
this.pages.push(page);
// Create the pages
page.create(undefined, lastPage && lastPage.element);
......@@ -397,7 +425,7 @@ class Chunker {
}
set total(num) {
this.pagesArea.style.setProperty('--page-count', num);
this.pagesArea.style.setProperty("--page-count", num);
this._total = num;
}
......@@ -410,17 +438,17 @@ class Chunker {
}, (r) => {
console.warn("Failed to preload font-family:", fontFace.family);
return fontFace.family;
})
});
fontPromises.push(fontLoaded);
}
});
return Promise.all(fontPromises).catch((err) => {
console.warn(err)
})
console.warn(err);
});
}
destroy() {
this.pagesArea.remove()
this.pagesArea.remove();
this.pageTemplate.remove();
}
......
This diff is collapsed.
......@@ -6,263 +6,262 @@ import EventEmitter from "event-emitter";
* @class
*/
class Page {
constructor(pagesArea, pageTemplate, blank, hooks) {
this.pagesArea = pagesArea;
this.pageTemplate = pageTemplate;
this.blank = blank;
constructor(pagesArea, pageTemplate, blank, hooks) {
this.pagesArea = pagesArea;
this.pageTemplate = pageTemplate;
this.blank = blank;
this.width = undefined;
this.height = undefined;
this.width = undefined;
this.height = undefined;
this.hooks = hooks;
this.hooks = hooks;
// this.element = this.create(this.pageTemplate);
}
// this.element = this.create(this.pageTemplate);
}
create(template, after) {
//let documentFragment = document.createRange().createContextualFragment( TEMPLATE );
//let page = documentFragment.children[0];
let clone = document.importNode(this.pageTemplate.content, true);
create(template, after) {
//let documentFragment = document.createRange().createContextualFragment( TEMPLATE );
//let page = documentFragment.children[0];
let clone = document.importNode(this.pageTemplate.content, true);
let page;
if (after) {
this.pagesArea.insertBefore(clone, after.nextSibling);
let index = Array.prototype.indexOf.call(this.pagesArea.children, after.nextSibling);
page = this.pagesArea.children[index];
} else {
this.pagesArea.appendChild(clone);
page = this.pagesArea.lastChild;
}
let page;
if (after) {
this.pagesArea.insertBefore(clone, after.nextSibling);
let index = Array.prototype.indexOf.call(this.pagesArea.children, after.nextSibling);
page = this.pagesArea.children[index];
} else {
this.pagesArea.appendChild(clone);
page = this.pagesArea.lastChild;
}
let area = page.querySelector(".pagedjs_page_content");
let area = page.querySelector(".pagedjs_page_content");
let size = area.getBoundingClientRect();
let size = area.getBoundingClientRect();
area.style.columnWidth = Math.round(size.width) + "px";
area.style.columnGap = "calc(var(--margin-right) + var(--margin-left))";
// area.style.overflow = "scroll";
area.style.columnWidth = Math.round(size.width) + "px";
area.style.columnGap = "calc(var(--margin-right) + var(--margin-left))";
// area.style.overflow = "scroll";
this.width = Math.round(size.width);
this.height = Math.round(size.height);
this.width = Math.round(size.width);
this.height = Math.round(size.height);
this.element = page;
this.area = area;
this.element = page;
this.area = area;
return page;
}
return page;
}
createWrapper() {
let wrapper = document.createElement("div");
createWrapper() {
let wrapper = document.createElement("div");
this.area.appendChild(wrapper);
this.area.appendChild(wrapper);
this.wrapper = wrapper;
this.wrapper = wrapper;
return wrapper;
}
return wrapper;
}
index(pgnum) {
this.position = pgnum;
index(pgnum) {
this.position = pgnum;
let page = this.element;
let page = this.element;
let id = `page-${pgnum+1}`;
let id = `page-${pgnum+1}`;
this.id = id;
this.id = id;
page.dataset.pageNumber = pgnum+1;
page.dataset.pageNumber = pgnum+1;
if (this.name) {
page.classList.add("pagedjs_" + this.name + "_page");
}
if (this.name) {
page.classList.add("pagedjs_" + this.name + "_page");
}
if (this.blank) {
page.classList.add("pagedjs_blank_page");
}
if (this.blank) {
page.classList.add("pagedjs_blank_page");
}
if (pgnum === 0) {
page.classList.add("pagedjs_first_page");
}
if (pgnum === 0) {
page.classList.add("pagedjs_first_page");
}
if (pgnum % 2 !== 1) {
page.classList.remove("pagedjs_left_page");
page.classList.add("pagedjs_right_page");
} else {
page.classList.remove("pagedjs_right_page");
page.classList.add("pagedjs_left_page");
}
}
if (pgnum % 2 !== 1) {
page.classList.remove("pagedjs_left_page");
page.classList.add("pagedjs_right_page");
} else {
page.classList.remove("pagedjs_right_page");
page.classList.add("pagedjs_left_page");
}
}
/*
size(width, height) {
if (width === this.width && height === this.height) {
return;
}
this.width = width;
this.height = height;
/*
size(width, height) {
if (width === this.width && height === this.height) {
return;
}
this.width = width;
this.height = height;
this.element.style.width = Math.round(width) + "px";
this.element.style.height = Math.round(height) + "px";
this.element.style.columnWidth = Math.round(width) + "px";
}
*/
this.element.style.width = Math.round(width) + "px";
this.element.style.height = Math.round(height) + "px";
this.element.style.columnWidth = Math.round(width) + "px";
}
*/
async layout(contents, breakToken) {
async layout(contents, breakToken, maxChars) {
this.clear();
this.clear();
this.startToken = breakToken;
this.startToken = breakToken;
this.layoutMethod = new Layout(this.area, this.hooks);
this.layoutMethod = new Layout(this.area, this.hooks, maxChars);
let newBreakToken = await this.layoutMethod.renderTo(this.wrapper, contents, breakToken);
let newBreakToken = await this.layoutMethod.renderTo(this.wrapper, contents, breakToken);
this.addListeners(contents);
this.addListeners(contents);
this.endToken = newBreakToken;
this.endToken = newBreakToken;
return newBreakToken;
}
return newBreakToken;
}
async append(contents, breakToken) {
async append(contents, breakToken) {
if (!this.layoutMethod) {
return this.layout(contents, breakToken);
}
if (!this.layoutMethod) {
return this.layout(contents, breakToken);
}
let newBreakToken = await this.layoutMethod.renderTo(this.wrapper, contents, breakToken);
let newBreakToken = await this.layoutMethod.renderTo(this.wrapper, contents, breakToken);
this.endToken = newBreakToken;
this.endToken = newBreakToken;
return newBreakToken;
}
return newBreakToken;
}
getByParent(ref, entries) {
let e;
for (var i = 0; i < entries.length; i++) {
e = entries[i];
if(e.dataset.ref === ref) {
return e;
break;
}
}
}
getByParent(ref, entries) {
let e;
for (var i = 0; i < entries.length; i++) {
e = entries[i];
if(e.dataset.ref === ref) {
return e;
}
}
}
onOverflow(func) {
this._onOverflow = func;
}
onOverflow(func) {
this._onOverflow = func;
}
onUnderflow(func) {
this._onUnderflow = func;
}
onUnderflow(func) {
this._onUnderflow = func;
}
clear() {
this.removeListeners();
this.wrapper && this.wrapper.remove();
this.createWrapper();
}
clear() {
this.removeListeners();
this.wrapper && this.wrapper.remove();
this.createWrapper();
}
addListeners(contents) {
if (typeof ResizeObserver !== "undefined") {
this.addResizeObserver(contents);
} else {
this._checkOverflowAfterResize = this.checkOverflowAfterResize.bind(this, contents);
this.element.addEventListener("overflow", this._checkOverflowAfterResize, false);
this.element.addEventListener("underflow", this._checkOverflowAfterResize, false);
}
// TODO: fall back to mutation observer?
addListeners(contents) {
if (typeof ResizeObserver !== "undefined") {
this.addResizeObserver(contents);
} else {
this._checkOverflowAfterResize = this.checkOverflowAfterResize.bind(this, contents);
this.element.addEventListener("overflow", this._checkOverflowAfterResize, false);
this.element.addEventListener("underflow", this._checkOverflowAfterResize, false);
}
// TODO: fall back to mutation observer?
this._onScroll = function() {
if(this.listening) {
this.element.scrollLeft = 0;
}
}.bind(this);
this._onScroll = function() {
if(this.listening) {
this.element.scrollLeft = 0;
}
}.bind(this);
// Keep scroll left from changing
this.element.addEventListener("scroll", this._onScroll);
// Keep scroll left from changing
this.element.addEventListener("scroll", this._onScroll);
this.listening = true;
this.listening = true;
return true;
}
return true;
}
removeListeners() {
this.listening = false;
removeListeners() {
this.listening = false;
if (typeof ResizeObserver !== "undefined" && this.ro) {
this.ro.disconnect();
} else if (this.element) {
this.element.removeEventListener("overflow", this._checkOverflowAfterResize, false);
this.element.removeEventListener("underflow", this._checkOverflowAfterResize, false);
}
if (typeof ResizeObserver !== "undefined" && this.ro) {
this.ro.disconnect();
} else if (this.element) {
this.element.removeEventListener("overflow", this._checkOverflowAfterResize, false);
this.element.removeEventListener("underflow", this._checkOverflowAfterResize, false);
}
this.element &&this.element.removeEventListener("scroll", this._onScroll);
this.element &&this.element.removeEventListener("scroll", this._onScroll);
}
}
addResizeObserver(contents) {
let wrapper = this.wrapper;
let prevHeight = wrapper.getBoundingClientRect().height;
this.ro = new ResizeObserver( entries => {
addResizeObserver(contents) {
let wrapper = this.wrapper;
let prevHeight = wrapper.getBoundingClientRect().height;
this.ro = new ResizeObserver( entries => {
if (!this.listening) {
return;
}
if (!this.listening) {
return;
}
for (let entry of entries) {
const cr = entry.contentRect;
for (let entry of entries) {
const cr = entry.contentRect;
if (cr.height > prevHeight) {
this.checkOverflowAfterResize(contents);
prevHeight = wrapper.getBoundingClientRect().height;
} else if (cr.height < prevHeight ) { // TODO: calc line height && (prevHeight - cr.height) >= 22
this.checkUnderflowAfterResize(contents);
prevHeight = cr.height;
}
}
});
this.ro.observe(wrapper);
}
checkOverflowAfterResize(contents) {
if (!this.listening || !this.layoutMethod) {
return;
}
let newBreakToken = this.layoutMethod.findBreakToken(this.wrapper, contents);
if (newBreakToken) {
this.endToken = newBreakToken;
this._onOverflow && this._onOverflow(newBreakToken);
}
}
checkUnderflowAfterResize(contents) {
if (!this.listening || !this.layoutMethod) {
return;
}
let endToken = this.layoutMethod.findEndToken(this.wrapper, contents);
// let newBreakToken = this.layoutMethod.findBreakToken(this.wrapper, contents);
if (cr.height > prevHeight) {
this.checkOverflowAfterResize(contents);
prevHeight = wrapper.getBoundingClientRect().height;
} else if (cr.height < prevHeight ) { // TODO: calc line height && (prevHeight - cr.height) >= 22