diary-ruby 0.1.0
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.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.travis.yml +4 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +4 -0
- data/LICENSE +674 -0
- data/README.md +56 -0
- data/Rakefile +10 -0
- data/TODO.md +4 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/diary-ruby.gemspec +39 -0
- data/exe/diaryrb +188 -0
- data/lib/diary-ruby.rb +20 -0
- data/lib/diary-ruby/configuration.rb +88 -0
- data/lib/diary-ruby/entry.rb +85 -0
- data/lib/diary-ruby/ext/encryptor.rb +95 -0
- data/lib/diary-ruby/ext/secure_pstore.rb +86 -0
- data/lib/diary-ruby/parser.rb +68 -0
- data/lib/diary-ruby/server/public/script.js +57 -0
- data/lib/diary-ruby/server/public/style.css +33 -0
- data/lib/diary-ruby/server/server.rb +93 -0
- data/lib/diary-ruby/server/views/index.erb +61 -0
- data/lib/diary-ruby/store.rb +79 -0
- data/lib/diary-ruby/version.rb +3 -0
- metadata +182 -0
data/README.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
**DON'T USE THIS YET**
|
|
2
|
+
|
|
3
|
+
# diary-ruby
|
|
4
|
+
|
|
5
|
+
A toy CLI app for me. Playing with encryption and the `$EDITOR` env var.
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
$ gem install diary-ruby
|
|
10
|
+
$ diaryrb
|
|
11
|
+
|
|
12
|
+
TYPE TYPE TYPE
|
|
13
|
+
|
|
14
|
+
Now you have a diary too.
|
|
15
|
+
|
|
16
|
+
You can create a config file to make it easier to manage multiple diaries.
|
|
17
|
+
`diaryrb` looks for a config file in ~/.diaryrb/config.yaml. Valid config
|
|
18
|
+
options are `passphrase` and `path`. For example:
|
|
19
|
+
|
|
20
|
+
```yaml
|
|
21
|
+
default:
|
|
22
|
+
path: "/Users/yername/Dropbox/Documents/notes.diary"
|
|
23
|
+
|
|
24
|
+
secure.store:
|
|
25
|
+
passphrase: "this is the passphrase, I put it in a config file! 82acf427f94c513f8d7f81995a549361089d903f"
|
|
26
|
+
path: "~/secure.secret.diary"
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
If a config file is used, diaryrb uses the -d option to pick a diary by name:
|
|
30
|
+
|
|
31
|
+
$ diaryrb -d default
|
|
32
|
+
|
|
33
|
+
would load the diary at `/Users/.../notes.diary`, while
|
|
34
|
+
|
|
35
|
+
$ diaryrb -d mynotes
|
|
36
|
+
|
|
37
|
+
would create a new diary file named "mynotes" in the current directory.
|
|
38
|
+
|
|
39
|
+
## Development
|
|
40
|
+
|
|
41
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
42
|
+
`rake test` to run the tests. You can also run `bin/console` for an interactive
|
|
43
|
+
prompt that will allow you to experiment.
|
|
44
|
+
|
|
45
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
46
|
+
release a new version, update the version number in `version.rb`, and then run
|
|
47
|
+
`bundle exec rake release`, which will create a git tag for the version, push
|
|
48
|
+
git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
49
|
+
|
|
50
|
+
## Contributing
|
|
51
|
+
|
|
52
|
+
Bug reports and pull requests are welcome on GitHub at
|
|
53
|
+
https://github.com/abachman/diary-ruby. This project is intended to be a
|
|
54
|
+
safe, welcoming space for collaboration, and contributors are expected to
|
|
55
|
+
adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
|
|
56
|
+
|
data/Rakefile
ADDED
data/TODO.md
ADDED
data/bin/console
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require "bundler/setup"
|
|
4
|
+
require "diary-ruby"
|
|
5
|
+
|
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
|
8
|
+
|
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
|
10
|
+
# require "pry"
|
|
11
|
+
# Pry.start
|
|
12
|
+
|
|
13
|
+
require "irb"
|
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/diary-ruby.gemspec
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'diary-ruby/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = "diary-ruby"
|
|
8
|
+
spec.version = Diary::VERSION
|
|
9
|
+
spec.authors = ["Adam Bachman"]
|
|
10
|
+
spec.email = ["adam.bachman@gmail.com"]
|
|
11
|
+
spec.licenses = ['GPL-3.0']
|
|
12
|
+
|
|
13
|
+
spec.summary = %q{A CLI diary: diaryrb}
|
|
14
|
+
spec.description = %q{A command line diary: diaryrb}
|
|
15
|
+
spec.homepage = "https://github.com/abachman/diary-ruby"
|
|
16
|
+
|
|
17
|
+
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
|
18
|
+
# delete this section to allow pushing this gem to any host.
|
|
19
|
+
if spec.respond_to?(:metadata)
|
|
20
|
+
spec.metadata['allowed_push_host'] = "https://rubygems.org"
|
|
21
|
+
else
|
|
22
|
+
raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
26
|
+
spec.bindir = "exe"
|
|
27
|
+
spec.executables = ['diaryrb']
|
|
28
|
+
spec.require_paths = ["lib"]
|
|
29
|
+
|
|
30
|
+
spec.add_development_dependency "bundler", "~> 1.10"
|
|
31
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
|
32
|
+
spec.add_development_dependency "minitest", '~> 5.8'
|
|
33
|
+
spec.add_development_dependency "minitest-display", '~> 0.3'
|
|
34
|
+
|
|
35
|
+
spec.add_dependency 'sinatra', '~> 1.4'
|
|
36
|
+
spec.add_dependency 'rdiscount', '~> 2.1'
|
|
37
|
+
spec.add_dependency 'slop', '~> 4.2'
|
|
38
|
+
spec.add_dependency 'launchy', '~> 2.4'
|
|
39
|
+
end
|
data/exe/diaryrb
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'diary-ruby'
|
|
4
|
+
require 'slop'
|
|
5
|
+
require 'launchy'
|
|
6
|
+
require 'thread'
|
|
7
|
+
|
|
8
|
+
DEFAULT_DIARY = "diaryrb.store"
|
|
9
|
+
|
|
10
|
+
prompt_for_password = false
|
|
11
|
+
opts = Slop.parse do |o|
|
|
12
|
+
# o.string '-c', '--configuration', 'config file location'
|
|
13
|
+
o.string '-d', '--diary', "choose diary storage file (leave blank for default, #{DEFAULT_DIARY})"
|
|
14
|
+
o.string '-p', '--passphrase', 'Use given encryption passphrase or prompt if option is used but no passphrase is given.', default: false do |v|
|
|
15
|
+
if v.start_with?('-') || v.nil? || v.strip.size == 0
|
|
16
|
+
prompt_for_password = true
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# usage modes
|
|
21
|
+
o.separator ''
|
|
22
|
+
o.separator "Actions (can't be used in combination):"
|
|
23
|
+
o.string '-e', '--edit', 'edit a specific post'
|
|
24
|
+
o.bool '-l', '--list', 'list all posts by date'
|
|
25
|
+
o.bool '-s', '--serve', 'start Diary webserver'
|
|
26
|
+
|
|
27
|
+
o.separator ''
|
|
28
|
+
o.separator 'Other options:'
|
|
29
|
+
o.bool '-v', '--verbose', 'enable verbose mode'
|
|
30
|
+
o.on '-V', '--version', 'print the version and quit' do
|
|
31
|
+
puts "diaryrb #{ Diary::VERSION }"
|
|
32
|
+
exit
|
|
33
|
+
end
|
|
34
|
+
o.on '-h', '--help', 'show help and quit' do
|
|
35
|
+
puts o
|
|
36
|
+
exit
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Global config options
|
|
41
|
+
Diary::Configuration.verbose = opts.verbose?
|
|
42
|
+
|
|
43
|
+
# Get diary name from configuration or command line
|
|
44
|
+
_diary = DEFAULT_DIARY
|
|
45
|
+
if opts[:diary]
|
|
46
|
+
# ALWAYS prefer the given argument
|
|
47
|
+
_diary = opts[:diary]
|
|
48
|
+
elsif Diary::Configuration.exists?
|
|
49
|
+
if Diary::Configuration.has_diary_config?('default')
|
|
50
|
+
Diary.debug "LOADING default DIARY"
|
|
51
|
+
_diary = 'default'
|
|
52
|
+
Diary::Configuration.load_config('default')
|
|
53
|
+
else
|
|
54
|
+
Diary.debug "CONFIG EXISTS, NO DEFAULT. LOADING DIARY #{ _diary }"
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
Diary::Configuration.current_diary = _diary
|
|
59
|
+
|
|
60
|
+
_passphrase = nil
|
|
61
|
+
if prompt_for_password
|
|
62
|
+
require 'io/console'
|
|
63
|
+
print "Enter passphrase (leave blank for none): "
|
|
64
|
+
_passphrase = STDIN.noecho {|io| io.gets}.chomp
|
|
65
|
+
elsif opts[:passphrase] && opts[:passphrase].strip.size > 0
|
|
66
|
+
_passphrase = opts[:passphrase]
|
|
67
|
+
elsif ENV['PASSPHRASE']
|
|
68
|
+
_passphrase = ENV['PASSPHRASE']
|
|
69
|
+
elsif Diary::Configuration.passphrase
|
|
70
|
+
_passphrase = Diary::Configuration.passphrase
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
diary_path = Diary::Configuration.path || Diary::Configuration.current_diary
|
|
74
|
+
Diary.debug "LOADING DIARY #{ Diary::Configuration.current_diary } AT PATH #{ diary_path }"
|
|
75
|
+
if _passphrase.nil? || _passphrase.size == 0
|
|
76
|
+
Diary.debug "LOADING WITH NO PASSPHRASE!"
|
|
77
|
+
$store = Diary::Store.new(diary_path)
|
|
78
|
+
else
|
|
79
|
+
Diary.debug "LOADING WITH PASSPHRASE #{ _passphrase.gsub(/./, '*') }"
|
|
80
|
+
$store = Diary::SecureStore.new(diary_path, _passphrase)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# this is like rake db:migrate
|
|
84
|
+
$store.write do |db|
|
|
85
|
+
db[:entries] ||= []
|
|
86
|
+
db[:entries] = db[:entries].compact.uniq.sort
|
|
87
|
+
db[:tags] ||= []
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
if opts.list?
|
|
91
|
+
entries = $store.read(:entries)
|
|
92
|
+
puts ''
|
|
93
|
+
|
|
94
|
+
if entries.nil? || entries.size == 0
|
|
95
|
+
puts "No entries"
|
|
96
|
+
exit
|
|
97
|
+
else
|
|
98
|
+
entries.uniq.sort.reverse.each do |entry_key|
|
|
99
|
+
puts "#{ entry_key } #{ $store.read(entry_key)[:text][0..40].gsub("\n", ' ') }..."
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
elsif opts.serve?
|
|
103
|
+
Diary::Server.store = $store
|
|
104
|
+
t = Thread.new do
|
|
105
|
+
Diary::Server.run!
|
|
106
|
+
end
|
|
107
|
+
Launchy.open('http://localhost:4567')
|
|
108
|
+
t.join
|
|
109
|
+
else
|
|
110
|
+
def finish(file)
|
|
111
|
+
file.close
|
|
112
|
+
file.unlink # deletes the temp file
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def parse_and_store(file)
|
|
116
|
+
diary_entry = Diary::Parser.parse_file(file)
|
|
117
|
+
$store.write_entry(diary_entry)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# create a tempfile to store entry in progress in EDITOR
|
|
121
|
+
file = Tempfile.new(['diary', '.md'])
|
|
122
|
+
file.sync = true
|
|
123
|
+
|
|
124
|
+
# default new entry
|
|
125
|
+
entry_source = {
|
|
126
|
+
day: Time.now.strftime("%F"),
|
|
127
|
+
time: Time.now.strftime("%T"),
|
|
128
|
+
tags: "",
|
|
129
|
+
title: "",
|
|
130
|
+
text: "text goes here"
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
# if --edit option is used with a valid entry, load it
|
|
134
|
+
if opts[:edit] && (entry_hash = $store.read(opts[:edit]))
|
|
135
|
+
entry = Diary::Entry.from_store(entry_hash)
|
|
136
|
+
entry_source = entry.to_hash
|
|
137
|
+
entry_source[:tags] = entry_source[:tags].join(', ')
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# prepare entry and launch editor
|
|
141
|
+
tmpl = Diary::Entry.generate(entry_source, $store)
|
|
142
|
+
file.write(tmpl)
|
|
143
|
+
|
|
144
|
+
ed = "vim -f"
|
|
145
|
+
if ENV['DIARY_EDITOR']
|
|
146
|
+
ed = ENV['DIARY_EDITOR']
|
|
147
|
+
elsif ENV['EDITOR']
|
|
148
|
+
ed = ENV['EDITOR']
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
pid = fork do
|
|
152
|
+
exec("#{ ed } #{ file.path }")
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# wait for child to finish, exit when the editor exits
|
|
156
|
+
exit_signal = Queue.new
|
|
157
|
+
|
|
158
|
+
trap("CLD") do
|
|
159
|
+
Diary.log "CHILD PID #{pid} TERMINATED"
|
|
160
|
+
exit_signal.push(true)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
Diary.log "WAITING FOR EDITOR IN PROCESS #{ pid }"
|
|
164
|
+
|
|
165
|
+
# Polling based observation of tempfile, save to Store whenever Entry is updated
|
|
166
|
+
omtime = File.mtime(file.path)
|
|
167
|
+
while true do
|
|
168
|
+
quitter = exit_signal.pop(true) rescue nil
|
|
169
|
+
|
|
170
|
+
mtime = File.mtime(file.path)
|
|
171
|
+
if mtime != omtime
|
|
172
|
+
Diary.log "FILE MODIFIED, UPDATING ENTRY"
|
|
173
|
+
parse_and_store(file)
|
|
174
|
+
omtime = mtime
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
if quitter
|
|
178
|
+
Diary.debug "QUIT SIGNAL RECEIVED"
|
|
179
|
+
# parse_and_store(file)
|
|
180
|
+
Diary.debug "CLEANING UP..."
|
|
181
|
+
finish(file)
|
|
182
|
+
Diary.debug "EXIT"
|
|
183
|
+
exit 0
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
sleep 1
|
|
187
|
+
end
|
|
188
|
+
end
|
data/lib/diary-ruby.rb
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require "diary-ruby/version"
|
|
2
|
+
require "diary-ruby/store"
|
|
3
|
+
require "diary-ruby/entry"
|
|
4
|
+
require "diary-ruby/parser"
|
|
5
|
+
require "diary-ruby/configuration"
|
|
6
|
+
require "diary-ruby/server/server"
|
|
7
|
+
|
|
8
|
+
module Diary
|
|
9
|
+
def self.log(message)
|
|
10
|
+
if Diary::Configuration.verbose
|
|
11
|
+
puts message
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.debug(message)
|
|
16
|
+
if Diary::Configuration.verbose
|
|
17
|
+
puts message
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
require 'pathname'
|
|
2
|
+
require 'yaml'
|
|
3
|
+
|
|
4
|
+
DIARY_DIR = ".diaryrb"
|
|
5
|
+
|
|
6
|
+
module Diary
|
|
7
|
+
# Read only app configuration
|
|
8
|
+
#
|
|
9
|
+
class Configuration
|
|
10
|
+
class Error < StandardError
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class << self
|
|
14
|
+
attr_accessor :current_diary
|
|
15
|
+
attr_accessor :verbose
|
|
16
|
+
|
|
17
|
+
# Find config directory starting at current dir and then moving up the tree
|
|
18
|
+
def config_dir(dir = Pathname.new("."))
|
|
19
|
+
app_config_dir = dir + DIARY_DIR
|
|
20
|
+
|
|
21
|
+
if dir.children.include?(app_config_dir)
|
|
22
|
+
app_config_dir.expand_path
|
|
23
|
+
else
|
|
24
|
+
return nil if dir.expand_path.root?
|
|
25
|
+
|
|
26
|
+
# go up the stack
|
|
27
|
+
config_dir(dir.parent)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def method_missing(method)
|
|
32
|
+
config[method.to_s]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def exists?
|
|
36
|
+
!config_dir.nil?
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def has_diary_config?(diary_identifier)
|
|
40
|
+
load_global_settings
|
|
41
|
+
global_settings.has_key?(diary_identifier)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def global_settings
|
|
45
|
+
@global_settings || {}
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# load a specific diary
|
|
49
|
+
def load_config(diary_identifier)
|
|
50
|
+
@config = load_config_for_diary(diary_identifier)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# default to current_diary
|
|
54
|
+
def config
|
|
55
|
+
@config ||= load_config_for_diary(current_diary)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
private
|
|
59
|
+
|
|
60
|
+
def load_config_for_diary(diary_identifier)
|
|
61
|
+
if !exists?
|
|
62
|
+
# no config file exists, build empty configuration options starting now
|
|
63
|
+
{}
|
|
64
|
+
else
|
|
65
|
+
load_global_settings
|
|
66
|
+
if global_settings.has_key?(diary_identifier)
|
|
67
|
+
global_settings[diary_identifier]
|
|
68
|
+
else
|
|
69
|
+
# configuration for this diary doesn't exist, build empty
|
|
70
|
+
# configuration options starting now
|
|
71
|
+
{}
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def load_global_settings
|
|
77
|
+
@global_settings ||= begin
|
|
78
|
+
if exists?
|
|
79
|
+
cf = File.join(config_dir, 'config.yaml')
|
|
80
|
+
YAML.load(File.open(cf))
|
|
81
|
+
else
|
|
82
|
+
{}
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
TEMPLATE = "# last entry posted at %{last_update_at}
|
|
2
|
+
|
|
3
|
+
DAY %{day}
|
|
4
|
+
TIME %{time}
|
|
5
|
+
TAGS %{tags}
|
|
6
|
+
TITLE %{title}
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
%{text}
|
|
11
|
+
"
|
|
12
|
+
|
|
13
|
+
require 'rdiscount'
|
|
14
|
+
|
|
15
|
+
module Diary
|
|
16
|
+
class Entry
|
|
17
|
+
attr_accessor :version, :day, :time, :tags, :text, :title, :key
|
|
18
|
+
|
|
19
|
+
CURRENT_VERSION = 1
|
|
20
|
+
|
|
21
|
+
def self.from_store(record)
|
|
22
|
+
if record[:version] == 1
|
|
23
|
+
self.new(
|
|
24
|
+
record[:version],
|
|
25
|
+
day: record[:day],
|
|
26
|
+
time: record[:time],
|
|
27
|
+
tags: record[:tags],
|
|
28
|
+
text: record[:text],
|
|
29
|
+
title: record[:title],
|
|
30
|
+
key: record[:key],
|
|
31
|
+
)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.keygen(day, time)
|
|
36
|
+
"%s-%s" % [day, time]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def self.generate(options={}, store)
|
|
40
|
+
options[:last_update_at] = store.read(:last_update_at)
|
|
41
|
+
|
|
42
|
+
# convert Arrays to dumb CSV
|
|
43
|
+
options.each do |(k, v)|
|
|
44
|
+
if v.is_a?(Array)
|
|
45
|
+
options[k] = v.join(', ')
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
TEMPLATE % options
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def initialize(version, options={})
|
|
53
|
+
@version = version || CURRENT_VERSION
|
|
54
|
+
|
|
55
|
+
@day = options[:day]
|
|
56
|
+
@time = options[:time]
|
|
57
|
+
@tags = options[:tags] || []
|
|
58
|
+
@text = options[:text]
|
|
59
|
+
@title = options[:title]
|
|
60
|
+
|
|
61
|
+
if options[:key].nil?
|
|
62
|
+
@key = Entry.keygen(day, time)
|
|
63
|
+
else
|
|
64
|
+
@key = options[:key]
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def formatted_text
|
|
69
|
+
RDiscount.new(text).to_html
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def to_hash
|
|
73
|
+
{
|
|
74
|
+
version: version,
|
|
75
|
+
day: day,
|
|
76
|
+
time: time,
|
|
77
|
+
tags: tags,
|
|
78
|
+
text: text,
|
|
79
|
+
title: '',
|
|
80
|
+
key: key,
|
|
81
|
+
}
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|