Skip to content

Commit d793cbc

Browse files
committed
Improve epub generation
1 parent cd4147f commit d793cbc

6 files changed

Lines changed: 75 additions & 17 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,5 @@
2020
/img/cover.xcf
2121
/epub/[012]*.xhtml
2222
/epub/img/*
23+
/epub/content.opf
2324
/Eloquent_JavaScript.epub

Makefile

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,13 @@ ejs_tex.zip: nostarch/book.tex $(foreach CHAP,$(CHAPTERS),nostarch/$(CHAP).tex)
8484
mv /tmp/ejs_tex.zip $@
8585
rm -rf $(TMPDIR)
8686

87-
Eloquent_JavaScript.epub: epub/titlepage.xhtml epub/toc.xhtml $(foreach CHAP,$(CHAPTERS),epub/$(CHAP).xhtml) epub/content.opf epub/style.css
87+
Eloquent_JavaScript.epub: epub/titlepage.xhtml epub/toc.xhtml $(foreach CHAP,$(CHAPTERS),epub/$(CHAP).xhtml) \
88+
epub/content.opf.src epub/style.css bin/add_images_to_epub.js
8889
rm -f $@
90+
grep '<img' epub/*.xhtml | sed -e 's/.*src="\([^"]*\)".*/\1/' | xargs -I{} cp --parents "{}" epub
91+
node bin/add_images_to_epub.js
8992
cd epub; zip -X ../$@ mimetype
90-
cd epub; zip -X ../$@ -r * -x mimetype
93+
cd epub; zip -X ../$@ -r * -x mimetype -x content.opf.src
9194

92-
epub/%.xhtml: %.txt asciidoc_epub.conf
93-
asciidoc -f asciidoc_epub.conf --backend=xhtml11 -o $@ $<
95+
epub/%.xhtml: %.txt asciidoc_epub.conf bin/pre_epub.js
96+
node bin/pre_epub.js $< | asciidoc -f asciidoc_epub.conf --backend=xhtml11 -o $@ -

asciidoc_epub.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ template::[source-filter-style]
6363
<body>
6464
<article>
6565

66-
<h1{id? id="{id}"}>{chap_num?<span class="chap_num">Chapter {chap_num}</span>}{doctitle}</h1>
66+
<h1 id="{docid}">{chap_num?<span class="chap_num">Chapter {chap_num}</span>}{doctitle}</h1>
6767

6868
[footer]
6969
</article>

bin/add_images_to_epub.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
var fs = require("fs"), path = require("path");
2+
3+
var images = [];
4+
function scanDir(dir) {
5+
fs.readdirSync(dir).forEach(function(file) {
6+
var full = path.resolve(dir, file), type;
7+
if (fs.lstatSync(full).isDirectory())
8+
return scanDir(full);
9+
if (/\.svg$/.test(file))
10+
type = "image/svg+xml";
11+
else if (/\.png$/.test(file))
12+
type = "image/png";
13+
else if (/\.jpg$/.test(file))
14+
type = "image/jpeg";
15+
else
16+
throw new Error("Unknown image type: " + full);
17+
var local = full.slice(full.indexOf("/img/") + 1);
18+
images.push(" <item id=\"image." + file + "\" href=\"" + local + "\" media-type=\"" + type + "\"/>");
19+
});
20+
}
21+
scanDir("epub/img");
22+
23+
var out = fs.readFileSync("epub/content.opf.src", "utf8").replace("{{images}}", images.join("\n"));
24+
fs.writeFileSync("epub/content.opf", out);

bin/pre_epub.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Script to pre-process the asciidoc sources for generating EPUB.
2+
3+
var fs = require("fs"), child = require("child_process");
4+
5+
var infile = process.argv[2];
6+
7+
var instream;
8+
if (infile == "-") {
9+
instream = process.stdin;
10+
instream.resume();
11+
} else {
12+
instream = fs.createReadStream(infile);
13+
}
14+
15+
var input = "";
16+
instream.on("data", function(chunk) {
17+
input += chunk;
18+
});
19+
instream.on("end", function() {
20+
if (infile != "-")
21+
input = ":docid: " + infile.match(/^\d{2}_(.*?)\.txt/)[1] + "\n" + input;
22+
process.stdout.write(input.replace(/\blink:([^\.]+)\.html#(.*?)\[|!!(hint)!![^]+?!!hint!!(?:\n|$)/g,
23+
function(match, linkFile, linkID, hint) {
24+
if (linkFile) {
25+
return "link:" + linkFile + ".xhtml#" + linkID + "[";
26+
} else if (hint) {
27+
return "";
28+
}
29+
}));
30+
});
Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,30 +18,30 @@
1818
<item id="titlepage" href="titlepage.xhtml" media-type="application/xhtml+xml"/>
1919
<item id="c00_intro" href="00_intro.xhtml" media-type="application/xhtml+xml"/>
2020
<item id="c01_values" href="01_values.xhtml" media-type="application/xhtml+xml"/>
21-
<item id="c02_program_structure" href="02_program_structure.xhtml" media-type="application/xhtml+xml"/>
21+
<item id="c02_program_structure" href="02_program_structure.xhtml" media-type="application/xhtml+xml" properties="svg"/>
2222
<item id="c03_functions" href="03_functions.xhtml" media-type="application/xhtml+xml"/>
23-
<item id="c04_data" href="04_data.xhtml" media-type="application/xhtml+xml"/>
23+
<item id="c04_data" href="04_data.xhtml" media-type="application/xhtml+xml" properties="svg"/>
2424
<item id="c05_higher_order" href="05_higher_order.xhtml" media-type="application/xhtml+xml"/>
25-
<item id="c06_object" href="06_object.xhtml" media-type="application/xhtml+xml"/>
25+
<item id="c06_object" href="06_object.xhtml" media-type="application/xhtml+xml" properties="svg"/>
2626
<item id="c07_elife" href="07_elife.xhtml" media-type="application/xhtml+xml"/>
2727
<item id="c08_error" href="08_error.xhtml" media-type="application/xhtml+xml"/>
28-
<item id="c09_regexp" href="09_regexp.xhtml" media-type="application/xhtml+xml"/>
28+
<item id="c09_regexp" href="09_regexp.xhtml" media-type="application/xhtml+xml" properties="svg"/>
2929
<item id="c10_modules" href="10_modules.xhtml" media-type="application/xhtml+xml"/>
30-
<item id="c11_language" href="11_language.xhtml" media-type="application/xhtml+xml"/>
30+
<item id="c11_language" href="11_language.xhtml" media-type="application/xhtml+xml" properties="svg"/>
3131
<item id="c12_browser" href="12_browser.xhtml" media-type="application/xhtml+xml"/>
32-
<item id="c13_dom" href="13_dom.xhtml" media-type="application/xhtml+xml"/>
32+
<item id="c13_dom" href="13_dom.xhtml" media-type="application/xhtml+xml" properties="svg"/>
3333
<item id="c14_event" href="14_event.xhtml" media-type="application/xhtml+xml"/>
34-
<item id="c15_game" href="15_game.xhtml" media-type="application/xhtml+xml"/>
35-
<item id="c16_canvas" href="16_canvas.xhtml" media-type="application/xhtml+xml"/>
34+
<item id="c15_game" href="15_game.xhtml" media-type="application/xhtml+xml" properties="svg"/>
35+
<item id="c16_canvas" href="16_canvas.xhtml" media-type="application/xhtml+xml" properties="svg"/>
3636
<item id="c17_http" href="17_http.xhtml" media-type="application/xhtml+xml"/>
3737
<item id="c18_forms" href="18_forms.xhtml" media-type="application/xhtml+xml"/>
38-
<item id="c19_paint" href="19_paint.xhtml" media-type="application/xhtml+xml"/>
39-
<item id="c20_node" href="20_node.xhtml" media-type="application/xhtml+xml"/>
40-
<item id="c21_skillsharing" href="21_skillsharing.xhtml" media-type="application/xhtml+xml"/>
38+
<item id="c19_paint" href="19_paint.xhtml" media-type="application/xhtml+xml" properties="svg"/>
39+
<item id="c20_node" href="20_node.xhtml" media-type="application/xhtml+xml" properties="svg"/>
40+
<item id="c21_skillsharing" href="21_skillsharing.xhtml" media-type="application/xhtml+xml" properties="svg"/>
4141
<item id="style" href="style.css" media-type="text/css"/>
4242
<item id="font.cinzel.bold" href="font/cinzel_bold.otf" media-type="application/vnd.ms-opentype"/>
4343
<item id="font.pt.regular" href="font/pt_mono.otf" media-type="application/vnd.ms-opentype"/>
44-
<item id="cover-image" properties="cover-image" href="img/cover.png" media-type="image/png"/>
44+
{{images}}
4545
</manifest>
4646
<spine>
4747
<itemref idref="titlepage" linear="yes"/>

0 commit comments

Comments
 (0)