Commit ec110ecd authored by Fred Chasen's avatar Fred Chasen

handle imports in stylesheets

parent b3d623fd
section {
break-before: page;
page-break-before: always;
}
p {
line-height: 22px;
}
h1{
font-size: 24px;
margin-top: 0;
}
<!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>
Imports
</title>
<script src="../../../dist/paged.polyfill.js"></script>
<style>
/* interface */
@media screen {
body {
background: whitesmoke;
}
.pagedjs_page {
background: white;
margin-bottom: 10px;
box-shadow: 0 0 0 1px rgba(0, 0,0,0.2);
}
.pagedjs_pages {
width: calc(var(--width) * 2);
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
margin: 0 auto;
}
.pagedjs_first_page {
margin-left: 50%;
}
}
</style>
<style>
@import url("screen.css") screen;
@import "screen.css" not print;
@import 'print1.css';
@import url("print2.css") print and (orientation:landscape);
@import "print3.css" print;
@import "all.css" all;
</style>
</head>
<body>
<section class="chapter">
<h1>Chapter 1: Lorem ipsum dolor sit amet</h1>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi non suscipit odio. Aenean ut ligula id mauris efficitur tincidunt vitae non leo. In convallis convallis leo, eget molestie metus imperdiet eu. Praesent pharetra, leo a laoreet mattis, ligula nisl commodo ante, non vestibulum nisi lacus eget magna. Maecenas scelerisque nibh ac felis egestas, egestas elementum risus pellentesque. Nulla iaculis ut leo a iaculis. Donec vel sodales dolor, vel fringilla elit. Vivamus aliquam diam eu maximus elementum. Integer eu urna at felis fermentum hendrerit.
</p>
<p>
Nulla dignissim pellentesque magna ac maximus. Integer id tincidunt erat. Sed elementum posuere augue, quis pharetra mi vehicula in. Nullam rhoncus mi quis lectus gravida dignissim. Pellentesque a tortor ut leo pretium auctor non in massa. Nunc efficitur vestibulum mi, id mattis quam aliquet id. Ut semper tortor sit amet molestie mattis. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec laoreet eleifend purus ut sagittis. Nunc consequat vel sapien at convallis. Maecenas sollicitudin quis justo non varius.
</p>
<p>
Maecenas arcu massa, egestas vel est nec, mollis venenatis tortor. Ut eu finibus libero. Phasellus pharetra ante a purus ornare, eget facilisis sem ultricies. Etiam tincidunt feugiat erat, eget hendrerit turpis ullamcorper quis. Fusce finibus porttitor nisi sed blandit. Nunc libero erat, vehicula ut tincidunt quis, maximus vitae eros. Donec tristique urna bibendum, mattis nisl vel, dignissim nisl. Duis tincidunt eros nec volutpat scelerisque. Phasellus id malesuada nulla. Duis aliquam mi non malesuada suscipit. Curabitur pretium nisl eu tortor tempus, et sollicitudin quam iaculis. Ut venenatis eros ligula, in ornare eros facilisis vel.
</p>
<p>
Donec auctor libero a lorem egestas consequat. Cras ac lacinia ipsum. Donec non elementum purus, et porta eros. Cras ullamcorper mi eu semper aliquam. Duis magna ipsum, auctor at leo non, pharetra luctus felis. Ut tempus finibus dui, sit amet scelerisque nisi feugiat non. Proin posuere quam vitae finibus pulvinar. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum id felis at nulla mollis bibendum.
</p>
<p>
Donec odio lacus, maximus a ultrices non, pulvinar eget nunc. Morbi cursus eget enim eleifend tincidunt. In vel odio gravida, hendrerit diam ut, fringilla urna. Aenean sit amet nisi ut nisl placerat bibendum. Aenean consequat dapibus orci non accumsan. In imperdiet leo lectus, vitae euismod quam egestas et. Donec augue mauris, malesuada ac nunc dapibus, faucibus malesuada velit. Vivamus quis enim eget orci sollicitudin ultrices. Duis ut nulla velit. Donec feugiat quam nec sem cursus, vel feugiat nunc fringilla.
</p>
</section>
<section class="chapter">
<h1>Chapter 2: Praesent placerat lectus</h1>
<p>
Praesent placerat lectus ac mauris rhoncus, eget iaculis nisl molestie. Etiam posuere luctus ligula quis ornare. Duis semper lectus vel bibendum dapibus. Morbi a lacus eget augue sagittis euismod. Aliquam non leo quis dui bibendum viverra eu vel erat. Fusce iaculis vulputate leo, sit amet laoreet eros aliquam a. Sed id tellus at ligula porttitor pharetra. Morbi non fringilla augue. Cras sodales egestas mi, et porta orci ultricies sed. Sed et nulla a ligula aliquet accumsan non eleifend quam. Aliquam pellentesque, justo vel interdum accumsan, purus ipsum porttitor lectus, ac luctus risus lectus nec lectus. Cras ut augue condimentum, egestas nisi in, dictum erat. Nullam tincidunt tincidunt tempor. Sed in eleifend nibh, sit amet feugiat nisi. Cras at ante ut urna sagittis dictum ut nec elit.
</p>
<p>
In feugiat euismod massa sagittis dictum. Nullam eu nisl eu elit laoreet tincidunt id sed ligula. Praesent vulputate faucibus nibh, ut ultrices nunc aliquam nec. Mauris et condimentum ligula. Vestibulum nec tortor quis urna dictum luctus. Cras quis suscipit metus. Ut dignissim ullamcorper aliquam. Donec condimentum eu tellus at interdum.
</p>
<p>
Proin eu quam id arcu interdum laoreet nec at urna. Vivamus non sem quis dolor sagittis facilisis. Nunc quis urna non neque sollicitudin hendrerit. Vestibulum odio velit, vestibulum vitae elementum convallis, tristique eu est. Sed vitae tortor sed purus accumsan euismod nec finibus lorem. Donec consectetur libero sit amet pretium eleifend. Nulla placerat ipsum sed eros aliquet, at venenatis purus convallis. Pellentesque pulvinar, justo eget tincidunt semper, augue massa placerat enim, non tempus quam erat eu orci. Suspendisse auctor consectetur lectus, a mattis odio. Pellentesque id sem sit amet justo fringilla bibendum id sit amet quam. Vivamus ex est, ultrices non pharetra eu, facilisis nec quam.
</p>
<p>
Etiam molestie sed orci sed suscipit. Donec ipsum est, venenatis ut nisl ut, viverra auctor diam. Cras vestibulum lacus vel nunc dapibus aliquam. Aliquam accumsan lorem rhoncus tortor rhoncus, ut euismod sapien ullamcorper. Vivamus et dictum lacus, eu pellentesque dolor. Suspendisse potenti. Mauris vitae volutpat odio. Duis vitae purus nec enim posuere efficitur at vitae nisl. Etiam enim nisl, rutrum in vestibulum nec, dapibus ut dui. Pellentesque imperdiet molestie ante quis feugiat. Sed nec felis congue, cursus ligula eget, bibendum est. Proin mattis, tortor non lobortis lobortis, nibh quam aliquam neque, sed tristique nibh ex aliquet felis. Phasellus non augue ac ante efficitur consectetur at at est. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nullam dui enim, iaculis et felis ac, porta ullamcorper justo. Suspendisse potenti.
</p>
</section>
<section>
<h1>Chapter 3: Aliquam eget massa loborti</h1>
<p>
Aliquam eget massa lobortis, maximus leo ac, iaculis quam. Sed non aliquet eros. Integer ultrices consequat tortor eget ullamcorper. Integer quis justo dignissim, porttitor urna sed, faucibus ex. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur elit tortor, pharetra eu nisl vitae, placerat tempus lorem. Praesent rhoncus venenatis sodales. Cras tempor tempus lacus et pharetra. Phasellus at nulla sed ligula gravida hendrerit. Sed lorem tortor, consectetur id tempus eget, accumsan at eros.
</p>
<p>
Aliquam erat volutpat. Aenean ornare elit magna, et efficitur massa dapibus sit amet. Interdum et malesuada fames ac ante ipsum primis in faucibus. Phasellus ultricies posuere magna. Vestibulum placerat ligula bibendum tempus viverra. Morbi et magna eleifend, scelerisque justo ut, suscipit enim. Vestibulum ex arcu, dictum ut ligula feugiat, fringilla feugiat dui. Aenean velit nisi, consectetur eu mi quis, sollicitudin elementum mauris. Phasellus condimentum eu magna nec sollicitudin. Morbi sed velit mollis, aliquam libero vel, rutrum sapien. Etiam sit amet turpis tincidunt, euismod justo eget, pretium leo. Quisque a blandit justo. Proin dolor leo, semper non rhoncus sit amet, varius ac erat. Donec in lacus nec purus iaculis posuere eget et ligula.
</p>
<p>
Vivamus vel velit vel metus bibendum luctus ut vitae tortor. Nullam at ante eu felis ultrices ultrices at in diam. Pellentesque eleifend leo sapien, vel commodo orci mollis vel. Phasellus placerat fermentum odio. Cras placerat posuere risus et consectetur. Fusce dictum faucibus est quis imperdiet. Ut tristique, enim ultrices scelerisque imperdiet, ex mauris pellentesque arcu, sit amet mattis lacus purus in ligula. Vestibulum rhoncus dapibus orci, sit amet volutpat turpis semper ullamcorper. Nullam tincidunt lacus vel purus molestie fermentum. Fusce dapibus pulvinar vehicula. Pellentesque tempor elementum fermentum. Nunc ex erat, gravida sit amet dictum at, semper ut mi. Vestibulum pulvinar congue eros id faucibus. In non tellus et mi egestas aliquet id non dolor.
</p>
<p>
Nam eros tellus, hendrerit ut rhoncus sed, aliquet et felis. Cras a ex malesuada, fringilla magna elementum, cursus purus. Etiam fringilla leo non diam congue tempor. Ut laoreet, est eget blandit congue, mauris magna cursus sapien, dictum tempus sapien diam et dolor. Vestibulum vel egestas velit. Pellentesque vel consectetur urna, eu consequat odio. Sed ac pretium magna, ut ultrices tortor.
</p>
</section>
</body>
</html>
const TIMEOUT = 10000;
describe('imports', async () => {
let page;
let rendered;
beforeAll(async () => {
page = await loadPage('issues/imports/imports.html')
return page.rendered;
}, TIMEOUT)
afterAll(async () => {
if (!DEBUG) {
await page.close();
}
})
it('should render 6 pages', async () => {
let pages = await page.$$eval(".pagedjs_page", (r) => {
return r.length;
});
expect(pages).toEqual(6);
})
it('should have a green paragaph 1', async () => {
let color = await page.$eval("[data-page-number='1'] p:nth-of-type(1)", (r) => window.getComputedStyle(r).color);
expect(color).toContain('rgb(0, 128, 0)'); // green
})
it('should have a yellow paragaph 1', async () => {
let color = await page.$eval("[data-page-number='1'] p:nth-of-type(2)", (r) => window.getComputedStyle(r).color);
expect(color).toContain('rgb(255, 255, 0)'); // yellow
})
it('should have a orange paragaph 1', async () => {
let color = await page.$eval("[data-page-number='1'] p:nth-of-type(3)", (r) => window.getComputedStyle(r).color);
expect(color).toContain('rgb(255, 165, 0)'); // orange
})
if (!DEBUG) {
it('should create a pdf', async () => {
let pdf = await page.pdf(PDF_SETTINGS);
expect(pdf).toMatchPDFSnapshot(1);
})
}
}
)
@page {
size: A5;
margin: 20mm 20mm;
@bottom-left{
content: counter(page);
}
}
p:nth-of-type(1) {
color: green;
}
p:nth-of-type(2) {
color: yellow;
}
p:nth-of-type(3) {
color: orange;
}
...@@ -15,6 +15,7 @@ class Polisher { ...@@ -15,6 +15,7 @@ class Polisher {
this.hooks.onRule = new Hook(this); this.hooks.onRule = new Hook(this);
this.hooks.onDeclaration = new Hook(this); this.hooks.onDeclaration = new Hook(this);
this.hooks.onContent = new Hook(this); this.hooks.onContent = new Hook(this);
this.hooks.onImport = new Hook(this);
this.hooks.beforeTreeParse = new Hook(this); this.hooks.beforeTreeParse = new Hook(this);
this.hooks.beforeTreeWalk = new Hook(this); this.hooks.beforeTreeWalk = new Hook(this);
...@@ -63,9 +64,9 @@ class Polisher { ...@@ -63,9 +64,9 @@ class Polisher {
.then(async (originals) => { .then(async (originals) => {
let text = ""; let text = "";
for (let index = 0; index < originals.length; index++) { for (let index = 0; index < originals.length; index++) {
text += await this.convertViaSheet(originals[index], urls[index]); text = await this.convertViaSheet(originals[index], urls[index]);
this.insert(text);
} }
this.insert(text);
return text; return text;
}); });
} }
...@@ -73,6 +74,16 @@ class Polisher { ...@@ -73,6 +74,16 @@ class Polisher {
async convertViaSheet(cssStr, href) { async convertViaSheet(cssStr, href) {
let sheet = new Sheet(href, this.hooks); let sheet = new Sheet(href, this.hooks);
await sheet.parse(cssStr); await sheet.parse(cssStr);
// Insert the imported sheets first
for (let url of sheet.imported) {
let str = await request(url).then((response) => {
return response.text();
});
let text = await this.convertViaSheet(str, url);
this.insert(text);
}
this.sheets.push(sheet); this.sheets.push(sheet);
if (typeof sheet.width !== "undefined") { if (typeof sheet.width !== "undefined") {
......
...@@ -15,6 +15,7 @@ class Sheet { ...@@ -15,6 +15,7 @@ class Sheet {
this.hooks.onRule = new Hook(this); this.hooks.onRule = new Hook(this);
this.hooks.onDeclaration = new Hook(this); this.hooks.onDeclaration = new Hook(this);
this.hooks.onContent = new Hook(this); this.hooks.onContent = new Hook(this);
this.hooks.onImport = new Hook(this);
this.hooks.beforeTreeParse = new Hook(this); this.hooks.beforeTreeParse = new Hook(this);
this.hooks.beforeTreeWalk = new Hook(this); this.hooks.beforeTreeWalk = new Hook(this);
...@@ -51,6 +52,8 @@ class Sheet { ...@@ -51,6 +52,8 @@ class Sheet {
// Replace IDs with data-id // Replace IDs with data-id
this.replaceIds(this.ast); this.replaceIds(this.ast);
this.imported = [];
// Trigger Hooks // Trigger Hooks
this.urls(this.ast); this.urls(this.ast);
this.rules(this.ast); this.rules(this.ast);
...@@ -93,6 +96,11 @@ class Sheet { ...@@ -93,6 +96,11 @@ class Sheet {
this.hooks.onAtMedia.trigger(node, item, list); this.hooks.onAtMedia.trigger(node, item, list);
this.declarations(node, item, list); this.declarations(node, item, list);
} }
if (basename === "import") {
this.hooks.onImport.trigger(node, item, list);
this.imports(node, item, list);
}
} }
}); });
} }
...@@ -215,6 +223,51 @@ class Sheet { ...@@ -215,6 +223,51 @@ class Sheet {
}); });
} }
imports(node, item, list) {
// console.log("import", node, item, list);
let queries = [];
csstree.walk(node, {
visit: "MediaQuery",
enter: (mqNode, mqItem, mqList) => {
csstree.walk(mqNode, {
visit: "Identifier",
enter: (identNode, identItem, identList) => {
queries.push(identNode.name);
}
});
}
});
// Just basic media query support for now
let shouldNotApply = queries.some((query, index) => {
let q = query;
if (q === "not") {
q = queries[index + 1];
return !(q === "screen" || q === "speech");
} else {
return (q === "screen" || q === "speech");
}
});
if (shouldNotApply) {
return;
}
csstree.walk(node, {
visit: "String",
enter: (urlNode, urlItem, urlList) => {
let href = urlNode.value.replace(/["']/g, "");
let url = new URL(href, this.url);
let value = url.toString();
this.imported.push(value);
// Remove the original
list.remove(item);
}
});
}
set text(t) { set text(t) {
this._text = t; this._text = t;
} }
......
export default async function request(url, options={}) {
return new Promise(function(resolve, reject) {
let request = new XMLHttpRequest();
request.open(options.method || 'get', url, true);
for (let i in options.headers) {
request.setRequestHeader(i, options.headers[i]);
}
request.withCredentials = options.credentials=='include';
request.onload = () => {
resolve(new Response(request.responseText, {status: request.status}));
};
request.onerror = reject;
request.send(options.body || null);
});
}
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