1
0
mirror of https://github.com/twirl/The-API-Book.git synced 2025-01-05 10:20:22 +02:00

covers added

This commit is contained in:
Sergey Konstantinov 2021-01-04 02:33:33 +03:00
parent 397b5d3557
commit 3dc0a64e59
12 changed files with 204 additions and 57 deletions

View File

@ -6,8 +6,6 @@ const builders = require('./src/lib/builders');
const mdHtml = require('./src/lib/md-html');
const htmlProcess = require('./src/lib/html-process');
const css = fs.readFileSync('./src/style.css', 'utf-8');
const l10n = {
en: require('./src/en/l10n.json'),
ru: require('./src/ru/l10n.json')
@ -66,20 +64,20 @@ async function buildDoc (lang, targets, l10n) {
}, [templates.sectionTitle(section)]).join(''))
];
const html = targets.html || targets.pdf ? (await htmlProcess(
templates.html(htmlContent.join(''), css, l10n), {
base: __dirname
}
)).contents : '';
return Promise.all(['html', 'pdf', 'epub'].map((target) => {
return targets[target] ? builders[target]({
lang,
structure,
html,
l10n,
path: path.join(__dirname, 'docs', `API.${lang}.${target}`)
}) : Promise.resolve();
if (targets[target]) {
return prepareHtml(htmlContent.join(''), l10n, target).then((html) => {
return builders[target]({
lang,
structure,
html,
l10n,
path: path.join(__dirname, 'docs', `API.${lang}.${target}`)
});
});
} else {
return Promise.resolve();
}
}));
}
@ -129,4 +127,16 @@ async function getStructure ({ path, l10n, pageBreak}) {
return structure;
}
async function prepareHtml (content, l10n, target) {
if (target == 'epub') {
return '';
} else {
return (await htmlProcess(
templates[target == 'html' ? 'screenHtml' : 'printHtml'](content, l10n), {
base: __dirname
}
)).contents;
}
}

View File

@ -5,14 +5,15 @@
"author": "Sergey Konstantinov <twirl-team@yandex.ru>",
"repository": "github.com:twirl/The-API-Book",
"devDependencies": {
"puppeteer": "^5.5.0",
"css": "^3.0.0",
"epub-gen": "^0.1.0",
"unified": "^9.2.0",
"remark-parse": "^8.0.3",
"remark-rehype": "^7.0.0",
"image-data-uri": "^2.0.1",
"puppeteer": "^5.5.0",
"rehype-parse": "^7.0.1",
"rehype-stringify": "^8.0.0",
"image-data-uri": "^2.0.1"
"remark-parse": "^8.0.3",
"remark-rehype": "^7.0.0",
"unified": "^9.2.0"
},
"scripts": {
"build": "node build.js"

BIN
src/cover_300dpi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

BIN
src/cover_96dpi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 KiB

View File

@ -58,6 +58,10 @@ h3 {
font-variant: small-caps;
}
h3 a, h5 a {
color: inherit;
}
h4, h5 {
font-size: 120%;
}

View File

@ -1,22 +1,17 @@
const fs = require('fs');
const path = require('path');
const fsPath = require('path');
const puppeteer = require('puppeteer');
const Epub = require('epub-gen');
const css = fs.readFileSync(path.resolve(__dirname, '..', 'epub.css'), 'utf-8');
const css = fs.readFileSync(fsPath.resolve(__dirname, '..', 'epub.css'), 'utf-8');
module.exports = {
html: function ({ html, path }) {
return new Promise((resolve, reject) => {
fs.writeFile(path, html, (e) => {
if (e) {
reject(e);
} else {
resolve();
}
});
});
fs.writeFileSync(path, html);
resolve();
});
},
pdf: async function ({ path, html }) {
const browser = await puppeteer.launch({ headless: true });

22
src/lib/css-process.js Normal file
View File

@ -0,0 +1,22 @@
const path = require('path');
const fs = require('fs');
const imageDataUri = require('image-data-uri');
const reworkCss = require('css');
module.exports = (css) => {
const ast = reworkCss.parse(css);
(ast.stylesheet.rules || []).forEach((rule) => {
(rule.declarations || []).forEach((declaration) => {
if (declaration.property == 'background-image') {
const file = declaration.value.match(/url\((.+)\)/)[1];
const data = fs.readFileSync(path.resolve(__dirname, '../..', file));
const uri = imageDataUri.encode(data, 'image/png');
declaration.value = `url(${uri})`;
}
});
})
return reworkCss.stringify(ast);
}

View File

@ -27,11 +27,41 @@ const chapterProcessor = () => {
}
}
let h5counter = 0;
tree.children.slice().forEach((node, index) => {
switch (node.tagName) {
case 'h3':
title.push(node.children[0].value);
tree.children.splice(index, 1);
h5counter = 0;
break;
case 'h5':
let value = node.children[0].value;
let number;
const match = value.match(/^\d+/);
if (!match) {
number = ++h5counter;
value = `${number}. ${value}`;
} else {
number = match[0];
}
const anchor = `chapter-${counter}-paragraph-${number}`;
node.children[0] = {
type: 'element',
tagName: 'a',
properties: {
href: '#' + anchor,
name: anchor,
className: ['anchor']
},
children: [{
type: 'text',
value
}],
position: node.children[0].position
};
break;
}
imageProcess(node);

58
src/print.css Normal file
View File

@ -0,0 +1,58 @@
html, body {
margin: 0;
padding: 0;
font-size: 14pt;
}
.github-corner {
display: none;
}
pre, img {
margin-right: 0.1em;
}
img {
margin-top: 1em;
}
:root {
--main-font: 'PT Serif';
--alt-font: 'PT Serif';
--code-font: Inconsolata;
}
.cover {
background-image: url(./src/cover_300dpi.png);
background-size: 100% auto;
background-repeat: no-repeat;
background-position: 50% 100%;
width: 100%;
height: 10.05in;
margin: 0;
padding: 0;
}
.annotation {
padding-top: 6in;
}
h1 {
padding: 1in 0.5in;
font-size: 40pt;
margin: 0;
}
p, ul, ol {
orphans: 4;
}
@page {
margin: 0.5in;
size: 8.5in 11in;
}
@page:first {
margin: 0;
size: 7.5in 10in;
}

12
src/screen.css Normal file
View File

@ -0,0 +1,12 @@
h1 {
font-size: 48px;
background-image: url(./src/cover_96dpi.png);
background-repeat: no-repeat;
background-position: 50% 100%;
height: 1056px;
min-width: 300px;
max-width: 816px;
margin: 0 auto;
padding-top: 4em;
padding-left: 2em;
}

View File

@ -108,6 +108,10 @@ h4, h5 {
font-size: 120%;
}
.annotation {
text-align: left;
}
ul.table-of-contents {
list-style-type: none;
padding-left: 0;
@ -130,17 +134,6 @@ a.anchor {
text-decoration: none;
}
@page {
size: 8.5in 11in;
margin: 0.5in;
}
:root {
--main-font: 'PT Serif';
--alt-font: 'PT Serif';
--code-font: Inconsolata;
}
@media screen {
body {
margin: 2em auto;
@ -155,14 +148,19 @@ a.anchor {
content: '¶';
width: 0.8em;
color: lightgray;
text-indent: 0;
}
h5 a.anchor:before {
color: transparent;
}
a.anchor:hover:before {
color: black;
}
h2:not(.toc), h3 {
margin-left: -0.8em;
h2:not(.toc), h3, h5 {
text-indent: -0.8em;
}
@keyframes octocat-wave {
@ -181,19 +179,6 @@ a.anchor {
}
}
@media print {
h1 {
margin: 4in 0 4in 0;
}
body {
font-size: 14pt;
}
.github-corner {
display: none;
}
}
@media screen and (max-width: 1000px) {
body {
padding: 2em;

View File

@ -1,5 +1,13 @@
const fs = require('fs');
const path = require('path');
const css = fs.readFileSync(path.resolve(__dirname, 'style.css'), 'utf-8');
const cssProcess = require('./lib/css-process');
const printCss = cssProcess(fs.readFileSync(path.resolve(__dirname, 'print.css'), 'utf-8'));
const screenCss = cssProcess(fs.readFileSync(path.resolve(__dirname, 'screen.css'), 'utf-8'));
const templates = module.exports = {
html: (html, css, l10n) => {
screenHtml: (html, l10n) => {
return `<html><head>
<meta charset="utf-8"/>
<title>${l10n.author}. ${l10n.title}</title>
@ -12,6 +20,28 @@ const templates = module.exports = {
<meta property="og:locale" content="${l10n.locale}"/>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=PT+Serif&amp;family=PT+Sans&amp;family=Inconsolata"/>
<style>${css}</style>
<style>${screenCss}</style>
</head><body>
<article>
${html}
</article>
</body></html>`;
},
printHtml: (html, l10n) => {
return `<html><head>
<meta charset="utf-8"/>
<title>${l10n.author}. ${l10n.title}</title>
<meta name="author" content="${l10n.author}"/>
<meta name="description" content="${l10n.description}"/>
<meta property="og:title" content="${l10n.author}. ${l10n.title}"/>
<meta property="og:url" content="${l10n.url}"/>
<meta property="og:type" content="article"/>
<meta property="og:description" content="${l10n.description}"/>
<meta property="og:locale" content="${l10n.locale}"/>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=PT+Serif&amp;family=PT+Sans&amp;family=Inconsolata"/>
<style>${css}</style>
<style>${printCss}</style>
</head><body>
<article>
${html}