rb-dayone 0.2.0 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -1
- data/History.rdoc +23 -0
- data/Manifest +15 -5
- data/README.md +14 -3
- data/Rakefile +34 -0
- data/bin/dayone +71 -0
- data/lib/rb-dayone.rb +6 -0
- data/lib/rb-dayone/entry.rb +27 -4
- data/lib/rb-dayone/entry_importer.rb +78 -0
- data/lib/rb-dayone/plist_reader.rb +9 -0
- data/lib/rb-dayone/search.rb +59 -0
- data/rb-dayone.gemspec +16 -1
- data/spec/data/entries/748AD5D252F44149920485B0CEA478E3.doentry +14 -0
- data/spec/data/entries/F13723CDFD454481B24312DCD627BFD7.doentry +14 -0
- data/spec/data/foo.doentry +1 -0
- data/spec/{locations → data/locations}/location-auto/location +0 -0
- data/spec/{locations → data/locations}/location-specified/location +0 -0
- data/spec/data/sample.doentry +12 -0
- data/spec/{sample.plist → data/sample.plist} +0 -0
- data/spec/data/utf.doentry +12 -0
- data/spec/dayone_spec.rb +1 -1
- data/spec/entry_importer_spec.rb +69 -0
- data/spec/entry_spec.rb +24 -11
- data/spec/plist_reader_spec.rb +1 -1
- data/spec/search_spec.rb +35 -0
- data/spec/spec_helper.rb +4 -0
- data/version.txt +1 -1
- metadata +41 -9
data/Gemfile
CHANGED
data/History.rdoc
CHANGED
@@ -1,3 +1,26 @@
|
|
1
|
+
== 0.3.3 / 2012-08-17
|
2
|
+
|
3
|
+
* [FIXED] LibXML will now accept UTF-8 characters in journal entries.
|
4
|
+
* Added the command "repair" to the dayone binary, which will at least repair *my* damage.
|
5
|
+
* Added the command "verify" to the dayone binary, which I at least find helpful.
|
6
|
+
* Added a post-install note telling people upgrading from <= 0.2.0 to repair.
|
7
|
+
|
8
|
+
== 0.3.2 / 2012-08-16
|
9
|
+
|
10
|
+
* Switched from REXML to LibXML-ruby for XML parsing. Now accepts ampersands in entries, as well as UTF-8. Rejoice!
|
11
|
+
|
12
|
+
== 0.3.1 / 2012-08-16
|
13
|
+
|
14
|
+
* [FIXED] Minor bugfixes
|
15
|
+
* [FIXED] REXML will no longer kill the whole program if it can't parse a journal file.
|
16
|
+
|
17
|
+
== 0.3.0 / 2012-08-16
|
18
|
+
|
19
|
+
* [FIXED] Fixed several bugs in Builder xml output, including:
|
20
|
+
* Output of trailing <target />
|
21
|
+
* Output of malformed DOCTYPE
|
22
|
+
* You can now import existing DayOne entries and search them
|
23
|
+
|
1
24
|
== 0.2.0 / 2012-08-14
|
2
25
|
|
3
26
|
* Now auto-detects DayOne journal location from your plist file
|
data/Manifest
CHANGED
@@ -3,16 +3,26 @@ Gemfile
|
|
3
3
|
History.rdoc
|
4
4
|
lib/rb-dayone.rb
|
5
5
|
lib/rb-dayone/entry.rb
|
6
|
+
lib/rb-dayone/entry_importer.rb
|
6
7
|
lib/rb-dayone/plist_reader.rb
|
8
|
+
lib/rb-dayone/search.rb
|
7
9
|
Manifest
|
10
|
+
Rakefile
|
8
11
|
rb-dayone.gemspec
|
9
12
|
README.md
|
13
|
+
spec/data/entries/748AD5D252F44149920485B0CEA478E3.doentry
|
14
|
+
spec/data/entries/F13723CDFD454481B24312DCD627BFD7.doentry
|
15
|
+
spec/data/foo.doentry
|
16
|
+
spec/data/locations/location-auto/location
|
17
|
+
spec/data/locations/location-specified/location
|
18
|
+
spec/data/locations/location-unspecified
|
19
|
+
spec/data/sample.doentry
|
20
|
+
spec/data/sample.plist
|
21
|
+
spec/data/utf.doentry
|
10
22
|
spec/dayone_spec.rb
|
23
|
+
spec/entry_importer_spec.rb
|
11
24
|
spec/entry_spec.rb
|
12
|
-
spec/locations/location-auto/location
|
13
|
-
spec/locations/location-specified/location
|
14
|
-
spec/locations/location-unspecified
|
15
|
-
spec/spec_helper.rb
|
16
25
|
spec/plist_reader_spec.rb
|
17
|
-
spec/
|
26
|
+
spec/search_spec.rb
|
27
|
+
spec/spec_helper.rb
|
18
28
|
version.txt
|
data/README.md
CHANGED
@@ -29,21 +29,32 @@ For more information on what you can do from the command line:
|
|
29
29
|
|
30
30
|
dayone --help
|
31
31
|
|
32
|
+
### Validating and repairing doentry files ###
|
33
|
+
|
34
|
+
As of version 0.2.0 of this gem, `rb-dayone` is finally outputting *nice* XML. Before then, it wasn't. You can check if any of your DayOne entries need repairing by running:
|
35
|
+
|
36
|
+
dayone validate
|
37
|
+
|
38
|
+
If they do, you might be able to fix them using:
|
39
|
+
|
40
|
+
dayone repair
|
41
|
+
|
42
|
+
If not, let me know, and I'll see what I can do to fix stuff.
|
43
|
+
|
32
44
|
## Install
|
33
45
|
|
34
46
|
gem install rb-dayone
|
35
47
|
|
36
48
|
## Author
|
37
49
|
|
38
|
-
Original author: Jan-Yves Ruzicka (@akchizar). Get in touch [via email](mailto:janyves.ruzicka@gmail.com).
|
50
|
+
Original author: [Jan-Yves Ruzicka](http://www.1klb.com) ([@akchizar](http://www.twitter.com/akchizar)). Get in touch [via email](mailto:janyves.ruzicka@gmail.com).
|
39
51
|
|
40
52
|
## To do
|
41
53
|
|
42
54
|
* Image support
|
43
55
|
* Location support?
|
44
56
|
|
45
|
-
License
|
46
|
-
-------
|
57
|
+
## License
|
47
58
|
|
48
59
|
Copyright (c) 2012 Jan-Yves Ruzicka
|
49
60
|
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
gem_title = 'rb-dayone'
|
2
|
+
|
3
|
+
def pkg
|
4
|
+
p = Dir['pkg/*.gem'].sort[-1]
|
5
|
+
if p.nil?
|
6
|
+
$stderr.puts "ERROR: Can't find pkg file."
|
7
|
+
else
|
8
|
+
p
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
task :build do
|
13
|
+
specfile = "#{gem_title}.gemspec"
|
14
|
+
sh "gem build '#{specfile}'"
|
15
|
+
|
16
|
+
gem_file = Dir["#{gem_title}-*.gem"]
|
17
|
+
gem_file.each do |f|
|
18
|
+
sh "mv '#{f}' pkg"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
task :install => [:build] do
|
23
|
+
sh "gem install #{pkg}"
|
24
|
+
end
|
25
|
+
|
26
|
+
task :push => [:build] do
|
27
|
+
sh "gem push #{pkg}"
|
28
|
+
end
|
29
|
+
|
30
|
+
task :spec do
|
31
|
+
sh "rspec"
|
32
|
+
end
|
33
|
+
|
34
|
+
task :default => :spec
|
data/bin/dayone
CHANGED
@@ -61,4 +61,75 @@ If you don't specify the --text tag, it will read text from STDIN and use this a
|
|
61
61
|
entry = DayOne::Entry.new entry_text, starred:starred
|
62
62
|
entry.create!
|
63
63
|
end
|
64
|
+
end
|
65
|
+
|
66
|
+
command :repair do |c|
|
67
|
+
c.syntax = "repair"
|
68
|
+
c.description = "Will repair any damage caused by previous versions of rb-dayone."
|
69
|
+
c.summary = "This command will trawl your DayOne journal archive looking for any malformed DayOne entries created by previous versions of rb-dayone, and will fix them. Currently it fixed malformed doctype declarations and trailing target tags."
|
70
|
+
|
71
|
+
c.action do |args, opts|
|
72
|
+
require 'rb-dayone'
|
73
|
+
|
74
|
+
repairs = {
|
75
|
+
'trailing target' => [
|
76
|
+
/<target\/>\Z/,
|
77
|
+
''
|
78
|
+
],
|
79
|
+
'malformed doctype' => [
|
80
|
+
%r|<!DOCTYPE "plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"">|,
|
81
|
+
%|<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">|
|
82
|
+
]
|
83
|
+
}
|
84
|
+
|
85
|
+
DayOne.entries.each do |f|
|
86
|
+
contents = File.read(f)
|
87
|
+
modified = []
|
88
|
+
repairs.each do |name, (replace_this, with_this)|
|
89
|
+
if replace_this === contents
|
90
|
+
modified << name
|
91
|
+
contents = contents.gsub(replace_this, with_this)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
unless modified.empty?
|
96
|
+
File.open(f,'w'){ |io| io.puts contents }
|
97
|
+
puts "Repaired file #{f}:"
|
98
|
+
modified.each{ |s| puts " Fixed #{s}" }
|
99
|
+
end
|
100
|
+
end
|
101
|
+
puts "All files have been repaired!"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
command :validate do |c|
|
106
|
+
c.syntax = "validate"
|
107
|
+
c.description = "Checks through your DayOne database to see if any of your journal entries break XML validation."
|
108
|
+
|
109
|
+
c.action do
|
110
|
+
require 'libxml'
|
111
|
+
require 'rb-dayone'
|
112
|
+
|
113
|
+
LibXML::XML::Error.set_handler(&LibXML::XML::Error::QUIET_HANDLER)
|
114
|
+
failed_entries = []
|
115
|
+
|
116
|
+
all_entries = DayOne.entries
|
117
|
+
puts "Checking #{all_entries.size} entr#{all_entries.size == 1 ? 'y' : 'ies'}..."
|
118
|
+
|
119
|
+
all_entries.each do |f|
|
120
|
+
begin
|
121
|
+
contents = File.read(f)
|
122
|
+
LibXML::XML::Parser.string(contents).parse
|
123
|
+
rescue LibXML::XML::Error
|
124
|
+
failed_entries << f
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
if failed_entries.empty?
|
129
|
+
puts "No errors. Everything is OK!"
|
130
|
+
else
|
131
|
+
puts "#{failed_entries.size} error#{failed_entries.size == 1 ? '' : 's'} in validation:"
|
132
|
+
failed_entries.each{ |f| puts " #{f}" }
|
133
|
+
end
|
134
|
+
end
|
64
135
|
end
|
data/lib/rb-dayone.rb
CHANGED
@@ -42,6 +42,12 @@ module DayOne
|
|
42
42
|
@auto_journal_location ||= File.expand_path(plist_reader['NSNavLastRootDirectory'])
|
43
43
|
end
|
44
44
|
|
45
|
+
# All DayOne entries, as file names
|
46
|
+
# @return [Array] all DayOne entries
|
47
|
+
def entries
|
48
|
+
Dir[File.join(journal_location, 'entries','*.doentry')]
|
49
|
+
end
|
50
|
+
|
45
51
|
private
|
46
52
|
|
47
53
|
# The journal file location
|
data/lib/rb-dayone/entry.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'libxml'
|
2
|
+
|
1
3
|
# A text-only journal entry for DayOne.
|
2
4
|
class DayOne::Entry
|
3
5
|
|
@@ -10,8 +12,11 @@ class DayOne::Entry
|
|
10
12
|
# Whether the entry has been starred
|
11
13
|
attr_accessor :starred
|
12
14
|
|
15
|
+
# Whether the entry has been saved to file at all.
|
16
|
+
attr_accessor :saved
|
17
|
+
|
13
18
|
# The PList doctype, used for XML export
|
14
|
-
DOCTYPE =
|
19
|
+
DOCTYPE = [:DOCTYPE, :plist, :PUBLIC, "-//Apple//DTD PLIST 1.0//EN", "http://www.apple.com/DTDs/PropertyList-1.0.dtd"]
|
15
20
|
|
16
21
|
# Initialise a journal entry, ready for inclusion into your journal
|
17
22
|
# @param [String] entry_text the body text of the journal entry
|
@@ -22,6 +27,7 @@ class DayOne::Entry
|
|
22
27
|
@creation_date = Time.now
|
23
28
|
@starred = false
|
24
29
|
@entry_text = entry_text
|
30
|
+
@saved = false
|
25
31
|
|
26
32
|
hsh.each do |k,v|
|
27
33
|
setter = "#{k}="
|
@@ -36,12 +42,17 @@ class DayOne::Entry
|
|
36
42
|
@uuid ||= `uuidgen`.gsub('-','').strip
|
37
43
|
end
|
38
44
|
|
45
|
+
# The same as calling Entry#saved
|
46
|
+
def saved?
|
47
|
+
saved
|
48
|
+
end
|
49
|
+
|
39
50
|
# Convert an entry to XML.
|
40
51
|
# @return [String] the entry as XML
|
41
52
|
def to_xml
|
42
|
-
builder = Builder::XmlMarkup.new
|
53
|
+
builder = Builder::XmlMarkup.new(indent:2)
|
43
54
|
builder.instruct! # Basic xml tag
|
44
|
-
builder.declare!
|
55
|
+
builder.declare! *DOCTYPE # PList doctype
|
45
56
|
builder.plist(version:1.0) do
|
46
57
|
builder.dict do
|
47
58
|
builder.key 'Creation Date'
|
@@ -61,7 +72,7 @@ class DayOne::Entry
|
|
61
72
|
builder.string uuid
|
62
73
|
end
|
63
74
|
end
|
64
|
-
builder.target
|
75
|
+
builder.target!
|
65
76
|
end
|
66
77
|
|
67
78
|
# Create a .doentry file with this entry.
|
@@ -74,4 +85,16 @@ class DayOne::Entry
|
|
74
85
|
File.open(file_location,'w'){ |io| io << xml }
|
75
86
|
return true
|
76
87
|
end
|
88
|
+
|
89
|
+
# Check to make sure that we output valid xml
|
90
|
+
def xml_valid?
|
91
|
+
LibXML::XML::Error.set_handler(&LibXML::XML::Error::QUIET_HANDLER)
|
92
|
+
begin
|
93
|
+
LibXML::XML::Parser.string(to_xml).parse
|
94
|
+
rescue LibXML::XML::Error
|
95
|
+
return false
|
96
|
+
else
|
97
|
+
return true
|
98
|
+
end
|
99
|
+
end
|
77
100
|
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'libxml'
|
2
|
+
|
3
|
+
# Imports DayOne entries from XML files or plain text
|
4
|
+
class DayOne::EntryImporter
|
5
|
+
|
6
|
+
# Raw data as provided in initialize
|
7
|
+
attr_accessor :data
|
8
|
+
|
9
|
+
# File (if supplied)
|
10
|
+
attr_accessor :file
|
11
|
+
|
12
|
+
# Create a new entry based on a string. To import from a file,
|
13
|
+
# use EntryImporter.from_file.
|
14
|
+
# @param [String] data The raw data for the importer to process
|
15
|
+
def initialize data
|
16
|
+
@data = data
|
17
|
+
end
|
18
|
+
|
19
|
+
# Create a new entry from a file
|
20
|
+
# @param [String] file The file to import
|
21
|
+
def self.from_file file
|
22
|
+
ei = new(File.read(file))
|
23
|
+
ei.file = file
|
24
|
+
ei
|
25
|
+
end
|
26
|
+
|
27
|
+
# Access entry data by key
|
28
|
+
# @param [String, Symbol] key The key to retrieve
|
29
|
+
# @return the value stored in the file, or nil
|
30
|
+
def [] key
|
31
|
+
processed_data[key]
|
32
|
+
end
|
33
|
+
|
34
|
+
# Generate and return the data contained within the doentry file, as a hash
|
35
|
+
# @return [Hash] the processed data
|
36
|
+
def processed_data
|
37
|
+
if !@processed_data
|
38
|
+
@processed_data = {}
|
39
|
+
LibXML::XML::Error.set_handler(&LibXML::XML::Error::QUIET_HANDLER)
|
40
|
+
|
41
|
+
begin
|
42
|
+
document = LibXML::XML::Parser.string(data).parse
|
43
|
+
key = nil
|
44
|
+
|
45
|
+
document.find('//plist/dict/*').each do |elem|
|
46
|
+
case elem.name
|
47
|
+
when 'key'
|
48
|
+
key = elem.content
|
49
|
+
when 'date'
|
50
|
+
if elem.content =~ /(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)Z/
|
51
|
+
@processed_data[key] = Time.new($1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i)
|
52
|
+
end
|
53
|
+
when 'true'
|
54
|
+
@processed_data[key] = true
|
55
|
+
when 'false'
|
56
|
+
@processed_data[key] = false
|
57
|
+
else
|
58
|
+
@processed_data[key] = elem.content
|
59
|
+
end
|
60
|
+
end
|
61
|
+
rescue LibXML::XML::Error
|
62
|
+
$stderr.puts "Error parsing #{file ? "file #{file}" : "data"}. Skipping."
|
63
|
+
end
|
64
|
+
end
|
65
|
+
@processed_data
|
66
|
+
end
|
67
|
+
|
68
|
+
# Generate an entry from this importer
|
69
|
+
# @return a DayOne::Entry based on this importer
|
70
|
+
def to_entry
|
71
|
+
DayOne::Entry.new(
|
72
|
+
self['Entry Text'],
|
73
|
+
starred: self['Starred'],
|
74
|
+
creation_date: self['Creation Date'],
|
75
|
+
saved: true
|
76
|
+
)
|
77
|
+
end
|
78
|
+
end
|
@@ -1,12 +1,20 @@
|
|
1
1
|
require 'json'
|
2
2
|
|
3
|
+
# The PListReader is a class that reads PLists.
|
4
|
+
# It is used to read the DayOne preferences PList.
|
3
5
|
class DayOne::PlistReader
|
6
|
+
|
7
|
+
# The path of the PList to read.
|
4
8
|
attr_accessor :path
|
5
9
|
|
10
|
+
# Initialize the PList Reader, given a path
|
11
|
+
# @param [String] path the path to the PList; defaults to the standard DayOne preference plist
|
6
12
|
def initialize path=nil
|
7
13
|
@path = path || File.join(ENV['HOME'], 'Library', 'Preferences', 'com.dayoneapp.dayone.plist')
|
8
14
|
end
|
9
15
|
|
16
|
+
# Retrieve the body of the plist as an array, parsed through JSON
|
17
|
+
# @return [Hash] the body of the plist as a hash.
|
10
18
|
def body
|
11
19
|
if !@body
|
12
20
|
json_string = `plutil -convert json -o - '#{path}'`
|
@@ -15,6 +23,7 @@ class DayOne::PlistReader
|
|
15
23
|
@body
|
16
24
|
end
|
17
25
|
|
26
|
+
# This allows us to access the body's method as well as the reader's.
|
18
27
|
def method_missing sym, *args
|
19
28
|
if self.body.respond_to? sym
|
20
29
|
self.body.send(sym, *args)
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# A search of the database.
|
2
|
+
# Create this object with Search.new. Give it some parameters to search for, then
|
3
|
+
# simple use Search#[] to access results.
|
4
|
+
class DayOne::Search
|
5
|
+
|
6
|
+
# The entry must include this text
|
7
|
+
attr_accessor :entry_text
|
8
|
+
|
9
|
+
# The entry must be starred
|
10
|
+
attr_accessor :starred
|
11
|
+
|
12
|
+
# Initialize the search. Currently you can only search by entry text and starred status,
|
13
|
+
# but both of these can be passed in via hash.
|
14
|
+
# @param [Hash] hash a hash of search criteria, including:
|
15
|
+
# * +entry_text+: Text that the entry must include
|
16
|
+
# * +starred+: whether the entry is starred or not
|
17
|
+
def initialize hash={}
|
18
|
+
@entry_text = ''
|
19
|
+
hash.each do |k,v|
|
20
|
+
setter = "#{k}="
|
21
|
+
self.send(setter, v) if self.respond_to?(setter)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Fetch the results by searching. Uses a cached version of the DayOne database.
|
26
|
+
# @return [Array] all entries matching your results
|
27
|
+
def results
|
28
|
+
if !@results
|
29
|
+
@results = []
|
30
|
+
working_results = cache
|
31
|
+
|
32
|
+
working_results = working_results.select{ |e| e.entry_text.include? entry_text } unless entry_text == ''
|
33
|
+
working_results = working_results.select{ |e| e.starred == starred } unless starred.nil?
|
34
|
+
|
35
|
+
@results = working_results
|
36
|
+
end
|
37
|
+
@results
|
38
|
+
end
|
39
|
+
|
40
|
+
# Fetches a particular result
|
41
|
+
# @param [Integer] index the index of the result to fetch
|
42
|
+
# @return [DayOne::Entry] the entry
|
43
|
+
def [] index
|
44
|
+
results[index]
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
# Caches all journal entries for us. On first running, will load everything
|
50
|
+
# from file. After this, will just refer back to the cache.
|
51
|
+
# @return [Array] an array of DayOne::Entry objects
|
52
|
+
def cache
|
53
|
+
if !@cache
|
54
|
+
entries = File.join(DayOne::journal_location, 'entries', '*.doentry')
|
55
|
+
@cache = Dir[entries].map{ |e| DayOne::EntryImporter::from_file(e).to_entry }
|
56
|
+
end
|
57
|
+
@cache
|
58
|
+
end
|
59
|
+
end
|
data/rb-dayone.gemspec
CHANGED
@@ -5,7 +5,7 @@ Gem::Specification.new do |s|
|
|
5
5
|
s.version = File.read('version.txt')
|
6
6
|
|
7
7
|
s.summary = "Create DayOne journal entries in ruby."
|
8
|
-
s.description = "Create [DayOne](http://www.dayoneapp.com) journal entries simply and easily in ruby. Currently only supports text entries, image entries to come."
|
8
|
+
s.description = "Create or search [DayOne](http://www.dayoneapp.com) journal entries simply and easily in ruby. Currently only supports text entries, image entries to come."
|
9
9
|
|
10
10
|
s.author = 'Jan-Yves Ruzicka'
|
11
11
|
s.email = 'janyves.ruzicka@gmail.com'
|
@@ -19,4 +19,19 @@ Gem::Specification.new do |s|
|
|
19
19
|
|
20
20
|
s.add_runtime_dependency 'builder', '~> 2.0'
|
21
21
|
s.add_runtime_dependency 'commander', '~> 4.1.2'
|
22
|
+
s.add_runtime_dependency 'libxml-ruby', '~> 2.3.3'
|
23
|
+
|
24
|
+
s.post_install_message = <<-end
|
25
|
+
#{'-'*80}
|
26
|
+
Hi there! If you're upgrading from version <= 0.2.0 of this gem, I've been a
|
27
|
+
horrid dev and let a few bugs through in my XML building code. In order to fix
|
28
|
+
this, you can run `dayone verify` to see if your database needs fixing. If any
|
29
|
+
of the errors are my fault, you should be able to fix them with `dayone
|
30
|
+
repair`.
|
31
|
+
|
32
|
+
Sorry if this has caused any inconvenience. If you still have trouble repairing
|
33
|
+
any of your .doentry files, send me an email and I'll see what I can do to
|
34
|
+
help.
|
35
|
+
#{'-'*80}
|
36
|
+
end
|
22
37
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
3
|
+
<plist version="1.0">
|
4
|
+
<dict>
|
5
|
+
<key>Creation Date</key>
|
6
|
+
<date>2012-08-16T08:42:17Z</date>
|
7
|
+
<key>Entry Text</key>
|
8
|
+
<string>Yes, this is foo.</string>
|
9
|
+
<key>Starred</key>
|
10
|
+
<false/>
|
11
|
+
<key>UUID</key>
|
12
|
+
<string>748AD5D252F44149920485B0CEA478E3</string>
|
13
|
+
</dict>
|
14
|
+
</plist>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
3
|
+
<plist version="1.0">
|
4
|
+
<dict>
|
5
|
+
<key>Creation Date</key>
|
6
|
+
<date>2012-08-16T08:42:19Z</date>
|
7
|
+
<key>Entry Text</key>
|
8
|
+
<string>Hello bar.</string>
|
9
|
+
<key>Starred</key>
|
10
|
+
<true/>
|
11
|
+
<key>UUID</key>
|
12
|
+
<string>F13723CDFD454481B24312DCD627BFD7</string>
|
13
|
+
</dict>
|
14
|
+
</plist>
|
@@ -0,0 +1 @@
|
|
1
|
+
foo
|
File without changes
|
File without changes
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
3
|
+
<plist version="1.0">
|
4
|
+
<dict>
|
5
|
+
<key>Entry Text</key>
|
6
|
+
<string>Hello, world!</string>
|
7
|
+
<key>Starred</key>
|
8
|
+
<true/>
|
9
|
+
<key>Creation Date</key>
|
10
|
+
<date>1997-08-29T02:14:0Z</date>
|
11
|
+
</dict>
|
12
|
+
</plist>
|
File without changes
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
3
|
+
<plist version="1.0">
|
4
|
+
<dict>
|
5
|
+
<key>Entry Text</key>
|
6
|
+
<string>æ</string>
|
7
|
+
<key>Starred</key>
|
8
|
+
<true/>
|
9
|
+
<key>Creation Date</key>
|
10
|
+
<date>1997-08-29T02:14:0Z</date>
|
11
|
+
</dict>
|
12
|
+
</plist>
|
data/spec/dayone_spec.rb
CHANGED
@@ -0,0 +1,69 @@
|
|
1
|
+
#encoding: UTF-8
|
2
|
+
|
3
|
+
require './spec/spec_helper'
|
4
|
+
|
5
|
+
describe DayOne::EntryImporter do
|
6
|
+
let(:sample_entry){ DayOne::EntryImporter::from_file spec_data('sample.doentry') }
|
7
|
+
|
8
|
+
describe "#initialize" do
|
9
|
+
it "should accept a string or file" do
|
10
|
+
ei = DayOne::EntryImporter.new('foo')
|
11
|
+
ei.data.should == 'foo'
|
12
|
+
|
13
|
+
file_ei = DayOne::EntryImporter::from_file spec_data('foo.doentry')
|
14
|
+
file_ei.data.should == 'foo'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#[]" do
|
19
|
+
|
20
|
+
def wrap str
|
21
|
+
<<-end
|
22
|
+
<plist>
|
23
|
+
<dict>
|
24
|
+
<key>element</key>
|
25
|
+
<string>#{str}</string>
|
26
|
+
</dict>
|
27
|
+
</plist>
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should parse strings" do
|
32
|
+
sample_entry['Entry Text'].should == 'Hello, world!'
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should parse booleans" do
|
36
|
+
sample_entry['Starred'].should == true
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should parse dates" do
|
40
|
+
sample_entry['Creation Date'].should == Time.new(1997, 8, 29, 2, 14, 0)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should accept ampersands" do
|
44
|
+
importer = DayOne::EntryImporter.new(wrap('&'))
|
45
|
+
importer['element'].should == '&'
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should accept UTF-8" do
|
49
|
+
importer = DayOne::EntryImporter.new(wrap('æ'))
|
50
|
+
importer['element'].should == 'æ'
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should accept UTF-8 from file" do
|
54
|
+
importer = DayOne::EntryImporter.from_file spec_data('utf.doentry')
|
55
|
+
importer['Entry Text'].should == 'æ'
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "#to_entry" do
|
61
|
+
it "should make a valid entry" do
|
62
|
+
entry = sample_entry.to_entry
|
63
|
+
entry.entry_text.should == 'Hello, world!'
|
64
|
+
entry.starred.should be_true
|
65
|
+
entry.creation_date.year.should == 1997
|
66
|
+
entry.should be_saved
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/spec/entry_spec.rb
CHANGED
@@ -2,12 +2,18 @@ require './spec/spec_helper'
|
|
2
2
|
require 'fileutils'
|
3
3
|
|
4
4
|
describe DayOne::Entry do
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
before :each do
|
6
|
+
FileUtils::mkdir_p spec_data('working/entries')
|
7
|
+
end
|
8
|
+
|
9
|
+
after :each do
|
10
|
+
FileUtils::rm_rf spec_data('working')
|
8
11
|
end
|
9
12
|
|
10
13
|
describe "#to_xml" do
|
14
|
+
|
15
|
+
let(:sample_entry){ DayOne::Entry.new('foo', starred:true) }
|
16
|
+
|
11
17
|
it "should give a default entry" do
|
12
18
|
e = subject.to_xml
|
13
19
|
e.should match %r|<key>Entry Text</key>\s*<string></string>|
|
@@ -15,31 +21,38 @@ describe DayOne::Entry do
|
|
15
21
|
end
|
16
22
|
|
17
23
|
it "should set from initialize" do
|
18
|
-
|
19
|
-
|
20
|
-
|
24
|
+
sample_entry.starred.should be_true
|
25
|
+
sample_entry.entry_text.should == 'foo'
|
26
|
+
sample_entry.should_not be_saved
|
21
27
|
end
|
22
28
|
|
23
29
|
it "should act properly when starred" do
|
24
|
-
|
25
|
-
e.should match %r|<key>Starred</key>\s*<true/>|
|
30
|
+
sample_entry.to_xml.should match %r|<key>Starred</key>\s*<true/>|
|
26
31
|
end
|
27
32
|
end
|
28
33
|
|
29
34
|
describe "#create!" do
|
30
35
|
it "should correctly create a .doentry file" do
|
31
|
-
|
32
|
-
|
36
|
+
|
37
|
+
DayOne::journal_location = spec_data('working')
|
33
38
|
|
34
39
|
e = subject
|
35
40
|
e.entry_text = "Hello, world!"
|
36
41
|
e.create!
|
37
42
|
|
38
|
-
file_location = Dir['
|
43
|
+
file_location = Dir[spec_data('working', 'entries', '*.doentry')][0]
|
39
44
|
file_location.should_not be_nil
|
40
45
|
|
41
46
|
contents = File.read(file_location)
|
42
47
|
contents.should == e.to_xml
|
43
48
|
end
|
44
49
|
end
|
50
|
+
|
51
|
+
describe "#xml_valid?" do
|
52
|
+
it "should handle weird XML characters" do
|
53
|
+
e = subject
|
54
|
+
e.entry_text = "Hello <&> Goodbye"
|
55
|
+
e.should be_xml_valid
|
56
|
+
end
|
57
|
+
end
|
45
58
|
end
|
data/spec/plist_reader_spec.rb
CHANGED
@@ -13,7 +13,7 @@ describe DayOne::PlistReader do
|
|
13
13
|
end
|
14
14
|
|
15
15
|
it "should correctly parse binary plists" do
|
16
|
-
reader = DayOne::PlistReader.new(File.join(File.dirname(__FILE__),'sample.plist'))
|
16
|
+
reader = DayOne::PlistReader.new(File.join(File.dirname(__FILE__),'data', 'sample.plist'))
|
17
17
|
reader['foo'].should == 'bar'
|
18
18
|
end
|
19
19
|
end
|
data/spec/search_spec.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
describe DayOne::Search do
|
2
|
+
describe "#initialize" do
|
3
|
+
it "should create a Search object, uninitialized" do
|
4
|
+
subject.entry_text.should == ''
|
5
|
+
subject.starred.should be_nil
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "#results" do
|
10
|
+
before :all do
|
11
|
+
DayOne::journal_location = spec_data
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should find all posts when no search criteria are applied" do
|
15
|
+
subject.results.size.should == 2
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should find posts when searching by string" do
|
19
|
+
search = DayOne::Search.new entry_text: 'foo'
|
20
|
+
search.results.size.should == 1
|
21
|
+
search[0].entry_text.should == "Yes, this is foo."
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should find posts when searching by starred" do
|
25
|
+
search = DayOne::Search.new starred:true
|
26
|
+
search.results.size.should == 1
|
27
|
+
search[0].entry_text.should == "Hello bar."
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should find posts when searching by string and starred" do
|
31
|
+
search = DayOne::Search.new entry_text: 'foo', starred:true
|
32
|
+
search.results.should be_empty
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/spec/spec_helper.rb
CHANGED
data/version.txt
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.3
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rb-dayone
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-08-
|
12
|
+
date: 2012-08-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: builder
|
@@ -43,8 +43,24 @@ dependencies:
|
|
43
43
|
- - ~>
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: 4.1.2
|
46
|
-
|
47
|
-
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: libxml-ruby
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 2.3.3
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.3.3
|
62
|
+
description: Create or search [DayOne](http://www.dayoneapp.com) journal entries simply
|
63
|
+
and easily in ruby. Currently only supports text entries, image entries to come.
|
48
64
|
email: janyves.ruzicka@gmail.com
|
49
65
|
executables:
|
50
66
|
- dayone
|
@@ -57,21 +73,37 @@ files:
|
|
57
73
|
- History.rdoc
|
58
74
|
- lib/rb-dayone.rb
|
59
75
|
- lib/rb-dayone/entry.rb
|
76
|
+
- lib/rb-dayone/entry_importer.rb
|
60
77
|
- lib/rb-dayone/plist_reader.rb
|
78
|
+
- lib/rb-dayone/search.rb
|
61
79
|
- Manifest
|
80
|
+
- Rakefile
|
62
81
|
- rb-dayone.gemspec
|
63
82
|
- README.md
|
83
|
+
- spec/data/entries/748AD5D252F44149920485B0CEA478E3.doentry
|
84
|
+
- spec/data/entries/F13723CDFD454481B24312DCD627BFD7.doentry
|
85
|
+
- spec/data/foo.doentry
|
86
|
+
- spec/data/locations/location-auto/location
|
87
|
+
- spec/data/locations/location-specified/location
|
88
|
+
- spec/data/sample.doentry
|
89
|
+
- spec/data/sample.plist
|
90
|
+
- spec/data/utf.doentry
|
64
91
|
- spec/dayone_spec.rb
|
92
|
+
- spec/entry_importer_spec.rb
|
65
93
|
- spec/entry_spec.rb
|
66
|
-
- spec/locations/location-auto/location
|
67
|
-
- spec/locations/location-specified/location
|
68
|
-
- spec/spec_helper.rb
|
69
94
|
- spec/plist_reader_spec.rb
|
70
|
-
- spec/
|
95
|
+
- spec/search_spec.rb
|
96
|
+
- spec/spec_helper.rb
|
71
97
|
- version.txt
|
72
98
|
homepage: https://github.com/jyruzicka/rb-dayone
|
73
99
|
licenses: []
|
74
|
-
post_install_message:
|
100
|
+
post_install_message: ! "--------------------------------------------------------------------------------\nHi
|
101
|
+
there! If you're upgrading from version <= 0.2.0 of this gem, I've been a\nhorrid
|
102
|
+
dev and let a few bugs through in my XML building code. In order to fix\nthis, you
|
103
|
+
can run `dayone verify` to see if your database needs fixing. If any \nof the errors
|
104
|
+
are my fault, you should be able to fix them with `dayone\nrepair`.\n\nSorry if
|
105
|
+
this has caused any inconvenience. If you still have trouble repairing\nany of your
|
106
|
+
.doentry files, send me an email and I'll see what I can do to\nhelp.\n--------------------------------------------------------------------------------\n"
|
75
107
|
rdoc_options: []
|
76
108
|
require_paths:
|
77
109
|
- lib
|