klipbook 2.1.3 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +9 -0
- data/.ruby-version +1 -1
- data/.travis.yml +1 -1
- data/CHANGELOG.txt +11 -0
- data/Gemfile +2 -15
- data/Gemfile.lock +73 -113
- data/LICENSE.txt +18 -17
- data/README.md +63 -69
- data/Rakefile +3 -30
- data/bin/klipbook +3 -221
- data/klipbook.gemspec +32 -118
- data/lib/klipbook/cli.rb +69 -0
- data/lib/klipbook/commands/command.rb +39 -0
- data/lib/klipbook/commands/export.rb +50 -0
- data/lib/klipbook/commands/exporters/exporter.rb +49 -0
- data/lib/klipbook/{tohtml → commands/exporters}/html_book_summary.erb +1 -1
- data/lib/klipbook/commands/exporters/html_exporter.rb +25 -0
- data/lib/klipbook/commands/exporters/json_exporter.rb +17 -0
- data/lib/klipbook/commands/exporters/markdown_book_summary.erb +12 -0
- data/lib/klipbook/commands/exporters/markdown_exporter.rb +19 -0
- data/lib/klipbook/commands/list.rb +17 -0
- data/lib/klipbook/config.rb +18 -10
- data/lib/klipbook/logger.rb +15 -0
- data/lib/klipbook/sources/amazon_site/book_scraper.rb +0 -2
- data/lib/klipbook/sources/book.rb +36 -21
- data/lib/klipbook/sources/clipping.rb +10 -8
- data/lib/klipbook/sources/kindle_device/entry.rb +8 -6
- data/lib/klipbook/sources/kindle_device/entry_parser.rb +66 -64
- data/lib/klipbook/sources/kindle_device/file.rb +45 -43
- data/lib/klipbook/sources/kindle_device/file_parser.rb +23 -21
- data/lib/klipbook/sources/source.rb +30 -0
- data/lib/klipbook/version.rb +1 -1
- data/lib/klipbook.rb +11 -11
- metadata +56 -113
- data/.document +0 -5
- data/.yardopts +0 -1
- data/Guardfile +0 -19
- data/features/fixtures/clippings-for-three-books.txt +0 -105
- data/features/list.feature +0 -31
- data/features/step_definitions/list_steps.rb +0 -15
- data/features/step_definitions/tohtml_steps.rb +0 -61
- data/features/step_definitions/tojson_steps.rb +0 -17
- data/features/support/env.rb +0 -16
- data/features/tohtml.feature +0 -51
- data/features/tojson.feature +0 -11
- data/lib/klipbook/colours.rb +0 -16
- data/lib/klipbook/commands/list_books.rb +0 -19
- data/lib/klipbook/commands/tohtml.rb +0 -17
- data/lib/klipbook/commands/tojson.rb +0 -18
- data/lib/klipbook/sources/invalid_source_error.rb +0 -12
- data/lib/klipbook/tohtml/html_printer.rb +0 -39
- data/lib/klipbook/tojson/book_file.rb +0 -58
- data/spec/lib/klipbook/commands/list_books_spec.rb +0 -43
- data/spec/lib/klipbook/commands/tohtml_spec.rb +0 -36
- data/spec/lib/klipbook/sources/book_spec.rb +0 -33
- data/spec/lib/klipbook/sources/kindle_device/entry_parser_spec.rb +0 -339
- data/spec/lib/klipbook/sources/kindle_device/file_parser_spec.rb +0 -68
- data/spec/lib/klipbook/sources/kindle_device/file_spec.rb +0 -163
- data/spec/lib/klipbook/tohtml/html_printer_spec.rb +0 -88
- data/spec/lib/klipbook/tojson/book_file_spec.rb +0 -76
- data/spec/spec_helper.rb +0 -7
@@ -1,19 +0,0 @@
|
|
1
|
-
module Klipbook::Commands
|
2
|
-
class ListBooks
|
3
|
-
def initialize(books)
|
4
|
-
@books = books
|
5
|
-
end
|
6
|
-
|
7
|
-
def call(output_stream=$stdout)
|
8
|
-
if @books.empty?
|
9
|
-
output_stream.puts 'No books available'
|
10
|
-
else
|
11
|
-
output_stream.puts 'Book list:'
|
12
|
-
@books.each_with_index do |book, index|
|
13
|
-
output_stream.puts "[#{index + 1}] #{book.title_and_author}"
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module Klipbook::Commands
|
2
|
-
class ToHtml
|
3
|
-
def initialize(books, pretty_printer=Klipbook::ToHtml::HtmlPrinter.new)
|
4
|
-
@books = books
|
5
|
-
@pretty_printer = pretty_printer
|
6
|
-
end
|
7
|
-
|
8
|
-
def call(output_dir, force, message_stream=$stdout)
|
9
|
-
message_stream.puts "Using output directory: #{output_dir}"
|
10
|
-
|
11
|
-
@books.each do |book|
|
12
|
-
@pretty_printer.print_to_file(book, output_dir, force)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
@@ -1,18 +0,0 @@
|
|
1
|
-
module Klipbook::Commands
|
2
|
-
class ToJson
|
3
|
-
def initialize(books, book_file)
|
4
|
-
@books = books
|
5
|
-
@book_file = book_file
|
6
|
-
end
|
7
|
-
|
8
|
-
def call(output_file_path, force, message_stream=$stdout)
|
9
|
-
message_stream.puts "\nWriting book json to file: #{output_file_path}"
|
10
|
-
|
11
|
-
@book_file.add_books(@books, force)
|
12
|
-
|
13
|
-
File.open(output_file_path, 'w') do |output_file|
|
14
|
-
output_file.puts @book_file.to_json
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,12 +0,0 @@
|
|
1
|
-
class InvalidSourceError < RuntimeError
|
2
|
-
|
3
|
-
DEFAULT_MESSAGE = "Please provide a valid source.\n" +
|
4
|
-
"e.g.\n" +
|
5
|
-
" file:path/to/my-clippings-file.txt\n" +
|
6
|
-
" site:my-kindle-user@blah.com:my-kindle-password"
|
7
|
-
|
8
|
-
def initialize(msg = DEFAULT_MESSAGE)
|
9
|
-
super
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
@@ -1,39 +0,0 @@
|
|
1
|
-
require 'erb'
|
2
|
-
|
3
|
-
module Klipbook::ToHtml
|
4
|
-
class HtmlPrinter
|
5
|
-
def initialize(message_stream=$stdout)
|
6
|
-
@message_stream = message_stream
|
7
|
-
end
|
8
|
-
|
9
|
-
def print_to_file(book, output_dir, force)
|
10
|
-
filename = filename_for_book(book)
|
11
|
-
filepath = File.join(output_dir, filename)
|
12
|
-
|
13
|
-
if !force && File.exists?(filepath)
|
14
|
-
@message_stream.puts(Colours.yellow("Skipping ") + filename)
|
15
|
-
return
|
16
|
-
end
|
17
|
-
|
18
|
-
@message_stream.puts(Colours.green("Writing ") + filename)
|
19
|
-
File.open(filepath, 'w') do |f|
|
20
|
-
f.write generate_html(book)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
def filename_for_book(book)
|
27
|
-
"#{book.title_and_author}.html"
|
28
|
-
end
|
29
|
-
|
30
|
-
def generate_html(book)
|
31
|
-
ERB.new(template, 0, '%<>').result(book.get_binding)
|
32
|
-
end
|
33
|
-
|
34
|
-
def template
|
35
|
-
@template ||= File.read(File.join(File.dirname(__FILE__), 'html_book_summary.erb'))
|
36
|
-
end
|
37
|
-
|
38
|
-
end
|
39
|
-
end
|
@@ -1,58 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
|
3
|
-
module Klipbook::ToJson
|
4
|
-
class BookFile
|
5
|
-
attr_reader :books
|
6
|
-
|
7
|
-
def self.from_json(raw_json)
|
8
|
-
if raw_json.blank?
|
9
|
-
books = []
|
10
|
-
else
|
11
|
-
objs = JSON.parse(raw_json)
|
12
|
-
books = objs.map { |o| Klipbook::Book.from_hash(o) }
|
13
|
-
end
|
14
|
-
self.new(books)
|
15
|
-
end
|
16
|
-
|
17
|
-
def initialize(books)
|
18
|
-
@books = books || []
|
19
|
-
end
|
20
|
-
|
21
|
-
def add_books(new_books, force, message_stream=$stdout)
|
22
|
-
new_books.each do |new_book|
|
23
|
-
if book_exists?(new_book)
|
24
|
-
if force
|
25
|
-
replace_book(new_book, message_stream)
|
26
|
-
else
|
27
|
-
message_stream.puts Colours.yellow("Skipping: ") + "#{new_book.title_and_author}"
|
28
|
-
end
|
29
|
-
else
|
30
|
-
message_stream.puts Colours.green("Adding: ") + "#{new_book.title_and_author}"
|
31
|
-
@books.push(new_book)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def to_json
|
37
|
-
JSON.pretty_generate(@books)
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
|
42
|
-
def book_exists?(new_book)
|
43
|
-
find_book(new_book)
|
44
|
-
end
|
45
|
-
|
46
|
-
def find_book(new_book)
|
47
|
-
@books.find { |existing_book| existing_book.title_and_author == new_book.title_and_author }
|
48
|
-
end
|
49
|
-
|
50
|
-
def replace_book(new_book, message_stream)
|
51
|
-
message_stream.puts Colours.green("Updating: ") + "#{new_book.title_and_author}"
|
52
|
-
|
53
|
-
old_book = find_book(new_book)
|
54
|
-
@books.delete(old_book)
|
55
|
-
@books.push(new_book)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
@@ -1,43 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
RSpec.describe Klipbook::Commands::ListBooks do
|
4
|
-
|
5
|
-
let (:output) do
|
6
|
-
double("output", puts: nil)
|
7
|
-
end
|
8
|
-
|
9
|
-
describe '#call' do
|
10
|
-
|
11
|
-
subject { Klipbook::Commands::ListBooks.new(books).call(output) }
|
12
|
-
|
13
|
-
context 'when created with no books' do
|
14
|
-
|
15
|
-
let (:books) { [] }
|
16
|
-
|
17
|
-
it 'displays a message saying that the clipping file contains no books' do
|
18
|
-
subject
|
19
|
-
expect(output).to have_received(:puts).with('No books available')
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
context 'when created with multiple books' do
|
24
|
-
let (:books) do
|
25
|
-
[
|
26
|
-
Klipbook::Book.new.tap { |b| b.title = 'My first fake title' },
|
27
|
-
Klipbook::Book.new.tap { |b| b.title = 'Another fake book'; b.author = 'Rock Riphard' }
|
28
|
-
]
|
29
|
-
end
|
30
|
-
|
31
|
-
it 'displays a message describing the book list' do
|
32
|
-
subject
|
33
|
-
expect(output).to have_received(:puts).with('Book list:')
|
34
|
-
end
|
35
|
-
|
36
|
-
it 'displays an indexed list of book titles including the author when available' do
|
37
|
-
subject
|
38
|
-
expect(output).to have_received(:puts).with('[1] My first fake title')
|
39
|
-
expect(output).to have_received(:puts).with('[2] Another fake book by Rock Riphard')
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
@@ -1,36 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
RSpec.describe Klipbook::Commands::ToHtml do
|
4
|
-
|
5
|
-
let (:it) { Klipbook::Commands::ToHtml.new(books, pretty_printer) }
|
6
|
-
|
7
|
-
let (:pretty_printer) do
|
8
|
-
double(print_to_file: nil)
|
9
|
-
end
|
10
|
-
|
11
|
-
let (:message_stream) do
|
12
|
-
double(puts: nil)
|
13
|
-
end
|
14
|
-
|
15
|
-
let (:book_one) { Klipbook::Book.new('book one') }
|
16
|
-
let (:book_two) { Klipbook::Book.new('book two') }
|
17
|
-
let (:books) { [ book_one, book_two ] }
|
18
|
-
|
19
|
-
let(:output_dir) { 'fake output dir' }
|
20
|
-
|
21
|
-
describe '#call' do
|
22
|
-
|
23
|
-
subject { it.call(output_dir, true, message_stream) }
|
24
|
-
|
25
|
-
it 'prints a message displaying the output directory' do
|
26
|
-
subject
|
27
|
-
expect(message_stream).to have_received(:puts).with('Using output directory: fake output dir')
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'passes each book to the pretty printer' do
|
31
|
-
subject
|
32
|
-
expect(pretty_printer).to have_received(:print_to_file).with(book_one, output_dir, true)
|
33
|
-
expect(pretty_printer).to have_received(:print_to_file).with(book_two, output_dir, true)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
RSpec.describe Klipbook::Book do
|
4
|
-
describe '#title_and_author' do
|
5
|
-
|
6
|
-
subject { book.title_and_author }
|
7
|
-
|
8
|
-
context 'with no author' do
|
9
|
-
let(:book) do
|
10
|
-
Klipbook::Book.new.tap do |b|
|
11
|
-
b.title = 'Book title'
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
it 'only contains the title' do
|
16
|
-
expect(subject).to eq 'Book title'
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
context 'with an author' do
|
21
|
-
let(:book) do
|
22
|
-
Klipbook::Book.new.tap do |b|
|
23
|
-
b.title = 'Book title'
|
24
|
-
b.author = 'Rob Ripjaw'
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'contains the title and author' do
|
29
|
-
expect(subject).to eq 'Book title by Rob Ripjaw'
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
@@ -1,339 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
RSpec.describe Klipbook::Sources::KindleDevice::EntryParser do
|
4
|
-
|
5
|
-
describe '#build_entry' do
|
6
|
-
subject { Klipbook::Sources::KindleDevice::EntryParser.new.build_entry(entry_text) }
|
7
|
-
|
8
|
-
context 'passed an empty entry' do
|
9
|
-
let(:entry_text) { " " }
|
10
|
-
|
11
|
-
it 'returns nil' do
|
12
|
-
expect(subject).to be_nil
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
context 'passed an incomplete entry' do
|
17
|
-
let(:entry_text) do
|
18
|
-
"Not long enough"
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'returns nil' do
|
22
|
-
expect(subject).to be_nil
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
context 'passed an entry with the title line "Book title (Author\'s Name)"' do
|
27
|
-
let (:entry_text) do
|
28
|
-
"Book title (Author's Name)\n" +
|
29
|
-
"- Highlight Loc. 466-69 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
|
30
|
-
"\n" +
|
31
|
-
"Highlight text\n"
|
32
|
-
end
|
33
|
-
|
34
|
-
it 'extracts the title' do
|
35
|
-
expect(subject.title).to eq 'Book title'
|
36
|
-
end
|
37
|
-
|
38
|
-
it 'extracts the author' do
|
39
|
-
expect(subject.author).to eq "Author's Name"
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
context 'passed an entry with the title line "Book title (sub title) (Author\'s Name)"' do
|
44
|
-
let (:entry_text) do
|
45
|
-
"Book title (sub title) (Author's Name)\n" +
|
46
|
-
"- Highlight Loc. 466-69 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
|
47
|
-
"\n" +
|
48
|
-
"Highlight text\n"
|
49
|
-
end
|
50
|
-
|
51
|
-
it 'extracts the title containing parens' do
|
52
|
-
expect(subject.title).to eq 'Book title (sub title)'
|
53
|
-
end
|
54
|
-
|
55
|
-
it 'extracts the author' do
|
56
|
-
expect(subject.author).to eq "Author's Name"
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
context 'passed an entry with the title line "Book title"' do
|
61
|
-
let (:entry_text) do
|
62
|
-
"Book title\n" +
|
63
|
-
"- Highlight Loc. 466-69 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
|
64
|
-
"\n" +
|
65
|
-
"Highlight text\n"
|
66
|
-
end
|
67
|
-
|
68
|
-
it 'extracts the title' do
|
69
|
-
expect(subject.title).to eq 'Book title'
|
70
|
-
end
|
71
|
-
|
72
|
-
it 'sets author to nil' do
|
73
|
-
expect(subject.author).to be_nil
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
context 'passed an entry that is a highlight' do
|
78
|
-
let (:entry_text) do
|
79
|
-
"Book title\n" +
|
80
|
-
"- Highlight Loc. 466-69 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
|
81
|
-
"\n" +
|
82
|
-
"The first line of the highlight\n" +
|
83
|
-
"The second line of the highlight"
|
84
|
-
end
|
85
|
-
|
86
|
-
it 'returns a highlight' do
|
87
|
-
expect(subject.type).to eq :highlight
|
88
|
-
end
|
89
|
-
|
90
|
-
it 'extracts the highlighted text' do
|
91
|
-
expect(subject.text).to eq "The first line of the highlight\nThe second line of the highlight"
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
context 'passed an entry that is a 4th-generation highlight' do
|
96
|
-
let (:entry_text) do
|
97
|
-
"Book title\n" +
|
98
|
-
"- Your Highlight Location 466-69 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
|
99
|
-
"\n" +
|
100
|
-
"The first line of the highlight\n" +
|
101
|
-
"The second line of the highlight"
|
102
|
-
end
|
103
|
-
|
104
|
-
it 'returns a highlight' do
|
105
|
-
expect(subject.type).to eq :highlight
|
106
|
-
end
|
107
|
-
|
108
|
-
it 'extracts the highlighted text' do
|
109
|
-
expect(subject.text).to eq "The first line of the highlight\nThe second line of the highlight"
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
context 'passed an entry that is a note' do
|
114
|
-
let (:entry_text) do
|
115
|
-
"Book title\n" +
|
116
|
-
"- Note Loc. 623 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
|
117
|
-
"\n" +
|
118
|
-
"The note text"
|
119
|
-
end
|
120
|
-
|
121
|
-
it 'returns a note' do
|
122
|
-
expect(subject.type).to eq :note
|
123
|
-
end
|
124
|
-
|
125
|
-
it 'extracts the note text' do
|
126
|
-
expect(subject.text).to eq "The note text"
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
context 'passed an entry that is a 4th-generation note' do
|
131
|
-
let (:entry_text) do
|
132
|
-
"Book title\n" +
|
133
|
-
"- Your Note Location 623 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
|
134
|
-
"\n" +
|
135
|
-
"The note text"
|
136
|
-
end
|
137
|
-
|
138
|
-
it 'returns a note' do
|
139
|
-
expect(subject.type).to eq :note
|
140
|
-
end
|
141
|
-
|
142
|
-
it 'extracts the note text' do
|
143
|
-
expect(subject.text).to eq "The note text"
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
context 'passed an entry with a bookmark' do
|
148
|
-
let (:entry_text) do
|
149
|
-
"Book title\n" +
|
150
|
-
"- Bookmark on Page 1 | Loc. 406 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
|
151
|
-
"\n" +
|
152
|
-
"\n"
|
153
|
-
end
|
154
|
-
|
155
|
-
it 'returns a bookmark' do
|
156
|
-
expect(subject.type).to eq :bookmark
|
157
|
-
end
|
158
|
-
|
159
|
-
it 'extracts empty text' do
|
160
|
-
expect(subject.text).to eq ""
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
context 'passed an entry with a 4th-generation bookmark' do
|
165
|
-
let (:entry_text) do
|
166
|
-
"Book title\n" +
|
167
|
-
"- Your Bookmark on Page 1 | Location 406 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
|
168
|
-
"\n" +
|
169
|
-
"\n"
|
170
|
-
end
|
171
|
-
|
172
|
-
it 'returns a bookmark' do
|
173
|
-
expect(subject.type).to eq :bookmark
|
174
|
-
end
|
175
|
-
|
176
|
-
it 'extracts empty text' do
|
177
|
-
expect(subject.text).to eq ""
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
context 'passed an entry with a single location value' do
|
182
|
-
let (:entry_text) do
|
183
|
-
"Book title\n" +
|
184
|
-
"- Highlight Loc. 465 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
|
185
|
-
"\n" +
|
186
|
-
"The first line of the highlight\n" +
|
187
|
-
"The second line of the highlight"
|
188
|
-
end
|
189
|
-
|
190
|
-
it 'returns the correct location' do
|
191
|
-
expect(subject.location).to eq 465
|
192
|
-
end
|
193
|
-
|
194
|
-
it 'returns the correct added date' do
|
195
|
-
expect(subject.added_on).to eq DateTime.parse('Thursday, April 21, 2011, 07:31 AM')
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
|
-
context 'passed a 4th-generation entry with a single location value' do
|
200
|
-
let (:entry_text) do
|
201
|
-
"Book title\n" +
|
202
|
-
"- Your Highlight Location 465 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
|
203
|
-
"\n" +
|
204
|
-
"The first line of the highlight\n" +
|
205
|
-
"The second line of the highlight"
|
206
|
-
end
|
207
|
-
|
208
|
-
it 'returns the correct location' do
|
209
|
-
expect(subject.location).to eq 465
|
210
|
-
end
|
211
|
-
|
212
|
-
it 'returns the correct added date' do
|
213
|
-
expect(subject.added_on).to eq DateTime.parse('Thursday, April 21, 2011, 07:31 AM')
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
context 'passed an entry with a location range' do
|
218
|
-
let (:entry_text) do
|
219
|
-
"Book title\n" +
|
220
|
-
"- Highlight Loc. 466-69 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
|
221
|
-
"\n" +
|
222
|
-
"The first line of the highlight\n" +
|
223
|
-
"The second line of the highlight"
|
224
|
-
end
|
225
|
-
|
226
|
-
it 'extracts the first element of the location range' do
|
227
|
-
expect(subject.location).to eq 466
|
228
|
-
end
|
229
|
-
|
230
|
-
it 'returns the correct added date' do
|
231
|
-
expect(subject.added_on).to eq DateTime.parse('Thursday, April 21, 2011, 07:31 AM')
|
232
|
-
end
|
233
|
-
end
|
234
|
-
|
235
|
-
context 'passed a 4th-generation entry with a location range' do
|
236
|
-
let (:entry_text) do
|
237
|
-
"Book title\n" +
|
238
|
-
"- Your Highlight Location 466-69 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
|
239
|
-
"\n" +
|
240
|
-
"The first line of the highlight\n" +
|
241
|
-
"The second line of the highlight"
|
242
|
-
end
|
243
|
-
|
244
|
-
it 'extracts the first element of the location range' do
|
245
|
-
expect(subject.location).to eq 466
|
246
|
-
end
|
247
|
-
|
248
|
-
it 'returns the correct added date' do
|
249
|
-
expect(subject.added_on).to eq DateTime.parse('Thursday, April 21, 2011, 07:31 AM')
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
context 'passed an entry with a page number and location range' do
|
254
|
-
let (:entry_text) do
|
255
|
-
"Book title\n" +
|
256
|
-
"- Highlight on Page 171 | Loc. 1858-59 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
|
257
|
-
"\n" +
|
258
|
-
"Some highlighted text\n" +
|
259
|
-
"\n"
|
260
|
-
end
|
261
|
-
|
262
|
-
it 'extracts the first element of the location range' do
|
263
|
-
expect(subject.location).to eq 1858
|
264
|
-
end
|
265
|
-
|
266
|
-
it 'extracts the page number' do
|
267
|
-
expect(subject.page).to eq 171
|
268
|
-
end
|
269
|
-
|
270
|
-
it 'returns the correct added date' do
|
271
|
-
expect(subject.added_on).to eq DateTime.parse('Thursday, April 21, 2011, 07:31 AM')
|
272
|
-
end
|
273
|
-
end
|
274
|
-
|
275
|
-
context 'passed a 4th-generation entry with a page number and location range' do
|
276
|
-
let (:entry_text) do
|
277
|
-
"Book title\n" +
|
278
|
-
"- Your Highlight on Page 171 | Location 1858-59 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
|
279
|
-
"\n" +
|
280
|
-
"Some highlighted text\n" +
|
281
|
-
"\n"
|
282
|
-
end
|
283
|
-
|
284
|
-
it 'extracts the first element of the location range' do
|
285
|
-
expect(subject.location).to eq 1858
|
286
|
-
end
|
287
|
-
|
288
|
-
it 'extracts the page number' do
|
289
|
-
expect(subject.page).to eq 171
|
290
|
-
end
|
291
|
-
|
292
|
-
it 'returns the correct added date' do
|
293
|
-
expect(subject.added_on).to eq DateTime.parse('Thursday, April 21, 2011, 07:31 AM')
|
294
|
-
end
|
295
|
-
end
|
296
|
-
|
297
|
-
context 'passed an entry with a page number and no location' do
|
298
|
-
let (:entry_text) do
|
299
|
-
"Book title\n" +
|
300
|
-
"- Highlight on Page 9 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
|
301
|
-
"\n" +
|
302
|
-
"Clipping"
|
303
|
-
end
|
304
|
-
|
305
|
-
it 'sets location to 0' do
|
306
|
-
expect(subject.location).to eq 0
|
307
|
-
end
|
308
|
-
|
309
|
-
it 'extracts the page number' do
|
310
|
-
expect(subject.page).to eq 9
|
311
|
-
end
|
312
|
-
|
313
|
-
it 'returns the correct added date' do
|
314
|
-
expect(subject.added_on).to eq DateTime.parse('Thursday, April 21, 2011, 07:31 AM')
|
315
|
-
end
|
316
|
-
end
|
317
|
-
|
318
|
-
context 'passed a 4th-generation entry with a page number and no location' do
|
319
|
-
let (:entry_text) do
|
320
|
-
"Book title\n" +
|
321
|
-
"- Your Highlight on Page 9 | Added on Thursday, April 21, 2011, 07:31 AM\n" +
|
322
|
-
"\n" +
|
323
|
-
"Clipping"
|
324
|
-
end
|
325
|
-
|
326
|
-
it 'sets location to 0' do
|
327
|
-
expect(subject.location).to eq 0
|
328
|
-
end
|
329
|
-
|
330
|
-
it 'extracts the page number' do
|
331
|
-
expect(subject.page).to eq 9
|
332
|
-
end
|
333
|
-
|
334
|
-
it 'returns the correct added date' do
|
335
|
-
expect(subject.added_on).to eq DateTime.parse('Thursday, April 21, 2011, 07:31 AM')
|
336
|
-
end
|
337
|
-
end
|
338
|
-
end
|
339
|
-
end
|
@@ -1,68 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
RSpec.describe Klipbook::Sources::KindleDevice::FileParser do
|
6
|
-
|
7
|
-
let(:parser) { Klipbook::Sources::KindleDevice::FileParser.new(entry_parser) }
|
8
|
-
|
9
|
-
let(:entry_parser) do
|
10
|
-
double('parser', build_entry: nil)
|
11
|
-
end
|
12
|
-
|
13
|
-
describe '#extract_entries' do
|
14
|
-
subject { parser.extract_entries(raw_text) }
|
15
|
-
|
16
|
-
context 'called with empty text' do
|
17
|
-
|
18
|
-
let(:raw_text) { '' }
|
19
|
-
|
20
|
-
it 'return an empty set of entries' do
|
21
|
-
expect(subject).to be_empty
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
context 'called with text containing two entries' do
|
26
|
-
let(:raw_text) do
|
27
|
-
" entry one" +
|
28
|
-
"==========" +
|
29
|
-
" entry two" +
|
30
|
-
"=========="
|
31
|
-
end
|
32
|
-
|
33
|
-
it 'builds two entries with the entries parser and returns them' do
|
34
|
-
entry_one = Object.new
|
35
|
-
entry_two = Object.new
|
36
|
-
|
37
|
-
allow(entry_parser).to receive(:build_entry).with(' entry one') { entry_one }
|
38
|
-
allow(entry_parser).to receive(:build_entry).with(' entry two') { entry_two }
|
39
|
-
|
40
|
-
expect(subject).to eq [ entry_one, entry_two ]
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
context 'called with text containing carriage return characters' do
|
45
|
-
let(:raw_text) do
|
46
|
-
"Example \r text\r" +
|
47
|
-
"=========="
|
48
|
-
end
|
49
|
-
|
50
|
-
it 'strips carriage returns before calling the entry parser' do
|
51
|
-
subject
|
52
|
-
expect(entry_parser).to have_received(:build_entry).with('Example text')
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
context 'called with text containing control characters' do
|
57
|
-
let(:raw_text) do
|
58
|
-
"Example \xef\xbb\xbf text\xef\xbb\xbf" +
|
59
|
-
"=========="
|
60
|
-
end
|
61
|
-
|
62
|
-
it 'strips control characters before calling the entry parser' do
|
63
|
-
subject
|
64
|
-
expect(entry_parser).to have_received(:build_entry).with('Example text')
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|