From fcaeedd4d1c128ff84371c0a7db5d0af6751492a Mon Sep 17 00:00:00 2001 From: Chris Jaekl Date: Sat, 24 Jun 2017 20:11:45 +0900 Subject: [PATCH] Add support for PDF (with .jpeg cover). --- book.rb | 40 ++++++++++++--- navigator.rb | 142 +++++++++++++++++++++++++++++++++++++++++++++++++++ series.rb | 87 +++++++++++++++++++++++++++++++ walkdir.rb | 20 +++++++- 4 files changed, 280 insertions(+), 9 deletions(-) create mode 100644 navigator.rb create mode 100644 series.rb diff --git a/book.rb b/book.rb index aa61930..e0ccc84 100644 --- a/book.rb +++ b/book.rb @@ -20,12 +20,12 @@ class Book @volume = nil end - def loadFromFile(fileName) + def load_from_file(fileName) @path = fileName - parseFileName!(fileName) + parse_file_name!(fileName) end - def self.canHandle?(fileName) + def self.can_handle?(fileName) if nil == fileName return false end @@ -37,6 +37,10 @@ class Book return true end + if lowerName.end_with?(".pdf") + return true + end + return false end @@ -204,8 +208,8 @@ class Book end protected - def parseFileName!(fileName) - parts = fileName.split('/') + def parse_file_name!(file_name) + parts = file_name.split('/') (series_code, @volume, @title) = processTitle(parts[-1]) if parts.length > 1 grouping = parts[-2] @@ -215,8 +219,11 @@ class Book @series_id = @store.get_series(grouping, series_code) end - if fileName.downcase.end_with?(".epub") - scanEpub!(fileName) + lc_file_name = file_name.downcase + if lc_file_name.end_with?(".epub") + scanEpub!(file_name) + elsif lc_file_name.end_with?(".pdf") + scan_pdf!(file_name) end end @@ -243,6 +250,25 @@ class Book end end + protected + def scan_pdf!(file_name) + #puts 'Scanning "' + file_name.to_s + '"...' + + pdf_path = File.expand_path(file_name).to_s + if ! pdf_path.end_with?('.pdf') + puts 'Unexpected internal error: path "' + file_name.to_s + '" does not end with ".pdf".' + return + end + + jpeg_path = pdf_path[0..-5] + '.jpeg' + if File.file?(jpeg_path) + File.open(jpeg_path, 'r') do |is| + @cover = Cover.new(is, jpeg_path, 'image/jpeg') + end + end + end + + protected def scanOpf!(zipfile, opfPath) coverId = nil diff --git a/navigator.rb b/navigator.rb new file mode 100644 index 0000000..16da652 --- /dev/null +++ b/navigator.rb @@ -0,0 +1,142 @@ +require 'page' +require 'store' + +class Navigator + def initialize(store) + @store = store + end + + def write_atoz_pages + atoz_counts = {} + + ('A'..'Z').each do |letter| + atoz_counts[letter] = write_authors_starting_with(letter) + end + + content = '' + ('A'..'Z').each do |letter| + content += ' ' + end + page = Page.new(@store) + page.output_dir = 'atoz' + page.special = content + page.up = ['../output/index.html', 'Up'] + + page.write_html( [] ) + end + + def write_authors_starting_with(letter) + book_ids = @store.query_books_by_author(letter + '%') + puts 'Authors starting with "' + letter + '": ' + book_ids.length.to_s() + ' books.' + + page = Page.new(@store) + if 'A' != letter + page.back = ['../atoz/output_' + (letter.ord - 1).chr + '.html', 'Prev'] + end + if 'Z' != letter + page.forward = ['../atoz/output_' + (letter.ord + 1).chr + '.html', 'Next'] + end + page.output_dir = 'atoz' + page.index_file = 'output_' + letter + '.html' + page.title = "Authors starting with '" + letter + "'" + page.up = ['../atoz/index.html', 'Up'] + + page.write_html(book_ids) + return book_ids.length + end + + def write_series_for_age(age) + series_infos = [] + + series_ids = @store.query_series_by_age(age) + + series_ids.each do |id| + series = @store.load_series(id) + book_ids = @store.query_books_by_series_id(id) + if nil != book_ids and book_ids.length > 0 + series_infos.push( [series, book_ids] ) + end + end + + for idx in 0 .. (series_infos.length - 1) do + #puts series.descr + ': ' + book_ids.length.to_s + ' books.' + + back = nil + fwd = nil + + if idx > 0 + back = series_infos[idx-1] + end + if (idx + 1) < series_infos.length + fwd = series_infos[idx+1] + end + + cur = series_infos[idx] + series = cur[0] + book_ids = cur[1] + + page = Page.new(@store) + if nil != back + page.back = [back[0].key + '.html', 'Back'] + end + if nil != fwd + page.forward = [fwd[0].key + '.html', 'Forward'] + end + page.output_dir = 'series/series_' + age + page.index_file = series.key + '.html' + page.title = 'Series “' + series.descr + '” (' + book_ids.length.to_s + ' books)' + page.up = ['index.html', 'Up'] + + page.write_html(book_ids) + end + + content = '

“' + age + '” Series

' + content += '

AuthorBooks
Starting with ' + letter + '' + atoz_counts[letter].to_s + '
' + series_infos.each do |cur| + series = cur[0] + book_ids = cur[1] + + author = series.grouping + letter = author[0] + + content += ' ' + content += '' + content += '' + content += '' + content += '' + content += '' + end + content += '
AuthorSeriesGenreBooks
' + author + '' + series.descr + '' + series.genre + '' + book_ids.length.to_s + '

' + page = Page.new(@store) + page.output_dir = 'series/series_' + age + page.special = content + page.up = ['../index.html', 'Up'] + page.write_html( [] ) + + return series_infos.length + end + + def write_series_listing + ages = ['beginner', 'junior', 'ya', 'adult'] + series_counts = {} + + ages.each do |age| + puts 'Series for "' + age + '" readers...' + + series_counts[age] = write_series_for_age(age) + end + + content = '

Browse Books By Series

' + content += '

' + content += '' + ages.each do |age| + content += '' + end + content += '
AgeNumber of Series
' + age + '' + series_counts[age].to_s + '

' + page = Page.new(@store) + page.output_dir = 'series' + page.special = content + page.up = ['../output/index.html', 'Up'] + page.write_html( [] ) + end +end diff --git a/series.rb b/series.rb new file mode 100644 index 0000000..0621876 --- /dev/null +++ b/series.rb @@ -0,0 +1,87 @@ + +class Series + def initialize(id) + @age = nil + @genre = nil + @grouping = nil + @code = nil + @descr = nil + @id = id + end + + def age + @age + end + + def age=(value) + @age = value + end + + def code + @code + end + + def code=(value) + @code = value + end + + def descr + @descr + end + + def descr=(value) + @descr = value + end + + def genre + @genre + end + + def genre=(value) + @genre = value + end + + def grouping + @grouping + end + + def grouping=(value) + @grouping = value + end + + def id + @id + end + + def inspect + data = [] + if nil != @age + data.push('age="' + @age.inspect + '"') + end + if nil != @code + data.push('code="' + @code.inspect + '"') + end + if nil != @descr + data.push('descr="' + @descr + '"') + end + if nil != @genre + data.push('genre="' + @genre + '"') + end + if nil != @grouping + data.push('grouping="' + @grouping + '"') + end + return '(Series:' + data.join(',') + ')' + end + + def key + if nil != grouping and nil != code + return grouping.to_s + '_' + code.to_s + end + return id.to_s + end + + def to_s + return inspect() + end +end + diff --git a/walkdir.rb b/walkdir.rb index 1dadd2e..236e3fe 100644 --- a/walkdir.rb +++ b/walkdir.rb @@ -31,9 +31,9 @@ class WalkDir def books result = [] for file in @files.sort - if Book.canHandle?(file) + if Book.can_handle?(file) && (!is_duplicate?(file)) book = Book.new(@store) - book.loadFromFile(file) + book.load_from_file(file) id = @store.store_book(book) result.push(id) end @@ -41,6 +41,22 @@ class WalkDir return result end + # Duplicate versions of a text are named + # xxx_suffix.ext + # Where suffix is one of bis, ter, quater, quinquies + # for the 2nd, 3rd, 4th or 5th variant respectively. + def is_duplicate?(file) + s = file.to_s + suffix = ['_bis.', '_ter.', '_quater.', '_quinquies.'] + suffix.each do |pat| + if s.include?(pat) + return true + end + end + + return false + end + def walk(path) result = [] children = Dir.entries(path) -- 2.39.2