1
0
mirror of https://github.com/twirl/The-API-Book.git synced 2025-08-10 21:51:42 +02:00

various build improvements

This commit is contained in:
Sergey Konstantinov
2023-09-24 23:27:06 +03:00
parent b292809fba
commit 7ecb663613
19 changed files with 561 additions and 342 deletions

Binary file not shown.

View File

@@ -346,6 +346,7 @@ ul.references li a.back-anchor {
text-align: right;
padding-right: 0.3em;
}
body > article {
position: relative;
}
@@ -545,11 +546,6 @@ article ul.share {
z-index: 1;
}
body > article {
margin: 2em auto;
max-width: 60%;
}
a.anchor:before {
display: inline-block;
content: '¶';
@@ -582,11 +578,6 @@ ul.references li p a.back-anchor {
flex-shrink: 0;
}
@media screen {
.github-corner:hover .octo-arm {
animation: octocat-wave 560ms ease-in-out;
}
a.anchor:before {
display: inline-block;
content: '¶';
@@ -609,18 +600,10 @@ ul.references li p a.back-anchor {
text-indent: -0.8em;
}
@keyframes octocat-wave {
0%, 100% {
transform: rotate(0);
}
20%, 60% {
transform: rotate(-25deg);
}
40%, 80% {
transform: rotate(10deg);
}
@media screen {
body > article {
margin: 2em auto;
max-width: 60%;
}
}
@@ -664,7 +647,98 @@ ul.references li p a.back-anchor {
.cover {
font-size: 2.8vw;
}
}</style>
}
@media print {
html,
body {
margin: 0;
padding: 0;
font-size: 14pt;
}
.toc a,
ul li,
ol li {
text-size-adjust: none;
}
pre {
margin: 0 0 1em 0;
width: calc(100% - 2px);
line-height: 0.8em !important;
}
p code,
pre code {
font-size: 12pt !important;
}
img {
margin: 1px;
}
img.cc-by-nc-img {
width: 90px;
}
h1,
h2,
h3,
h4,
h5 {
break-after: avoid;
line-height: 1.2em;
font-size: 120%;
}
h6 {
break-before: avoid;
}
p,
li {
orphans: 5;
widows: 5;
}
img {
margin-top: 1em;
break-after: avoid;
}
.cover {
display: none;
}
.toc ul li ul li + li,
h4 + ul,
h4 + p {
break-inside: avoid;
break-before: avoid;
break-after: avoid;
}
.page-break {
break-after: page;
}
.no-page-break {
break-inside: avoid;
}
nav.page-main {
display: none;
}
}
@media print {
@page {
margin: 28mm 25mm 30mm 25mm;
padding: 0;
size: A4;
}
}
</style>
</head><body><div class="fade display-none"></div>
<aside class="side-panel display-none">
<h3 class="title">Sergey Konstantinov. The API</h3>

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

BIN
docs/API.ru.sample.epub Normal file

Binary file not shown.

View File

@@ -7,7 +7,7 @@
"version": "2.0.0",
"devDependencies": {
"@jest/globals": "^29.6.4",
"@twirl/book-builder": "0.0.27",
"@twirl/book-builder": "0.0.28",
"@types/jest": "^29.5.4",
"express": "^4.18.2",
"jest": "^29.6.4",
@@ -22,9 +22,9 @@
},
"scripts": {
"build": "node scripts/build.mjs",
"build-samples": "node scripts/build.mjs en,ru epub 21-22 --sample",
"build-v1": "node scripts/build-v1.mjs",
"build-graphs": "node scripts/build-graphs.mjs",
"build-clean": "node scripts/build.mjs --clean",
"build-examples": "node scripts/build-examples.js \"docs/examples/01. Decomposing UI Components\"",
"docs-server": "node scripts/docs-server 3000",
"test": "jest"

View File

@@ -11,6 +11,8 @@ const { flags, args } = process.argv.slice(2).reduce(
case '--no-cache':
flags.noCache = true;
break;
case '--sample':
flags.sample = true;
}
if (!v.startsWith('--')) {
args.push(v);
@@ -28,6 +30,24 @@ const l10n = {
ru: JSON.parse(readFileSync('./src/ru/l10n.json', 'utf-8'))
};
const css = ['fonts', 'common', 'screen', 'print', 'page', 'epub'].reduce(
(css, file) => {
css[file] = readFileSync(`src/css/${file}.css`).toString('utf-8');
return css;
},
{}
);
const targetCss = {
html: [css.fonts, css.common, css.screen, css.print],
pdf: [css.fonts, css.common, css.print],
epub: [css.common, css.epub]
};
const extraCss = {
html: css.page,
pdf: css.page
};
const langsToBuild = (args[0] && args[0].split(',').map((s) => s.trim())) || [
'ru',
'en'
@@ -51,6 +71,7 @@ console.log(`Building langs: ${langsToBuild.join(', ')}…`);
(async () => {
for (const lang of langsToBuild) {
await init({
lang,
l10n: l10n[lang],
basePath: pathResolve(`src`),
path: pathResolve(`src/${lang}/clean-copy`),
@@ -94,6 +115,7 @@ console.log(`Building langs: ${langsToBuild.join(', ')}…`);
},
chapters,
noCache,
sample: flags.sample,
cover: 'src/cover_embed.png'
}).then(async (builder) => {
for (const target of Object.keys(targets)) {
@@ -102,8 +124,14 @@ console.log(`Building langs: ${langsToBuild.join(', ')}…`);
target,
pathResolve(
'docs',
`${l10n[lang].file}.${lang}.${target}`
)
`${l10n[lang].file}.${lang}${
flags.sample ? '.sample' : ''
}.${target}`
),
{
css: targetCss[target],
extraCss: extraCss[target]
}
);
console.log(
`Finished lang=${lang} target=${target}\n${Object.entries(

View File

@@ -1,61 +1,3 @@
@font-face {
font-family: local-serif;
src: url(/fonts/Vollkorn-VariableFont_wght.ttf);
}
@font-face {
font-family: local-serif;
src: url(/fonts/Vollkorn-Italic-VariableFont_wght.ttf);
font-style: italic;
}
@font-face {
font-family: local-serif;
src: url(/fonts/Vollkorn-Italic-VariableFont_wght.ttf);
font-style: oblique;
}
@font-face {
font-family: local-sans;
src: url(/fonts/PTSans-Regular.ttf);
}
@font-face {
font-family: local-sans;
src: url(/fonts/PTSans-Bold.ttf);
font-weight: bold;
}
@font-face {
font-family: local-sans;
src: url(/fonts/PTSans-Italic.ttf);
font-style: oblique;
}
@font-face {
font-family: local-sans;
src: url(/fonts/PTSans-Italic.ttf);
font-style: italic;
}
@font-face {
font-family: local-sans;
src: url(/fonts/PTSans-BoldItalic.ttf);
font-style: oblique;
font-weight: bold;
}
@font-face {
font-family: local-sans;
src: url(/fonts/PTSans-BoldItalic.ttf);
font-style: italic;
font-weight: bold;
}
@font-face {
font-family: local-monospace;
src: url(/fonts/RobotoMono-VariableFont_wght.ttf);
}
html,
body {
width: 100%;

View File

@@ -1,5 +1,5 @@
body {
font-family: serif;
font-family: 'Vollkorn', serif;
font-size: 14pt;
text-align: justify;
}
@@ -18,7 +18,7 @@ h3,
h4,
h5 {
text-align: left;
font-family: sans-serif;
font-family: 'PT Sans', sans-serif;
font-weight: bold;
page-break-after: avoid;
}
@@ -52,3 +52,8 @@ div {
widows: 2;
orphans: 2;
}
pre,
code {
font-family: 'Roboto Mono', monospace;
}

57
src/css/fonts.css Normal file
View File

@@ -0,0 +1,57 @@
@font-face {
font-family: local-serif;
src: url(/fonts/Vollkorn-VariableFont_wght.ttf);
}
@font-face {
font-family: local-serif;
src: url(/fonts/Vollkorn-Italic-VariableFont_wght.ttf);
font-style: italic;
}
@font-face {
font-family: local-serif;
src: url(/fonts/Vollkorn-Italic-VariableFont_wght.ttf);
font-style: oblique;
}
@font-face {
font-family: local-sans;
src: url(/fonts/PTSans-Regular.ttf);
}
@font-face {
font-family: local-sans;
src: url(/fonts/PTSans-Bold.ttf);
font-weight: bold;
}
@font-face {
font-family: local-sans;
src: url(/fonts/PTSans-Italic.ttf);
font-style: oblique;
}
@font-face {
font-family: local-sans;
src: url(/fonts/PTSans-Italic.ttf);
font-style: italic;
}
@font-face {
font-family: local-sans;
src: url(/fonts/PTSans-BoldItalic.ttf);
font-style: oblique;
font-weight: bold;
}
@font-face {
font-family: local-sans;
src: url(/fonts/PTSans-BoldItalic.ttf);
font-style: italic;
font-weight: bold;
}
@font-face {
font-family: local-monospace;
src: url(/fonts/RobotoMono-VariableFont_wght.ttf);
}

7
src/css/page.css Normal file
View File

@@ -0,0 +1,7 @@
@media print {
@page {
margin: 28mm 25mm 30mm 25mm;
padding: 0;
size: A4;
}
}

View File

@@ -1,9 +1,4 @@
@media print {
@page {
margin: 20mm 18mm 27mm 25mm;
size: letter;
}
html,
body {
margin: 0;
@@ -50,7 +45,8 @@
break-before: avoid;
}
p {
p,
li {
orphans: 5;
widows: 5;
}

View File

@@ -197,11 +197,6 @@ article ul.share {
z-index: 1;
}
body > article {
margin: 2em auto;
max-width: 60%;
}
a.anchor:before {
display: inline-block;
content: '¶';
@@ -234,11 +229,6 @@ ul.references li p a.back-anchor {
flex-shrink: 0;
}
@media screen {
.github-corner:hover .octo-arm {
animation: octocat-wave 560ms ease-in-out;
}
a.anchor:before {
display: inline-block;
content: '¶';
@@ -261,19 +251,10 @@ ul.references li p a.back-anchor {
text-indent: -0.8em;
}
@keyframes octocat-wave {
0%,
100% {
transform: rotate(0);
}
20%,
60% {
transform: rotate(-25deg);
}
40%,
80% {
transform: rotate(10deg);
}
@media screen {
body > article {
margin: 2em auto;
max-width: 60%;
}
}

View File

@@ -88,6 +88,11 @@
"<p class=\"cc-by-nc\">This book is distributed under the <a href=\"https://creativecommons.org/licenses/by-nc/4.0/\">Creative Commons Attribution-NonCommercial 4.0 International licence</a>.</p>"
]
},
"samplePage": {
"contents": [
"<p>This is a sample fragment comprising chapters 21 and 22 of the Section II: The API Patterns.</p>"
]
},
"landing": {
"subTitle": "Free e-book",
"subscribeOn": "Subscribe for updates on",

View File

@@ -90,6 +90,11 @@
"<p class=\"cc-by-nc\">Это произведение доступно по <a href=\"https://creativecommons.org/licenses/by-nc/4.0/\">лицензии Creative Commons «Attribution-NonCommercial» («Атрибуция — Некоммерческое использование») 4.0 Всемирная</a>.</p>"
]
},
"samplePage": {
"contents": [
"<p>Этот ознакомительный фрагмент содержит главы 21 и 22 раздела «Паттерны API».</p>"
]
},
"landing": {
"subTitle": "Бесплатная электронная книга",
"subscribeOn": "Подпишитесь на обновления на",

View File

@@ -30,6 +30,31 @@ export const templates = {
}" href="https://isbnsearch.org/isbn/${isbn}">${l10n.isbn} ${isbn}</a>`;
},
footerTemplate: (l10n) => {
return `<html><head><style>
.content {
width: 100%;
font-size: 12pt;
font-family: local-serif, Vollkorn;
text-align: right;
margin: 0 25mm 18mm 25mm;
border-top: 1px solid black;
padding-top: 2mm;
}
.pageNumber {
display: inline-block;
border-left: 1px solid black;
width: 30pt;
}
.title {
padding-right: 4pt;
}
</style></head><body>
<div class="content"><span class="title">${l10n.author}. ${l10n.title}</span>
<span class="pageNumber"></span></div>
</body></html>`;
},
sidePanel: ({
structure,
l10n,
@@ -99,6 +124,26 @@ export const templates = {
templates
})}</p><div class="page-break"></div>`,
samplePage: ({ l10n }) => `
<div class="cover">
<h1>
<span class="author">${l10n.author}</span><br /><span class="title"
>${l10n.frontPage.title}</span
>
</h1>
</div><div class="annotation"><p class="text-align-left">
<strong>${l10n.author}. ${l10n.title}.</strong><br />
<a target="_blank" href="mailto:${l10n.links.email}">${
l10n.links.emailString
}</a> &middot; <a target="_blank" href="${l10n.links.linkedinHref}">${
l10n.links.linkedinString
}</a> &middot; <a target="_blank" href="${l10n.links.substackHref}">${
l10n.links.substackString
}</a></p>
${l10n.samplePage.contents.join('\n')}
<div class="page-break"></div>
</div>`,
shareLink: (link, parameters) => {
let result = link;
for (const [key, value] of Object.entries(parameters)) {