Commit 4116ec11 authored by Fred Chasen's avatar Fred Chasen

Merge branch 'master' into splits

parents 27f5a967 7863f956
......@@ -20,7 +20,7 @@ let flow = paged.preview(DOMContent, ["path/to/css/file.css"], document.body).th
Add the the `paged.polyfill.js` script to replace all `@page` css and render the html page with the Paged Media styles applied:
```html
<script src="https://s3.amazonaws.com/pagedmedia/pagedjs/dist/paged.polyfill.js"></script>
<script src="https://unpkg.com/pagedjs/dist/paged.polyfill.js"></script>
```
Try the [polyfill with Aurorae](https://s3.amazonaws.com/pagedmedia/pagedjs/examples/polyfill.html).
......@@ -51,7 +51,7 @@ Modules are groups of handlers for that apply the layout and styles of a CSS mod
New handlers can be registered from `import { registerHandlers } from 'pagedjs'` or by calling `Paged.registerHandlers` on an html page.
```html
<script src="https://s3.amazonaws.com/pagedmedia/pagedjs/dist/paged.polyfill.js"></script>
<script src="https://unpkg.com/pagedjs/dist/paged.polyfill.js"></script>
<script>
class myHandler() extends Paged.Handler {
constructor(chunker, polisher, caller) {
......@@ -76,6 +76,7 @@ afterPageLayout(pageElement, page, breakToken)
afterRendered(pages)
// Polisher
beforeTreeParse(text, sheet)
onUrl(urlNode)
onAtPage(atPageNode)
onRule(ruleNode)
......
......@@ -139,7 +139,7 @@ section[data-type="epigraph"],
/* running elements */
#cover h1 {
string-set: booktitle content(text);
/* string-set: booktitle content(text); */
}
#cover {
......@@ -210,8 +210,8 @@ section[data-type="copyright"] #flexbox {
float:right;
}
.toc-subchap a[href]::before{
content: target-text(attr(href)); /* pdfreactor */
.toc-subchap a[href]::before {
content: target-text(attr(href));
}
.toc-subchap a[href]::after {
......
{
"name": "pagedjs",
"version": "0.1.8",
"version": "0.1.10",
"description": "Chunks up a document into paged media flows and applies print styles",
"author": "Fred Chasen",
"license": "MIT",
......@@ -35,13 +35,14 @@
},
"scripts": {
"build": "./node_modules/.bin/rollup -c",
"legacy": "./node_modules/.bin/rollup -c rollup.legacy.config.js",
"start": "./node_modules/.bin/rollup -w -c rollup.server.config.js",
"test": "npm run tests && npm run specs",
"tests": "jest --config=tests/jest.config.js",
"specs": "jest --config=specs/jest.config.js",
"compile": "./node_modules/.bin/babel src/ -d lib/",
"pretest": "npm run build",
"prepublishOnly": "npm run build && npm run compile",
"prepublishOnly": "npm run build && npm run compile && npm run legacy",
"watch": "./node_modules/.bin/rollup -w -c"
},
"repository": {
......
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import json from 'rollup-plugin-json';
import pkg from './package.json';
const plugins = [
resolve(),
commonjs(),
json()
];
export default [
// browser-friendly UMD build
{
input: pkg.main,
output: {
name: 'Paged',
file: pkg.browser.replace(".js", ".legacy.js"),
format: 'umd'
},
plugins: plugins
},
{
input: "./lib/polyfill/polyfill.js",
output: {
name: 'PagedPolyfill',
file: "./dist/paged.legacy.polyfill.js",
format: 'umd'
},
plugins: plugins
}
];
<!DOCTYPE html PUBLIC>
<html lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<title>
Content None
</title>
<script src="../../../dist/paged.polyfill.js"></script>
<style>
/* Paged.js fragmentation rendering on screen */
/* bind chapter section to the chapter layout */
.chapter {
page: chapter;
}
@page chapter :first {
background-color: lightcyan;
@top-left {
content: none;
}
@top-left-corner {
content: none;
}
@top-right {
content: none;
}
@top-right-corner {
content: none;
}
}
@page chapter :nth(4) {
@top-right {
content: 'lol';
}
}
/* blanck page: pages with no content */
@page :blank {
@top-left-corner {
content: none;
}
@top-left {
content: none;
}
@top-right-corner {
content: none;
}
@top-right {
content: none;
}
background: white;
}
/* variable used for the boook */
:root {
--background: rgba(0,0,0,0.4);
--color-paper: white;
--color-margin-box: transparent;
--color-page-box: grey;
--size-margin-box: 2px;
}
/* set the running-title element AS a running title position */
.running-title {
position: running(titleRun);
}
/* Binding the part layout to the section with a class 'part' */
.part {
page: part;
}
/* print css that's being rendered on screen */
@page {
size: 170mm 240mm;
margin: 30mm 25mm;
}
@page part {
background: darkcyan;
color: white;
@top-left-corner {
content: none;
}
@top-left {
content: none;
}
@top-right-corner {
content: none;
}
@top-right {
content: none;
}
}
/* layout for the left page */
@page :left {
@top-left-corner {
content: counter(page);
padding-right: 3ch
}
@top-left {
content: element(titleRun);
}
}
/* layout for the right page */
@page :right {
@top-right-corner {
content: counter(page);
padding-left: 3ch;
}
@top-right {
content: element(titleRun);
}
}
</style>
<style>
/* BELOW COMES CSS FOR THE BOOK STYLING AND FOR THE THE PAGES ALIGNMENTS */
header p {
text-transform: uppercase;
font-family: sans-serif;
margin-top: -6em;
margin-left: -14ch;
background: white;
position: absolute;
padding: 0.5em;
padding-left: 4em;
}
header h1 {
margin-top: 2em;
}
body {
padding: 1em;
}
section {
break-before: right;
}
/* To define how the book look on the screen: */
@media screen {
body {
background-color: var(--background);
}
.pagedjs_pages {
display: flex;
width: calc(var(--width) * 2);
flex: 0;
flex-wrap: wrap;
margin: 0 auto;
}
.pagedjs_page {
background: var(--color-paper);
box-shadow: 0 0 0 1px inset var(--color-page-box);
margin: 0;
flex-shrink: 0;
flex-grow: 0;
margin-top: 10mm;
}
.pagedjs_first_page {
margin-left: var(--width);
}
/* show the margin-box */
[class*="pagedjs_margin-top"], [class*="pagedjs_margin-left"], [class*="pagedjs_margin-right"], [class*="pagedjs_margin-bottom"] {
box-shadow: 0 0 0 var(--size-margin-box) inset var(--color-margin-box);
}
}
body {
font-family: serif;
}
</style>
</head>
<body>
<section class="part">
<h1>Awesome part</h1>
<p>In this part, we'll talk about a lot of different things</p>
</section>
<section class="chapter">
<header>
<p>chapter one</p>
<h1>Margin boxes</h1>
</header>
<div class="running-title">Margin boxes </div>
<p>the margin boxes as declared by the W3C.</p>
<h2>Now, some random wikipedia article </h2>
<h3>Zduńska Wola Karsznice</h3>
<p>Zduńska Wola Karsznice is one of the biggest rail junctions in Poland, located in central part of the country, within the borders of the town of Zduńska Wola (Łódź Voivodeship). It is a station along the Polish Coal Trunk-Line; before 1930 it had been a separate village, but construction of the Trunk-Line resulted in creation of a separate district for rail workers, with numerous condominiums. A few kilometers north of Karsznice, the Trunk-Line crosses the main East-West rail route Warsaw - Łódź - Ostrów Wielkopolski - Poznań/Wrocław. p Zduńska Wola Karsznice is one of the biggest rail junctions in Poland, located in central part of the country, within the borders of the town of Zduńska Wola (Łódź Voivodeship). It is a station along the Polish Coal Trunk-Line; before 1930 it had been a separate village, but construction of the Trunk-Line resulted in creation of a separate district for rail workers, with numerous condominiums. A few kilometers north of Karsznice, the Trunk-Line crosses the main East-West rail route Warsaw - Łódź - Ostrów Wielkopolski - Poznań/Wrocław. </p>
<p>Zduńska Wola Karsznice is one of the biggest rail junctions in Poland, located in central part of the country, within the borders of the town of Zduńska Wola (Łódź Voivodeship). It is a station along the Polish Coal Trunk-Line; before 1930 it had been a separate village, but construction of the Trunk-Line resulted in creation of a separate district for rail workers, with numerous condominiums. A few kilometers north of Karsznice, the Trunk-Line crosses the main East-West rail route Warsaw - Łódź - Ostrów Wielkopolski - Poznań/Wrocław. Zduńska Wola Karsznice is one of the biggest rail junctions in Poland, located in central part of the country, within the borders of the town of Zduńska Wola (Łódź Voivodeship). It is a station along the Polish Coal Trunk-Line; before 1930 it had been a separate village, but construction of the Trunk-Line resulted in creation of a separate district for rail workers, with numerous condominiums. A few kilometers north of Karsznice, the Trunk-Line crosses the main East-West rail route Warsaw - Łódź - Ostrów Wielkopolski - Poznań/Wrocław. </p>
<p>Zduńska Wola Karsznice is one of the biggest rail junctions in Poland, located in central part of the country, within the borders of the town of Zduńska Wola (Łódź Voivodeship). It is a station along the Polish Coal Trunk-Line; before 1930 it had been a separate village, but construction of the Trunk-Line resulted in creation of a separate district for rail workers, with numerous condominiums. A few kilometers north of Karsznice, the Trunk-Line crosses the main East-West rail route Warsaw - Łódź - Ostrów Wielkopolski - Poznań/Wrocław. </p>
<p>Zduńska Wola Karsznice is one of the biggest rail junctions in Poland, located in central part of the country, within the borders of the town of Zduńska Wola (Łódź Voivodeship). It is a station along the Polish Coal Trunk-Line; before 1930 it had been a separate village, but construction of the Trunk-Line resulted in creation of a separate district for rail workers, with numerous condominiums. A few kilometers north of Karsznice, the Trunk-Line crosses the main East-West rail route Warsaw - Łódź - Ostrów Wielkopolski - Poznań/Wrocław. </p>
<p>Zduńska Wola Karsznice is one of the biggest rail junctions in Poland, located in central part of the country, within the borders of the town of Zduńska Wola (Łódź Voivodeship). It is a station along the Polish Coal Trunk-Line; before 1930 it had been a separate village, but construction of the Trunk-Line resulted in creation of a separate district for rail workers, with numerous condominiums. A few kilometers north of Karsznice, the Trunk-Line crosses the main East-West rail route Warsaw - Łódź - Ostrów Wielkopolski - Poznań/Wrocław. </p>
<p>Zduńska Wola Karsznice is one of the biggest rail junctions in Poland, located in central part of the country, within the borders of the town of Zduńska Wola (Łódź Voivodeship). It is a station along the Polish Coal Trunk-Line; before 1930 it had been a separate village, but construction of the Trunk-Line resulted in creation of a separate district for rail workers, with numerous condominiums. A few kilometers north of Karsznice, the Trunk-Line crosses the main East-West rail route Warsaw - Łódź - Ostrów Wielkopolski - Poznań/Wrocław. </p>
<p>Zduńska Wola Karsznice is one of the biggest rail junctions in Poland, located in central part of the country, within the borders of the town of Zduńska Wola (Łódź Voivodeship). It is a station along the Polish Coal Trunk-Line; before 1930 it had been a separate village, but construction of the Trunk-Line resulted in creation of a separate district for rail workers, with numerous condominiums. A few kilometers north of Karsznice, the Trunk-Line crosses the main East-West rail route Warsaw - Łódź - Ostrów Wielkopolski - Poznań/Wrocław. </p>
</section>
</body>
const TIMEOUT = 10000;
describe('content-none', async () => {
let page;
let rendered;
beforeAll(async () => {
page = await loadPage('generate-content/content-none/content-none.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;
});
expect(pages).toEqual(5);
})
if (!DEBUG) {
it('should create a pdf', async () => {
let pdf = await page.pdf(PDF_SETTINGS);
expect(pdf).toMatchPDFSnapshot(3);
expect(pdf).toMatchPDFSnapshot(4);
})
}
}
)
......@@ -50,7 +50,7 @@
@bottom-left{
content: counter(page);
}
@top-left: {
@top-left {
content: element(chapter-title);
}
}
......
......@@ -51,9 +51,7 @@
@bottom-left{
content: counter(page);
}
@top-left: {
content: element(chapter-title);
}
}
section {
......
This diff is collapsed.
const TIMEOUT = 10000; // Some book might take longer than this to renderer
describe('target-counter', async () => {
let page;
let rendered;
beforeAll(async () => {
page = await loadPage('target/target-counter/target-counter.html')
return page.rendered;
}, TIMEOUT)
afterAll(async () => {
if (!DEBUG) {
await page.close();
}
})
it('Cross reference should include See p. text', async () => {
let text = await page.$eval("#ref-call", (r) => window.getComputedStyle(r, '::after').content);
expect(text).toContain("(See p. ");
})
if (!DEBUG) {
it('should create a pdf', async () => {
let pdf = await page.pdf(PDF_SETTINGS);
expect(pdf).toMatchPDFSnapshot(1);
})
}
}
)
......@@ -32,26 +32,20 @@ class RunningHeaders extends Handler {
}
if (declaration.property === "content") {
// Handle Raw
// element(x) is not parsed
csstree.walk(declaration, {
visit: 'Raw',
visit: 'Function',
enter: (funcNode, fItem, fList) => {
if (funcNode.value.indexOf("element") > -1) {
if (funcNode.name.indexOf("element") > -1) {
let selector = csstree.generate(rule.ruleNode.prelude);
let parsed = funcNode.value.match(/([^(]+)\(([^)]+)\)/);
let func = parsed[1];
let value = funcNode.value;
let func = funcNode.name;
let args = [];
let value = funcNode.children.first().name;
if (parsed.length >= 3) {
args.push(parsed[2]);
}
let args = [value];
// we only handle first for now
let style = "first";
......@@ -121,7 +115,7 @@ class RunningHeaders extends Handler {
let running = this.runningSelectors[el.args[0]];
if (running && running.first) {
selected.innerHTML = ""; // Clear node
selected.classList.add("pagedjs_clear-after"); // Clear ::after
// selected.classList.add("pagedjs_clear-after"); // Clear ::after
let clone = running.first.cloneNode(true);
clone.style.display = null;
selected.appendChild(clone);
......@@ -216,6 +210,11 @@ class RunningHeaders extends Handler {
return orderedSelectors;
}
beforeTreeParse(text, sheet) {
// element(x) is parsed as image element selector, so update element to element-ident
sheet.text = text.replace(/element[\s]*\(([^\|^#)]*)\)/g, "element-ident($1)");
}
}
export default RunningHeaders;
......@@ -33,6 +33,8 @@ class TargetCounters extends Handler {
counter = last.name;
}
let variable = "--" + UUID();
selector.split(",").forEach((s) => {
this.counterTargets[s] = {
func: func,
......@@ -40,10 +42,19 @@ class TargetCounters extends Handler {
value: value,
counter: counter,
selector: s,
fullSelector: selector
fullSelector: selector,
variable: variable
}
});
// Replace with variable
funcNode.name = "var";
funcNode.children = new csstree.List()
funcNode.children.appendData({
type: "Identifier",
loc: 0,
name: variable
});
}
}
......@@ -81,7 +92,8 @@ 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} { content: "${pg}"; }`, this.styleSheet.cssRules.length);
this.styleSheet.insertRule(`[data-target-counter="${selector}"]${psuedo} { ${target.variable}: "${pg}" }`, this.styleSheet.cssRules.length);
}
}
});
......
......@@ -32,6 +32,8 @@ class TargetText extends Handler {
style = last.name;
}
let variable = "--" + UUID();
selector.split(",").forEach((s) => {
this.textTargets[s] = {
func: func,
......@@ -39,10 +41,19 @@ class TargetText extends Handler {
value: value,
style: style || "content",
selector: s,
fullSelector: selector
fullSelector: selector,
variable: variable
}
});
// Replace with variable
funcNode.name = "var";
funcNode.children = new csstree.List()
funcNode.children.appendData({
type: "Identifier",
loc: 0,
name: variable
});
}
}
......@@ -59,7 +70,6 @@ class TargetText extends Handler {
if (target.style === "content") {
let text = element.textContent;
let selector = UUID();
selected.setAttribute("data-target-text", selector);
let psuedo = "";
......@@ -67,8 +77,18 @@ class TargetText extends Handler {
psuedo += "::" + split[1];
}
this.styleSheet.insertRule(`[data-target-text="${selector}"]${psuedo} { content: "${element.textContent}"; }`, this.styleSheet.cssRules.length);
let textContent = element.textContent.trim().replace(/[\"\']/g, (match) => {
return "\\" + match;
}).replace(/[\n]/g, (match) => {
return "\\00000A";
});
// this.styleSheet.insertRule(`[data-target-text="${selector}"]${psuedo} { content: "${element.textContent}" }`, this.styleSheet.cssRules.length);
this.styleSheet.insertRule(`[data-target-text="${selector}"]${psuedo} { ${target.variable}: "${textContent}" }`, this.styleSheet.cssRules.length);
}
} else {
console.warn("missed target", val);
}
});
......
......@@ -537,6 +537,7 @@ class AtPage extends Handler {
}
addMarginaliaContent(page, list, item, sheet) {
let displayNone;
// Just content
for (let loc in page.marginalia) {
let content = csstree.clone(page.marginalia[loc]);
......@@ -546,9 +547,10 @@ class AtPage extends Handler {
if (node.property !== "content") {
list.remove(item);
}
// else if (node.value.children && node.value.children.first().name === "none") {
// list.remove(item);
// }
if (node.value.children && node.value.children.first().name === "none") {
displayNone = true;
}
}
});
......@@ -556,14 +558,37 @@ class AtPage extends Handler {
continue;
}
// insert display rule - handled after page layout
/*
let displaySelectors = this.selectorsForPageMargin(page, loc);
let displayDeclaration = this.createDeclaration("display", "flex");
let displayRule = this.createRule(displaySelectors, [displayDeclaration]);
let displayDeclaration;
displaySelectors.insertData({
type: 'Combinator',
name: ">"
});
displaySelectors.insertData({
type: 'ClassSelector',
name: "pagedjs_margin-content"
});
displaySelectors.insertData({
type: 'Combinator',
name: ">"
});
displaySelectors.insertData({
type: 'TypeSelector',
name: "*"
});
if (displayNone) {
displayDeclaration = this.createDeclaration("display", "none");
} else {
displayDeclaration = this.createDeclaration("display", "block");
}
let displayRule = this.createRule(displaySelectors, [displayDeclaration]);
sheet.insertRule(displayRule);
*/
// insert content rule
let contentSelectors = this.selectorsForPageMargin(page, loc);
......@@ -805,6 +830,10 @@ class AtPage extends Handler {
left.classList.add("emptyBalance");
}
if (leftContent && rightContent) {
center.classList.add("balanceMargins");
}
// Balance Sizes
if (leftContent) {
leftWidth = window.getComputedStyle(left)["max-width"];
......@@ -823,8 +852,8 @@ class AtPage extends Handler {
left.style["width"] = "auto";
left.style["max-width"] = "none";
} else if ((centerWidth === "none" || centerWidth === "auto") &&
leftWidth !== "none" && leftWidth !== "auto" &&
rightWidth !== "none" && rightWidth !== "auto") {
leftContent && leftWidth !== "none" && leftWidth !== "auto" &&
rightContent && rightWidth !== "none" && rightWidth !== "auto") {
// TODO: convert units before comparing
let newWidth = Math.max(parseFloat(leftWidth), parseFloat(rightWidth));
......@@ -889,8 +918,8 @@ class AtPage extends Handler {
bottom.style["height"] = "auto";
bottom.style["max-height"] = "none";
} else if ((middleHeight === "none" || middleHeight === "auto") &&
topHeight !== "none" && topHeight !== "auto" &&
bottomHeight !== "none" && bottomHeight !== "auto") {
topContent && topHeight !== "none" && topHeight !== "auto" &&
bottomContent && bottomHeight !== "none" && bottomHeight !== "auto") {
// TODO: convert units before comparing
let newHeight = Math.max(parseFloat(topHeight), parseFloat(bottomHeight));
......
......@@ -143,6 +143,10 @@ export default `
visibility: hidden;
}