Skip to content

Commit 445cf5c

Browse files
committed
Set up the CSS to convert to PDF using Prince XML.
* Finished out the margin boxes to put the document number and current section in the right corners. * Adjusted font sizes and spacing to better match the C++ standard. * Switched to using <h1> to define section titles and <header> to style them, for better control over PDF bookmarks. * Generated page numbers in the table of contents when printing. * Lined up the markers better in the table of contents. * Changed how styles are transferred to the standalone document, so that styles the browser doesn't understand are preserved. * Fixed some formatting in the Normative References section.
1 parent 9b3c8f7 commit 445cf5c

14 files changed

+817
-194
lines changed

README.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,9 @@ Custom C++-specific elements
5454

5555
These automatically number clauses and sections, fill in
5656
table-of-contents data, and allow cross-linking. `<cxx-clause>` is for
57-
top-level sections, while `<cxx-section>` can be nested
58-
arbitrarily. The title of the section is given in either the `title`
59-
attribute or a nested `<cxx-title>` element. The `id` attribute is
60-
used for cross-linking.
57+
top-level sections, while `<cxx-section>` can be nested arbitrarily.
58+
The title of the section is given in a nested `<h1>` element.
59+
The `id` attribute is used for cross-linking.
6160

6261
### `<cxx-titlepage>`
6362

base.css

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,60 @@
11
@page {
22
margin: 10%;
3-
@top-left { content: "© ISO/IEC"; }
4-
@bottom-right { content: counter(page); }
3+
@top-left { content: "© ISO/IEC"; font-size: 10pt; }
4+
@top-right { content: string(docnum); font-weight: bold; font-size: 10pt; }
5+
@bottom-left { content: string(current-section, last); font-size: 10pt; }
6+
@bottom-right { content: counter(page); font-size: 10pt; }
57
}
8+
cxx-titlepage { page: title; page-break-after: always; }
69
@page title {
7-
@top-left { content: normal; }
10+
@top-left { content: "© ISO 2014 — All rights reserved"; }
11+
@top-right { content: normal; }
12+
@bottom-left { content: normal; }
813
@bottom-right { content: normal; }
914
}
1015

1116
@media screen {
12-
body { max-width: 7in; }
17+
body { max-width: 7in;
18+
/* Make room for paragraph numbers. */
19+
margin-left: 2em }
1320
}
1421

1522
@media print {
16-
/* Current PDF output from browsers doesn't preserve links, so avoid
17-
the affordance that says the text is a link. */
18-
a[href] { color:black; text-decoration:none; }
23+
html { font-size: 10pt; }
24+
pre,code { font-size: 8pt; }
25+
/* Note that only Prince generates clickable links. */
26+
a[href] { text-decoration:none; }
1927
}
2028

2129
/* Needed to make the <cxx-titlepage>'s vertical spacing work. */
2230
html, body {height: 100%}
23-
body { margin-left: 1.5em }
2431

25-
cxx-clause ^ h1 { font-size: 150%; }
32+
cxx-docnum { string-set: docnum content(); }
33+
34+
cxx-clause { page-break-before: always; }
35+
@media screen {
36+
cxx-clause, cxx-toc { margin-top: 3em; }
37+
}
38+
39+
cxx-clause ^ header { font-size: 150%; }
2640
cxx-toc ^ h1 { font-size: 150%; }
27-
cxx-clause cxx-section ^ h1 { font-size: 117% }
28-
cxx-clause cxx-section cxx-section ^ h1 { font-size: 100% }
41+
cxx-clause cxx-section ^ header { font-size: 117%; }
42+
cxx-clause cxx-section cxx-section ^ header { font-size: 100%; }
43+
44+
[data-bookmark-label] { bookmark-label: attr(data-bookmark-label); }
45+
h1 { bookmark-level: 1; }
46+
cxx-toc ^ h1 { bookmark-level: 2; }
47+
cxx-clause h1 { bookmark-level: 2; }
48+
cxx-clause cxx-section h1 { bookmark-level: 3; }
49+
cxx-clause cxx-section cxx-section h1 { bookmark-level: 4; }
50+
51+
* ^ .section-number { string-set: current-section "§ " content(); }
2952

3053
p {margin-top: .5em; margin-bottom: .5em}
3154
p:first-child, ul, ol {margin-top: 0}
3255

3356
[para_num]::before { content: attr(para_num); float: left;
34-
font-size: 60%; margin-left: -2em; width: 1.5em; text-align: right; }
57+
font-size: 70%; margin-left: -2.5em; width: 1.5em; text-align: right; }
3558

3659
aside { float: right; max-width: 40%;
3760
margin: 1ex;
@@ -43,7 +66,10 @@ ins {text-decoration: underline; color: #005100;}
4366

4467
pre { margin-left: 1em; }
4568

46-
cxx-clause { page-break-before: always; }
47-
@media not paged {
48-
cxx-clause, cxx-toc { margin-top: 3em; }
69+
/* This is here rather than inside elements/toc.html because browsers
70+
don't understand leader() or target-counter(), so they drop them
71+
inside the CSSOM. */
72+
@media print {
73+
/* Generate page numbers in the table of contents. */
74+
cxx-toc ^ a[href]::after { content: leader(" . ") target-counter(attr(href), page); }
4975
}

elements/clause.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
(function() {
44
var clause_num = 1;
55
Polymer('cxx-clause', {
6-
created: function() {
6+
ready: function() {
77
this.update_sec_nums(clause_num++);
8-
CxxSectionElement.prototype.created.apply(this);
8+
CxxSectionElement.prototype.ready.apply(this);
99
},
1010
});
1111
})();

elements/function.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
<template>
2828
<style>
2929
:host {display:block; margin-top: .5em; margin-bottom: .5em;}
30-
dt { float: left; font-style: italic; padding-right: 1ex;}
30+
dt { float: left; font-style: italic; font-weight: normal; padding-right: 1ex;}
3131
dd { margin-left: 0em; }
3232
/* @polyfill dd > ul, dd > ol */
3333
::content > ul, ::content > ol { clear: left; }

elements/publish.js

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,23 @@
2828
return document.createComment(scriptComment);
2929
}
3030

31+
function fetch(url) {
32+
return new Promise(function(resolve, reject) {
33+
var request = new XMLHttpRequest();
34+
request.onload = function() {
35+
resolve(this.responseText);
36+
}
37+
request.onerror = function() {
38+
reject(this);
39+
}
40+
request.onabort = function() {
41+
reject(this);
42+
}
43+
request.open('GET', url);
44+
request.send();
45+
});
46+
}
47+
3148
function cloneStaticAndInline(doc) {
3249
var copy = doc.cloneNode(true);
3350
function removeAll(nodes) {
@@ -40,39 +57,51 @@
4057
removeAll(copy.querySelectorAll('cxx-publish-button'));
4158

4259
// Inline all style sheets.
43-
removeAll(copy.querySelectorAll('style'));
44-
removeAll(copy.querySelectorAll('link'));
45-
var allStyles = '';
46-
forEach(doc.styleSheets,
47-
function(sheet) {
60+
var sheetUpdates = Array.prototype.map.call(
61+
copy.querySelectorAll('link[rel="stylesheet"]'),
62+
function(extSheet) {
63+
return fetch(extSheet.href).catch(function(error) {
64+
console.warning('Could not fetch', extSheet.href,
65+
'falling back to stylesheet contents.',
66+
error);
67+
var styleText = '';
68+
var sheet = extSheet.sheet;
4869
if (!sheet.disabled) {
4970
forEach(sheet.cssRules, function(rule) {
50-
allStyles += rule.cssText;
71+
styleText += rule.cssText;
5172
});
5273
}
74+
return styleText;
75+
}).then(function(styleText) {
76+
var inlinedStyle = copy.createElement('style');
77+
inlinedStyle.textContent = styleText;
78+
extSheet.parentNode.insertBefore(inlinedStyle, extSheet);
79+
extSheet.parentNode.removeChild(extSheet);
5380
});
54-
var allStylesElem = copy.createElement('style');
55-
allStylesElem.textContent = allStyles;
56-
copy.head.appendChild(allStylesElem);
81+
});
5782

5883
copy.head.insertBefore(declareCustomTagNamesForIE8(),
5984
copy.head.firstElementChild);
6085

61-
return copy;
86+
return Promise.all(sheetUpdates).then(function() {
87+
return copy;
88+
});
6289
}
6390

6491
Polymer('cxx-publish-button', {
6592
publish: function() {
66-
var copy = cloneStaticAndInline(document);
93+
var copyPromise = cloneStaticAndInline(document);
6794
var source = '';
6895
if (this.source) {
6996
var source = '<!-- Sources at ' + this.source + ' -->\n';
7097
}
71-
var published = new Blob(['<!DOCTYPE html>\n',
72-
source,
73-
copy.documentElement.outerHTML],
74-
{type: 'text/html'});
75-
window.open(URL.createObjectURL(published), '_blank');
98+
copyPromise.then(function(copy) {
99+
var published = new Blob(['<!DOCTYPE html>\n',
100+
source,
101+
copy.documentElement.outerHTML],
102+
{type: 'text/html'});
103+
window.open(URL.createObjectURL(published), '_blank');
104+
});
76105
}
77106
});
78107
})();

elements/ref.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
><template if="{{in_elem.index}}">{{in_elem.name}} &#xa7;{{in_elem.index[to]}}</template
1717
><template if="{{!in}}"><a href="#{{to}}">{{to_elem.sec_num}}</a></template
1818
></template
19-
><template if="{{insynopsis}}">// <i><template bind="" ref="target_num"></template>, {{to_elem.text_title}}</i></template
19+
><template if="{{insynopsis}}">// <i><template bind="" ref="target_num"></template>, {{to_elem.title_element.textContent}}</i></template
2020
><template if="{{!insynopsis}}">(<template bind="" ref="target_num"></template>)</template
2121
></template>
2222
<script src="ref.js"></script>

elements/section.html

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,22 @@
22
Recognizes attributes 'id' and 'title', but marking these as attributes
33
cause problems for the ShadowDOM polyfill.
44
-->
5-
<polymer-element name="cxx-section" constructor="CxxSectionElement" attributes="">
5+
<polymer-element name="cxx-section" constructor="CxxSectionElement">
66
<template>
77
<style>
88
:host { display: block; }
99
:host:target {background-color: inherit;}
1010
:host:target > section > h1 {background-color: #fed;}
11-
h1::after { clear:both; display: block; content: " "; height: 0 }
11+
/* @polyfill header > h1 */
12+
::content h1 { display: inline; font-size: 100%; }
13+
header { font-weight: bold; margin-top: 20px; margin-bottom: 20px; }
14+
header::after { clear:both; display: block; content: " "; height: 0 }
1215
</style>
1316

1417
<section>
15-
<h1>{{sec_num}} {{title}}<content select="cxx-title"></content> <span style="float:right"><a href="#{{id}}">[{{id}}]</a></span></h1>
18+
<header><span class="section-number">{{sec_num}}</span> <content select="h1"></content> <span style="float:right"><a href="#{{id}}">[{{id}}]</a></span></header>
1619
<content></content>
1720
</section>
1821
</template>
1922
<script src="section.js"></script>
2023
</polymer-element>
21-
<polymer-element name="cxx-title" noscript>
22-
<template><content></content></template>
23-
</polymer-element>

elements/section.js

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
Polymer('cxx-section', {
33
// String section number, like "17.2.3". 1-based.
44
sec_num: "?",
5-
text_title: "",
6-
title_element: null,
75

86
applyAuthorStyles: true,
97

@@ -18,19 +16,18 @@
1816
}
1917
},
2018

21-
created: function() {
22-
var title_element = this.querySelector('cxx-title');
23-
if (title_element && title_element.parentElement != this)
24-
title_element = null;
25-
if (title_element && this.title)
26-
console.warn(this, 'has two titles');
27-
if (!title_element && !this.title)
28-
console.warn(this, 'has no title');
29-
this.text_title = this.title;
30-
if (title_element) {
31-
this.title_element = title_element;
32-
this.text_title = title_element.textContent;
19+
sec_numChanged: function() {
20+
if (this.title_element) {
21+
this.title_element.setAttribute(
22+
'data-bookmark-label',
23+
this.sec_num + ' ' + this.title_element.textContent);
3324
}
25+
},
26+
27+
ready: function() {
28+
var title_element = this.querySelector('h1');
29+
if (title_element && title_element.parentElement == this)
30+
this.title_element = title_element;
3431

3532
this.numberParagraphChildren();
3633
},

elements/titlepage.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
<polymer-element name="cxx-titlepage" attributes="stage">
1111
<template>
1212
<style>
13-
:host { display: block; page: 'title'; page-break-after: always; min-height: 100%; }
13+
:host { display: block; min-height: 100%; }
1414

1515
/* position:relative on :host makes position:absolute on its children work
1616
relative to :host's bounds. */

elements/toc.html

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,28 @@
44
<template>
55
<style>
66
:host { display: block; }
7+
nav > ol { font-weight: bold; }
8+
ol { font-weight: normal; padding-left: 0; margin-left: 0; }
9+
10+
/* Browsers don't support ::marker or display:marker, so emulate it. */
711
li { list-style-type: none; }
8-
ol { font-weight: normal; }
9-
nav > ol { padding-left: 0; font-weight: bold; }
10-
.marker { margin-right: 1em; }
12+
.marker { display: inline-block; }
1113

12-
/* Enable when custom markers are supported:
13-
* http://www.w3.org/TR/css3-lists/#marker-pseudoelement
14-
* li { list-style-type: inline; }
15-
* .marker { display: marker; }
16-
*/
14+
li .marker { width: 2em; text-align: left; }
15+
ol ol { margin-left: 2em; }
16+
li li .marker { width: 3em; }
17+
ol ol ol { margin-left: 3em; }
18+
li li li .marker { width: 3.5em; }
19+
ol ol ol ol { margin-left: 3.5em; }
20+
li li li li .marker { width: 4.5em; }
1721
</style>
1822
<nav>
1923
<h1>Contents</h1>
2024
<template bind="" id="hierarchy">
2125
<template if="{{sections.length > 0}}">
2226
<ol>
2327
<template repeat="{{sections}}">
24-
<li><a href="#{{elem.id}}"><span class="marker">{{elem.sec_num}}</span>{{elem.text_title}}</a><template bind="" ref="hierarchy"
28+
<li><span class="marker">{{elem.sec_num}}</span><a href="#{{elem.id}}">{{title.textContent}}</a><template bind="" ref="hierarchy"
2529
></template></li>
2630
</template>
2731
</ol>

elements/toc.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
continue;
1414
sections.push(this.collectSections(child));
1515
}
16-
return {elem: root, sections: sections};
16+
return {elem: root,
17+
title: root.querySelector('h1'),
18+
sections: sections};
1719
},
1820

1921
created: function() {

0 commit comments

Comments
 (0)