Commit 4ae49f1b authored by Fred Chasen's avatar Fred Chasen

Merge branch 'nellie/nthOfType' into 'master'

Adding handling for nth-of-type selectors

See merge request tools/pagedjs!122
parents 58b2c9ea 77b83891
Pipeline #546 passed with stage
in 4 minutes and 8 seconds
This diff is collapsed.
const TIMEOUT = 10000; // Some book might take longer than this to renderer
describe("nth-of-type-selector", () => {
let page;
beforeAll(async () => {
page = await loadPage("nth-of-type-selector/nth-of-type-selector.html");
return page.rendered;
}, TIMEOUT);
afterAll(async () => {
if (!DEBUG) {
await page.close();
}
});
it("should render text", async () => {
let text = await page.evaluate(() => document.body.textContent);
expect(text).toContain("Chapter 1. Loomings.");
});
it("should render 14 pages", async () => {
let pages = await page.$$eval(".pagedjs_page", (r) => r.length);
expect(pages).toBe(14);
});
if (!DEBUG) {
it("should create a pdf", async () => {
let pdf = await page.pdf(PDF_SETTINGS);
expect(pdf).toMatchPDFSnapshot(1);
expect(pdf).toMatchPDFSnapshot(2);
});
}
}
);
......@@ -47,19 +47,19 @@
display: block;
margin-bottom: 3em;
}
nav li:nth-of-type(1) a[href]::after {
nav li#first a[href]::after {
content: target-text(attr(href url));
}
nav li:nth-of-type(2) a[href]::after {
nav li#second a[href]::after {
content: target-text(attr(href url), content);
}
nav li:nth-of-type(3) a[href]::after {
nav li#third a[href]::after {
content: target-text(attr(href url), first-letter);
}
nav li:nth-of-type(4) a[href]::after {
nav li#fourth a[href]::after {
content: target-text(attr(href url), before);
}
nav li:nth-of-type(5) a[href]::after {
nav li#fifth a[href]::after {
content: target-text(attr(href url), after);
}
......@@ -106,11 +106,11 @@
<nav>
<h1>Table of contents</h1>
<ul>
<li><a href="#chap0">target-text: </a></li>
<li><a href="#chap1">target-text content: </a></li>
<li><a href="#chap2">target-text first-letter: </a></li>
<li><a href="#chap3">target-text:: before: </a></li>
<li><a href="#chap4">target-text:: after: </a></li>
<li id="first"><a href="#chap0">target-text: </a></li>
<li id="second"><a href="#chap1">target-text content: </a></li>
<li id="third"><a href="#chap2">target-text first-letter: </a></li>
<li id="fourth"><a href="#chap3">target-text:: before: </a></li>
<li id="fifth"><a href="#chap4">target-text:: after: </a></li>
</ul>
</nav>
</section>
......
......@@ -14,27 +14,27 @@ describe("target-text", () => {
});
it("Table of content should include chapter titles", async () => {
let text = await page.$eval("nav li:nth-of-type(1) a" , (r) => window.getComputedStyle(r, "::after").content);
let text = await page.$eval("nav li#first a" , (r) => window.getComputedStyle(r, "::after").content);
expect(text).toEqual("\"'Lorem \\\"ipsum\\\" dolor sit amet'\"");
});
it("Table of content should include chapter titles", async () => {
let text = await page.$eval("nav li:nth-of-type(2) a" , (r) => window.getComputedStyle(r, "::after").content);
let text = await page.$eval("nav li#second a" , (r) => window.getComputedStyle(r, "::after").content);
expect(text).toEqual("\"'Lorem ipsum dolor sit amet'\"");
});
it("Table of content should include first-letter of the chapter title", async () => {
let text = await page.$eval("nav li:nth-of-type(3) a" , (r) => window.getComputedStyle(r, "::after").content);
let text = await page.$eval("nav li#third a" , (r) => window.getComputedStyle(r, "::after").content);
expect(text).toEqual("\"P\"");
});
it("Table of content should include the content of the before pseudo element", async () => {
let text = await page.$eval("nav li:nth-of-type(4) a" , (r) => window.getComputedStyle(r, "::after").content);
let text = await page.$eval("nav li#fourth a" , (r) => window.getComputedStyle(r, "::after").content);
expect(text).toEqual("\"This is 'inside' the before:\"");
});
it("Table of content should include the content of the before pseudo element", async () => {
let text = await page.$eval("nav li:nth-of-type(5) a" , (r) => window.getComputedStyle(r, "::after").content);
let text = await page.$eval("nav li#fifth a" , (r) => window.getComputedStyle(r, "::after").content);
expect(text).toEqual("\": This is inside the after\"");
});
// if (!DEBUG) {
......
......@@ -5,6 +5,7 @@ import Splits from "./splits";
import Counters from "./counters";
import Lists from "./lists";
import PositionFixed from "./position-fixed";
import NthOfType from "./nth-of-type";
export default [
AtPage,
......@@ -13,5 +14,6 @@ export default [
Splits,
Counters,
Lists,
PositionFixed
PositionFixed,
NthOfType
];
import Handler from "../handler";
import csstree from "css-tree";
import {UUID} from "../../utils/utils";
class NthOfType extends Handler {
constructor(chunker, polisher, caller) {
super(chunker, polisher, caller);
this.styleSheet = polisher.styleSheet;
this.selectors = {};
}
onRule(ruleNode, ruleItem, rulelist) {
let selector = csstree.generate(ruleNode.prelude);
if (selector.match(/:(first|last|nth)-of-type/)) {
let declarations = csstree.generate(ruleNode.block);
declarations = declarations.replace(/[{}]/g,"");
let uuid = "nth-of-type-" + UUID();
selector.split(",").forEach((s) => {
if (!this.selectors[s]) {
this.selectors[s] = [uuid, declarations];
} else {
this.selectors[s][1] = `${this.selectors[s][1]};${declarations}` ;
}
});
rulelist.remove(ruleItem);
}
}
afterParsed(parsed) {
this.processSelectors(parsed, this.selectors);
}
processSelectors(parsed, selectors) {
// add the new attributes to matching elements
for (let s in selectors) {
let elements = parsed.querySelectorAll(s);
for (var i = 0; i < elements.length; i++) {
let dataNthOfType = elements[i].getAttribute("data-nth-of-type");
if (dataNthOfType && dataNthOfType != "") {
dataNthOfType = `${dataNthOfType},${selectors[s][0]}`;
elements[i].setAttribute("data-nth-of-type", dataNthOfType);
} else {
elements[i].setAttribute("data-nth-of-type", selectors[s][0]);
}
}
let rule = `*[data-nth-of-type*='${selectors[s][0]}'] { ${selectors[s][1]}; }`;
this.styleSheet.insertRule(rule, this.styleSheet.cssRules.length);
}
}
}
export default NthOfType;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment