Skip to content

Commit

Permalink
Merge pull request #4 from pedia/model-structure
Browse files Browse the repository at this point in the history
Model structure change
  • Loading branch information
pedia authored Nov 11, 2024
2 parents 8ed5c7b + 5d89ecb commit 38b04e4
Show file tree
Hide file tree
Showing 18 changed files with 839 additions and 891 deletions.
1 change: 1 addition & 0 deletions epub3/.pubignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ test/res
example
epubcheck-5.1.0
*.epub
test
t
3 changes: 3 additions & 0 deletions epub3/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# 0.3.0
refine Book

# 0.2.2
Fix utf8 decode in Book.readString

Expand Down
15 changes: 12 additions & 3 deletions epub3/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import 'package:epub3/epub3_io.dart' as epub;
final book = epub.readFile('test/res/alice.epub')!;
print(book.version); // Version.epub3
print(book.title); // Alice's Adventures...
print(book.title); // Alice's Adventures.
print(book.author); // Lewis Carroll
print(book.chapters); // first level chapters
```
Expand Down Expand Up @@ -42,10 +42,19 @@ final book = epub.Book.create(
book.add(
epub.Chapter(title: 'Part 1', children: [
epub.Chapter.content('Chapter 1', 'Content of Chapter 1'),
epub.Chapter.content('Chapter 2', 'Content of Chapter 2'),
epub.Chapter.content('Chapter 1', '<p>Content of Chapter 1</p>'),
epub.Chapter.content('Chapter 2', '<p>Content of Chapter 2</p>'),
]),
);
epub.writeFile(book, 'new.epub');
```

## TODO:
refine Book members to:
- metadata
- spines
- manifest
- navigation document

not impl: Layout redering control, Media overlay documents, mathml3, smil3
6 changes: 3 additions & 3 deletions epub3/example/build.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ void main(List<String> args) {

book.add(
epub.Chapter(title: 'Part 1', children: [
epub.Chapter.content('Chapter 1', 'Chapter 1 content'),
epub.Chapter.content('Chapter 2', 'Chapter 2 content'),
epub.Chapter.textContent('Chapter 1', 'Chapter 1 content'),
epub.Chapter.textContent('Chapter 2', 'Chapter 2 content'),
]),
);

for (var c in book.navigation.chapters) {
for (var c in book.chapters) {
dumpChapter(c);
}

Expand Down
19 changes: 12 additions & 7 deletions epub3/example/demo.dart
Original file line number Diff line number Diff line change
@@ -1,27 +1,32 @@
import 'package:epub3/epub3_io.dart' as epub;
// import 'package:image/image.dart';

void dumpChapter(epub.Chapter c, {int depth = 1}) {
void dumpChapter(epub.Book b, epub.Chapter c, {int depth = 1}) {
final char = '#'.codeUnits[0];
final prefix = String.fromCharCodes(List.generate(depth, (index) => char));

print('$prefix ${c.title}');
// final af = b.reader?.readFile(c.href!);
// final cc = af != null ? af.size : 0;

var cc = 0;

print('🚩$prefix ${c.title} ${c.href} $cc');
for (var cc in c.children) {
dumpChapter(cc, depth: depth + 1);
dumpChapter(b, cc, depth: depth + 1);
}
}

void main(List<String> args) {
final book =
epub.readFile(args.isEmpty ? 'test/res/std/epub30-spec.epub' : args[0]);
for (var c in book!.navigation.chapters) {
dumpChapter(c);
for (var c in book!.chapters) {
dumpChapter(book, c);
}

epub.writeFile(book, 'alice.epub');

final b2 = epub.readFile('alice.epub');
for (var c in b2!.navigation.chapters) {
dumpChapter(c);
for (var c in b2!.chapters) {
dumpChapter(b2, c);
}
}
101 changes: 101 additions & 0 deletions epub3/example/md.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import 'dart:io';
import 'dart:convert';
import 'package:path/path.dart' as p;

import 'package:epub3/epub3_io.dart' as epub;

/// Parse "### title" => 3, "title"
class LeveledTitle {
final int level;
epub.Chapter chapter;
LeveledTitle(this.level, this.chapter);

factory LeveledTitle.from(String line) {
int level = 0;

int i = 0;
while (true) {
i = line.indexOf('#', i);
if (-1 == i) {
break;
}
i++;
level++;
}

final title = line.trim().replaceAll('#', "").trim();
return LeveledTitle(level, epub.Chapter(title: title, children: []));
}

String get html {
final tag = {
1: 'h5',
2: 'h4',
3: 'h3',
}[level];
return '<$tag>${HtmlEscape().convert(chapter.title)}</$tag>';
}
}

List<epub.Chapter> split(File file) {
final stack = <LeveledTitle>[];
final body = <String>[]; // current Chapter's body in text(not html)

final lines = file.readAsLinesSync();
for (String line in lines) {
if (line.startsWith('#')) {
// End previous chapter: set content
if (body.isNotEmpty) {
stack.last.chapter =
epub.Chapter.textContent(stack.last.chapter.title, body.join('\n'));

body.clear();
}

// new Title
final current = LeveledTitle.from(line);
stack.add(current);
} else {
body.add(line.trim());
}
}

if (body.isNotEmpty) {
stack.last.chapter =
epub.Chapter.textContent(stack.last.chapter.title, body.join('\n'));

body.clear();
}

// Build tree liked chapters
final res = <epub.Chapter>[];
final toplevel = stack.first.level;
for (final lt in stack) {
if (lt.level == toplevel) {
// new top Chapter
res.add(lt.chapter);
} else {
// Find and push
int i = stack.last.level;
var c = res;
while (i != lt.level) {
c = c.last.children;
i -= 1;
}
c.add(lt.chapter);
}
}

return res;
}

// Convert markdown to epub
void main(List<String> args) {
final fp = args[0];
final chs = split(File(fp));
final book = epub.Book.create(title: p.basenameWithoutExtension(fp), author: '');
for (final ch in chs) {
book.add(ch);
}
epub.writeFile(book, p.basenameWithoutExtension(fp) + '.epub');
}
2 changes: 1 addition & 1 deletion epub3/example/web_ex/web/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ void main() async {
var epubRes = await http.get(Uri.parse('/alicesAdventuresUnderGround.epub'));
if (epubRes.statusCode == 200) {
final a = ZipDecoder().decodeBytes(epubRes.bodyBytes);
final book = epub.Reader.open(a).read()!;
final book = epub.Reader(a).parse()!;
querySelector('#title')?.text = book.title;
querySelector('#author')?.text = book.author;
// var chapters = await book.getChapters();
Expand Down
3 changes: 1 addition & 2 deletions epub3/lib/epub3.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
library epub3;

export 'src/model.dart';
export 'model.dart';
export 'src/reader.dart';
export 'src/writer.dart';
20 changes: 5 additions & 15 deletions epub3/lib/epub3_io.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
library epub3;
library epub3_io;

import 'dart:io';

import 'package:archive/archive_io.dart';
import 'package:path/path.dart' as p;

import "src/model.dart";
export "src/model.dart";
import "model.dart";
export "model.dart";
import 'src/reader.dart';
export 'src/reader.dart';
import 'src/writer.dart';
Expand All @@ -18,7 +17,8 @@ export 'src/writer.dart';
/// final book = epub.openFile('path-to-file.epub');
/// ```
Book? readFile(String filepath) =>
Reader.open(ZipDecoder().decodeBuffer(InputFileStream(filepath))).read();
Reader(ZipDecoder().decodeBuffer(InputFileStream(filepath)))
.parse(extractContent: true);

/// Global function for open file as epub and read content to [Book].
/// ```dart
Expand All @@ -30,13 +30,3 @@ void writeFile(Book book, String fn) {
..createSync()
..writeAsBytesSync(Writer(book).encode()!);
}

class LocalFileReader extends ContentReader {
final String root;
LocalFileReader({this.root = '.'});

@override
ArchiveFile readFile(String path) {
return ArchiveFile(path, 0, File(p.join(root, path)).readAsBytesSync());
}
}
Loading

0 comments on commit 38b04e4

Please sign in to comment.