rb-dayone 0.2.0 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|