aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRalph Amissah <ralph.amissah@gmail.com>2026-09-12 22:25:26 -0400
committerRalph Amissah <ralph.amissah@gmail.com>2026-09-14 00:24:33 -0400
commita74e7ea61f797bd3f6bb9378124f8e1265e83cdf (patch)
treed25473671660df850adeda511e05a78c2f4a27fa
parentepub: manifest lists files, spine orders files (diff)
epub: mimetype entry comes first in the archive
OCF requires the mimetype entry to be the first in the zip and stored uncompressed, so that a reader can tell what the file is by looking at a known offset without parsing the archive. The index is now set to: 0 for the mimetype, 1 upward for everything else as it is added. mimetype Stored first META-INF/container.xml Stored OEBPS/toc_nav.xhtml Stored ... (assisted by Claude-Code)
-rw-r--r--org/out_xmls.org21
-rw-r--r--src/sisudoc/outputs/io_out/epub3.d21
2 files changed, 36 insertions, 6 deletions
diff --git a/org/out_xmls.org b/org/out_xmls.org
index b477d34..165cea2 100644
--- a/org/out_xmls.org
+++ b/org/out_xmls.org
@@ -3174,10 +3174,25 @@ zip -0 file.epub mimetype && zip -r -9 file.epub META-INF OEBPS
/+ zip file +/
auto fn_epub = pth_epub3.epub_file(doc_matters.src.filename);
auto zip = new ZipArchive(); // ZipArchive zip = new ZipArchive();
- /+ zip archive member files +/
- void EPUBzip()(string contents, string fn) {
+ /+ zip archive member files.
+ ZipArchive.build() emits members sorted by ArchiveMember.index, and
+ addMember does not set one. An epub is not free to choose: OCF requires the
+ mimetype entry to be the first in the archive, a reader being entitled to
+ look only there to tell what the file is. The index is therefore set
+ deliberately, 0 for the mimetype and 1 upward for the rest as they are
+ added.
+ .
+ Compression is already done for every member (ArchiveMember defaults to
+ it), which is the other half of what OCF asks of the mimetype.
+ +/
+ uint _zip_seq = 1;
+ void EPUBzip()(string contents, string fn, bool _is_mimetype = false) {
auto zip_arc_member_file = new ArchiveMember();
zip_arc_member_file.name = fn;
+ zip_arc_member_file.index = _is_mimetype ? 0 : _zip_seq++;
+ if (_is_mimetype) {
+ zip_arc_member_file.compressionMethod = CompressionMethod.none;
+ }
auto zip_data = new OutBuffer();
(doc_matters.opt.action.debug_do_epub)
? zip_data.write(contents.dup)
@@ -3262,7 +3277,7 @@ zip -0 file.epub mimetype && zip -r -9 file.epub META-INF OEBPS
}
}
fn = pth_epub3.fn_mimetypes;
- EPUBzip(epub_write.mimetypes, fn);
+ EPUBzip(epub_write.mimetypes, fn, true); /+ first in the archive +/
}
{ /+ META-INF/container.xml (identify doc root) +/
{ /+ debug +/
diff --git a/src/sisudoc/outputs/io_out/epub3.d b/src/sisudoc/outputs/io_out/epub3.d
index e07aeb8..d149dac 100644
--- a/src/sisudoc/outputs/io_out/epub3.d
+++ b/src/sisudoc/outputs/io_out/epub3.d
@@ -602,10 +602,25 @@ template outputEPub3() {
/+ zip file +/
auto fn_epub = pth_epub3.epub_file(doc_matters.src.filename);
auto zip = new ZipArchive(); // ZipArchive zip = new ZipArchive();
- /+ zip archive member files +/
- void EPUBzip()(string contents, string fn) {
+ /+ zip archive member files.
+ ZipArchive.build() emits members sorted by ArchiveMember.index, and
+ addMember does not set one. An epub is not free to choose: OCF requires the
+ mimetype entry to be the first in the archive, a reader being entitled to
+ look only there to tell what the file is. The index is therefore set
+ deliberately, 0 for the mimetype and 1 upward for the rest as they are
+ added.
+ .
+ Compression is already done for every member (ArchiveMember defaults to
+ it), which is the other half of what OCF asks of the mimetype.
+ +/
+ uint _zip_seq = 1;
+ void EPUBzip()(string contents, string fn, bool _is_mimetype = false) {
auto zip_arc_member_file = new ArchiveMember();
zip_arc_member_file.name = fn;
+ zip_arc_member_file.index = _is_mimetype ? 0 : _zip_seq++;
+ if (_is_mimetype) {
+ zip_arc_member_file.compressionMethod = CompressionMethod.none;
+ }
auto zip_data = new OutBuffer();
(doc_matters.opt.action.debug_do_epub)
? zip_data.write(contents.dup)
@@ -690,7 +705,7 @@ template outputEPub3() {
}
}
fn = pth_epub3.fn_mimetypes;
- EPUBzip(epub_write.mimetypes, fn);
+ EPUBzip(epub_write.mimetypes, fn, true); /+ first in the archive +/
}
{ /+ META-INF/container.xml (identify doc root) +/
{ /+ debug +/