retter 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.travis.yml +1 -0
- data/README.md +54 -4
- data/bin/retter +2 -0
- data/lib/retter/command.rb +37 -41
- data/lib/retter/config.rb +94 -84
- data/lib/retter/entries.rb +93 -0
- data/lib/retter/entry.rb +46 -9
- data/lib/retter/generator/skel/images/orange/ic_li01.gif +0 -0
- data/lib/retter/generator/skel/layouts/article.html.haml +16 -3
- data/lib/retter/generator/skel/layouts/entries.html.haml +2 -2
- data/lib/retter/generator/skel/layouts/entry.html.haml +17 -3
- data/lib/retter/generator/skel/layouts/index.html.haml +14 -4
- data/lib/retter/generator/skel/stylesheets/base.css +1 -1
- data/lib/retter/generator/skel/stylesheets/orange.css +17 -2
- data/lib/retter/page/view_helper.rb +33 -0
- data/lib/retter/page.rb +86 -0
- data/lib/retter/pages/archive.rb +13 -0
- data/lib/retter/pages/article.rb +35 -0
- data/lib/retter/pages/entry.rb +28 -0
- data/lib/retter/pages/feed.rb +46 -0
- data/lib/retter/pages/index.rb +13 -0
- data/lib/retter/pages/profile.rb +13 -0
- data/lib/retter/pages.rb +40 -0
- data/lib/retter/preprint.rb +21 -0
- data/lib/retter/{stationery/renderer.rb → renderer.rb} +1 -1
- data/lib/retter/repository.rb +21 -0
- data/lib/retter/version.rb +1 -1
- data/lib/retter.rb +36 -3
- data/retter.gemspec +31 -0
- data/spec/command/callback_spec.rb +1 -1
- data/spec/command/commit_spec.rb +1 -1
- data/spec/command/edit_spec.rb +1 -1
- data/spec/command/invoke_after_spec.rb +2 -2
- data/spec/command/list_spec.rb +47 -0
- data/spec/command/open_spec.rb +1 -1
- data/spec/command/preview_spec.rb +1 -1
- data/spec/command/rebind_spec.rb +8 -8
- data/spec/spec_helper.rb +2 -0
- data/spec/support/stream_capture.rb +16 -0
- metadata +84 -39
- data/lib/retter/stationery/binder.rb +0 -150
- data/lib/retter/stationery/previewer.rb +0 -64
- data/lib/retter/stationery/view.rb +0 -68
- data/lib/retter/stationery.rb +0 -47
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -66,7 +66,7 @@ You can use `retter` command anywhere, If you set `$RETTER_HOME` variable.
|
|
66
66
|
|
67
67
|
作業ディレクトリにRetterfileがある場合は、そのディレクトリが`$RETTER_HOME`に指定されているものとして動作します。
|
68
68
|
|
69
|
-
### 記事を書く - Write an
|
69
|
+
### 記事を書く - Write an entry
|
70
70
|
|
71
71
|
`retter`コマンドは設定されているエディタを起動します。今のところMarkdown形式で記事を書くことができます。
|
72
72
|
|
@@ -151,15 +151,65 @@ To publish, use the git command. Or, upload the file to your server.
|
|
151
151
|
|
152
152
|
後述するコールバックを設定しておくことで、さらに手数を減らすことも可能です。
|
153
153
|
|
154
|
-
### 特定の日付の記事を編集する - Edit
|
154
|
+
### 特定の日付の記事を編集する - Edit entry (specific date).
|
155
155
|
|
156
156
|
昨日、明日、過去や未来の日付を指定して記事を編集・プレビューするには、 `--date` オプションを用います。
|
157
157
|
|
158
158
|
`--date` option is available in `edit` `preview` sub-command.
|
159
159
|
|
160
160
|
~~~~
|
161
|
-
retter
|
162
|
-
retter preview --date 20110101
|
161
|
+
retter --date 20110101 # 編集
|
162
|
+
retter preview --date 20110101 # プレビュー
|
163
|
+
~~~~
|
164
|
+
|
165
|
+
サブコマンドを明示する場合は、日付の指定は引数のように指定することもできます(`--date`が不要になります)。
|
166
|
+
|
167
|
+
~~~~
|
168
|
+
retter edit 20110101
|
169
|
+
retter preview 20110101
|
170
|
+
~~~~
|
171
|
+
|
172
|
+
日付は相対的に指定することができます。以下のような形式をサポートします。
|
173
|
+
|
174
|
+
~~~~
|
175
|
+
retter edit yesterday # 昨日
|
176
|
+
retter edit today # 今日
|
177
|
+
retter edit tommorow # 明日
|
178
|
+
|
179
|
+
retter edit '3 days ago' # 3日前
|
180
|
+
retter edit 3.days.ago # 3日前
|
181
|
+
retter edit 3.days.since # 3日後
|
182
|
+
retter edit 1.week.ago # 1週間前
|
183
|
+
retter edit 3.weeks.ago # 3週間前
|
184
|
+
retter edit 3.months.ago # 3カ月前
|
185
|
+
retter edit 3.years.ago # 3年前
|
186
|
+
~~~~
|
187
|
+
|
188
|
+
### 記事の一覧を出力する - Browse entries
|
189
|
+
|
190
|
+
これまでに書いた記事の一覧を出力することができます。すべての一覧を出力するため、`less`や`lv`、`grep`などで適宜フィルタしてください。
|
191
|
+
|
192
|
+
~~~~
|
193
|
+
retter list
|
194
|
+
[e0] 2011-10-12
|
195
|
+
記事ごとにPermlinkがつくようにした, retter 0.1.0
|
196
|
+
|
197
|
+
[e1] 2011-10-10
|
198
|
+
Rubyのトップレベルについて整理する
|
199
|
+
|
200
|
+
[e2] 2011-10-03
|
201
|
+
モジュール関数がprivateな理由
|
202
|
+
|
203
|
+
[e3] 2011-09-19
|
204
|
+
スタイルシートを追加してテーマを変えられるようにした
|
205
|
+
~~~~
|
206
|
+
|
207
|
+
日付の左側に表示されている文字列は、編集やプレビューの際の記事の指定に使うことができます。
|
208
|
+
|
209
|
+
~~~~
|
210
|
+
retter edit e3
|
211
|
+
retter preview e3
|
212
|
+
retter preview --key e3
|
163
213
|
~~~~
|
164
214
|
|
165
215
|
### コールバック - Callbacks
|
data/bin/retter
CHANGED
data/lib/retter/command.rb
CHANGED
@@ -1,47 +1,50 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
3
|
class Retter::Command < Thor
|
4
|
+
include Retter::Stationery
|
5
|
+
|
4
6
|
map '-v' => :version,
|
5
7
|
'-e' => :edit,
|
6
8
|
'-p' => :preview,
|
7
9
|
'-o' => :open,
|
8
10
|
'-r' => :rebind,
|
9
|
-
'-b' => :bind
|
10
|
-
'-h' => :home
|
11
|
+
'-b' => :bind
|
11
12
|
|
12
13
|
desc 'edit', 'Open $EDITOR. Write an article with Markdown.'
|
13
|
-
method_options date: :string, silent: :boolean
|
14
|
-
def edit
|
15
|
-
|
14
|
+
method_options date: :string, key: :string, silent: :boolean
|
15
|
+
def edit(date_or_index = options[:date] || options[:key])
|
16
|
+
entry = entries.detect_by_string(date_or_index)
|
17
|
+
|
18
|
+
system config.editor, entry.path
|
16
19
|
|
17
|
-
invoke_after :edit unless
|
20
|
+
invoke_after :edit unless silent?
|
18
21
|
end
|
19
22
|
|
20
23
|
default_task :edit
|
21
24
|
|
22
25
|
desc 'preview', 'Preview the draft article (browser will open).'
|
23
|
-
method_options date: :string
|
24
|
-
def preview
|
25
|
-
|
26
|
+
method_options date: :string, key: :string
|
27
|
+
def preview(date_or_index = options[:date] || options[:key])
|
28
|
+
entry = entries.detect_by_string(date_or_index)
|
26
29
|
|
27
|
-
|
28
|
-
|
30
|
+
preprint.print entry
|
31
|
+
|
32
|
+
Launchy.open preprint.path
|
29
33
|
end
|
30
34
|
|
31
35
|
desc 'open', 'Open your (static) site top page (browser will open).'
|
32
36
|
def open
|
33
|
-
Launchy.open
|
37
|
+
Launchy.open pages.index.path
|
34
38
|
end
|
35
39
|
|
36
40
|
desc 'rebind', 'Bind the draft article, re-generate all html pages.'
|
37
41
|
method_options silent: :boolean
|
38
42
|
def rebind
|
39
|
-
|
43
|
+
entries.commit_wip_entry!
|
40
44
|
|
41
|
-
|
42
|
-
binder.rebind!
|
45
|
+
pages.bind!
|
43
46
|
|
44
|
-
unless
|
47
|
+
unless silent?
|
45
48
|
invoke_after :bind
|
46
49
|
invoke_after :rebind
|
47
50
|
end
|
@@ -54,14 +57,21 @@ class Retter::Command < Thor
|
|
54
57
|
desc 'commit', "cd $RETTER_HOME && git add . && git commit -m 'Retter commit'"
|
55
58
|
method_options silent: :boolean
|
56
59
|
def commit
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
+
repository.open do |git|
|
61
|
+
say git.add(config.retter_home), :green
|
62
|
+
say git.commit_all('Retter commit'), :green
|
63
|
+
end
|
60
64
|
|
61
|
-
|
62
|
-
|
65
|
+
invoke_after :commit unless silent?
|
66
|
+
end
|
63
67
|
|
64
|
-
|
68
|
+
desc 'list', 'List retters'
|
69
|
+
def list
|
70
|
+
entries.each_with_index do |entry, n|
|
71
|
+
say "[e#{n}] #{entry.date}"
|
72
|
+
say " #{entry.articles.map(&:title).join(', ')}"
|
73
|
+
say
|
74
|
+
end
|
65
75
|
end
|
66
76
|
|
67
77
|
desc 'home', 'Open a new shell in $RETTER_HOME'
|
@@ -81,6 +91,9 @@ class Retter::Command < Thor
|
|
81
91
|
desc 'new', 'Create a new site'
|
82
92
|
def new; end
|
83
93
|
|
94
|
+
desc 'gen', 'Generate initial files'
|
95
|
+
def gen; end
|
96
|
+
|
84
97
|
desc 'usage', 'Show usage.'
|
85
98
|
def usage
|
86
99
|
say Retter::Command.usage, :green
|
@@ -93,25 +106,8 @@ class Retter::Command < Thor
|
|
93
106
|
|
94
107
|
private
|
95
108
|
|
96
|
-
def
|
97
|
-
|
98
|
-
config.retter_file(Date.parse(options[:date]))
|
99
|
-
else
|
100
|
-
todays_file = config.retter_file(Date.today)
|
101
|
-
todays_file.exist? ? todays_file : config.wip_file
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
def detected_date
|
106
|
-
options[:date] ? Date.parse(options[:date]) : Date.today
|
107
|
-
end
|
108
|
-
|
109
|
-
def config
|
110
|
-
@retter_config ||= Retter::Config.new(ENV)
|
111
|
-
rescue Retter::EnvError
|
112
|
-
say 'Set $RETTER_HOME and $EDITOR, first.', :red
|
113
|
-
say Retter::Command.usage, :green
|
114
|
-
exit 1
|
109
|
+
def silent?
|
110
|
+
!options[:silent].nil?
|
115
111
|
end
|
116
112
|
|
117
113
|
def invoke_after(name)
|
data/lib/retter/config.rb
CHANGED
@@ -1,102 +1,112 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
:editor,
|
6
|
-
:shell,
|
7
|
-
:title,
|
8
|
-
:description,
|
9
|
-
:url,
|
10
|
-
:author,
|
11
|
-
:retters_dir,
|
12
|
-
:wip_file,
|
13
|
-
:layouts_dir,
|
14
|
-
:layout_file,
|
15
|
-
:profile_layout_file,
|
16
|
-
:entry_layout_file,
|
17
|
-
:article_layout_file,
|
18
|
-
:entries_layout_file,
|
19
|
-
:index_layout_file,
|
20
|
-
:entries_dir,
|
21
|
-
:profile_file,
|
22
|
-
:index_file,
|
23
|
-
:entries_file,
|
24
|
-
:feed_file
|
25
|
-
]
|
3
|
+
module Retter
|
4
|
+
class EnvError < RuntimeError; end
|
26
5
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
6
|
+
class Config
|
7
|
+
ATTRIBUTES = [
|
8
|
+
:editor,
|
9
|
+
:shell,
|
10
|
+
:title,
|
11
|
+
:description,
|
12
|
+
:url,
|
13
|
+
:author,
|
14
|
+
:retters_dir,
|
15
|
+
:wip_file,
|
16
|
+
:layouts_dir,
|
17
|
+
:layout_file,
|
18
|
+
:profile_layout_file,
|
19
|
+
:entry_layout_file,
|
20
|
+
:article_layout_file,
|
21
|
+
:entries_layout_file,
|
22
|
+
:index_layout_file,
|
23
|
+
:entries_dir,
|
24
|
+
:profile_file,
|
25
|
+
:index_file,
|
26
|
+
:entries_file,
|
27
|
+
:feed_file
|
28
|
+
]
|
34
29
|
|
35
|
-
|
30
|
+
ATTRIBUTES.each do |att|
|
31
|
+
class_eval <<-EOM
|
32
|
+
def #{att}(val = nil)
|
33
|
+
val ? @options[:#{att}] = val : @options[:#{att}]
|
34
|
+
end
|
35
|
+
EOM
|
36
|
+
end
|
36
37
|
|
37
|
-
|
38
|
-
@env, @options = env, {}
|
39
|
-
@after_callbacks = {}
|
38
|
+
attr_reader :retter_home
|
40
39
|
|
41
|
-
|
42
|
-
|
40
|
+
def initialize(env)
|
41
|
+
@env, @options = env, {}
|
42
|
+
@after_callbacks = {}
|
43
43
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
44
|
+
detect_retter_home
|
45
|
+
unless env.values_at('EDITOR', 'RETTER_HOME').all?
|
46
|
+
raise Retter::EnvError, 'Set $RETTER_HOME and $EDITOR, first.'
|
47
|
+
end
|
48
48
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
profile_layout_file layouts_dir.join('profile.html.haml')
|
58
|
-
entry_layout_file layouts_dir.join('entry.html.haml')
|
59
|
-
article_layout_file layouts_dir.join('article.html.haml')
|
60
|
-
entries_layout_file layouts_dir.join('entries.html.haml')
|
61
|
-
index_layout_file layouts_dir.join('index.html.haml')
|
62
|
-
entries_dir retter_home.join('entries/')
|
63
|
-
profile_file retter_home.join('profile.html')
|
64
|
-
index_file retter_home.join('index.html')
|
65
|
-
entries_file retter_home.join('entries.html')
|
66
|
-
feed_file retter_home.join('entries.rss')
|
67
|
-
end
|
49
|
+
@retter_home = Pathname.new(@env['RETTER_HOME'])
|
50
|
+
load_defaults
|
51
|
+
load_retterfile_if_exists
|
52
|
+
rescue Retter::EnvError
|
53
|
+
$stderr.puts 'Set $RETTER_HOME and $EDITOR, first.'
|
54
|
+
say Retter::Command.usage, :green
|
55
|
+
exit 1
|
56
|
+
end
|
68
57
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
58
|
+
def load_defaults
|
59
|
+
editor @env['EDITOR']
|
60
|
+
shell @env['SHELL']
|
61
|
+
url 'http://example.com'
|
62
|
+
retters_dir retter_home.join('retters/')
|
63
|
+
wip_file retters_dir.join('today.md')
|
64
|
+
layouts_dir retter_home.join('layouts/')
|
65
|
+
layout_file layouts_dir.join('retter.html.haml')
|
66
|
+
profile_layout_file layouts_dir.join('profile.html.haml')
|
67
|
+
entry_layout_file layouts_dir.join('entry.html.haml')
|
68
|
+
article_layout_file layouts_dir.join('article.html.haml')
|
69
|
+
entries_layout_file layouts_dir.join('entries.html.haml')
|
70
|
+
index_layout_file layouts_dir.join('index.html.haml')
|
71
|
+
entries_dir retter_home.join('entries/')
|
72
|
+
profile_file retter_home.join('profile.html')
|
73
|
+
index_file retter_home.join('index.html')
|
74
|
+
entries_file retter_home.join('entries.html')
|
75
|
+
feed_file retter_home.join('entries.rss')
|
76
|
+
end
|
73
77
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
+
def load_retterfile_if_exists
|
79
|
+
retterfile = retter_home.join('Retterfile')
|
80
|
+
instance_eval retterfile.read, retterfile.to_s if retterfile.exist?
|
81
|
+
end
|
78
82
|
|
79
|
-
|
80
|
-
|
81
|
-
|
83
|
+
def detect_retter_home
|
84
|
+
# TODO こういうの上のディレクトリも見て判断するのを何か参考にして書く
|
85
|
+
@env['RETTER_HOME'] = Dir.pwd if File.exist? 'Retterfile'
|
86
|
+
end
|
82
87
|
|
83
|
-
|
84
|
-
|
85
|
-
|
88
|
+
def retter_file(date)
|
89
|
+
retters_dir.join(date ? date.strftime("%Y%m%d.md") : "today.md")
|
90
|
+
end
|
86
91
|
|
87
|
-
|
88
|
-
|
89
|
-
|
92
|
+
def entry_file(date)
|
93
|
+
entries_dir.join date.strftime('%Y%m%d.html')
|
94
|
+
end
|
90
95
|
|
91
|
-
|
92
|
-
|
93
|
-
|
96
|
+
def entry_dir(date)
|
97
|
+
entries_dir.join date.strftime('%Y%m%d')
|
98
|
+
end
|
94
99
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
+
def self.delegatables
|
101
|
+
ATTRIBUTES + [:retter_file, :entry_file, :entry_dir]
|
102
|
+
end
|
103
|
+
|
104
|
+
def after(name, sym = nil, &block)
|
105
|
+
if callback = sym || block
|
106
|
+
@after_callbacks[name] = callback
|
107
|
+
else
|
108
|
+
@after_callbacks[name]
|
109
|
+
end
|
100
110
|
end
|
101
111
|
end
|
102
112
|
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'active_support/core_ext/object'
|
4
|
+
|
5
|
+
module Retter
|
6
|
+
class Entries < Array
|
7
|
+
include Retter::Stationery
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
load_entries config.retters_dir
|
11
|
+
end
|
12
|
+
|
13
|
+
def detect_by_string(str)
|
14
|
+
case str
|
15
|
+
when nil, ''
|
16
|
+
detect_by_today or wip_entry
|
17
|
+
when /^e([0-9]+)$/
|
18
|
+
index = $1.to_i
|
19
|
+
self[index] or wip_entry
|
20
|
+
else
|
21
|
+
date = parse_date_string(str)
|
22
|
+
detect_by_date(date) || wip_entry(date)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def detect_by_today
|
27
|
+
detect_by_date(Date.today)
|
28
|
+
end
|
29
|
+
|
30
|
+
def detect_by_date(date)
|
31
|
+
detect {|e| e.date == date }
|
32
|
+
end
|
33
|
+
|
34
|
+
def parse_date_string(date_str)
|
35
|
+
case date_str
|
36
|
+
when /^yesterday$/i then 1.day.ago
|
37
|
+
when /^today$/i then 0.day.ago
|
38
|
+
when /^tomorrow$/i then 1.day.since
|
39
|
+
when /^[0-9]+[\.\s](?:days?|weeks?|months?|years?)[\.\s](?:ago|since)$/i
|
40
|
+
eval(date_str.gsub(/\s+/, '.')).to_date
|
41
|
+
else
|
42
|
+
Date.parse(date_str)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def wip_entry(date = nil)
|
47
|
+
wip_file = config.retter_file(date)
|
48
|
+
wip_date = date || Date.today
|
49
|
+
wip_body = wip_file.exist? ? wip_file.read : ''
|
50
|
+
|
51
|
+
Retter::Entry.new date: wip_date, body: markupper.render(wip_body), pathname: wip_file
|
52
|
+
end
|
53
|
+
|
54
|
+
def commit_wip_entry!
|
55
|
+
if config.wip_file.exist?
|
56
|
+
copy = config.wip_file.read
|
57
|
+
config.retter_file(Date.today).open('a') {|f| f.puts copy }
|
58
|
+
config.wip_file.unlink
|
59
|
+
end
|
60
|
+
|
61
|
+
Retter.reset_entries!
|
62
|
+
end
|
63
|
+
|
64
|
+
def load_entries(path)
|
65
|
+
date_files = find_markup_files(path).map {|file|
|
66
|
+
date_str = file.basename('.*').to_s
|
67
|
+
[Date.parse(date_str), file]
|
68
|
+
}.sort_by(&:first)
|
69
|
+
|
70
|
+
date_files.reverse_each {|date, file|
|
71
|
+
self << Retter::Entry.new(date: date, body: markupper.render(file.read))
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
def find_markup_files(path)
|
76
|
+
path = Pathname.new(path).realpath
|
77
|
+
Dir.open(path, &:to_a).grep(/^\d{4}(?:0[1-9]|1[012])(?:0[1-9]|[12][0-9]|3[01])\.(md)$/).map {|f| path.join f }
|
78
|
+
end
|
79
|
+
|
80
|
+
def markupper
|
81
|
+
@markupper ||= ::Redcarpet::Markdown.new(
|
82
|
+
Renderer,
|
83
|
+
autolink: true,
|
84
|
+
space_after_headers: true,
|
85
|
+
fenced_code_blocks: true,
|
86
|
+
strikethrough: true,
|
87
|
+
superscript: true,
|
88
|
+
fenced_code_blocks: true,
|
89
|
+
tables: true
|
90
|
+
)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
data/lib/retter/entry.rb
CHANGED
@@ -4,25 +4,67 @@ class Retter::Entry
|
|
4
4
|
class Article
|
5
5
|
attr_accessor :entry, :id, :title, :body
|
6
6
|
|
7
|
+
def initialize(attrs = {})
|
8
|
+
@id, @entry, @title, @body = attrs.values_at(:id, :entry, :title, :body)
|
9
|
+
end
|
10
|
+
|
7
11
|
def to_s
|
8
12
|
body
|
9
13
|
end
|
14
|
+
|
15
|
+
def next
|
16
|
+
articles[index.next] || (entry.next && entry.next.articles.first)
|
17
|
+
end
|
18
|
+
|
19
|
+
def prev
|
20
|
+
index.pred < 0 ? (entry.prev && entry.prev.articles.last) : articles[index.pred]
|
21
|
+
end
|
22
|
+
|
23
|
+
def index
|
24
|
+
articles.index(self)
|
25
|
+
end
|
26
|
+
|
27
|
+
def articles
|
28
|
+
@articles ||= entry.articles
|
29
|
+
end
|
10
30
|
end
|
11
31
|
|
32
|
+
include Retter::Stationery
|
33
|
+
|
12
34
|
attr_accessor :date, :lede, :body, :articles
|
35
|
+
attr_reader :pathname
|
13
36
|
|
14
37
|
def initialize(attrs={})
|
15
38
|
@date, @body = attrs.values_at(:date, :body)
|
16
39
|
|
40
|
+
pathname_by_date = Retter.config.retters_dir.join(date.strftime('%Y%m%d.md'))
|
41
|
+
@pathname = attrs[:pathname] || pathname_by_date
|
42
|
+
|
17
43
|
attach_titles
|
18
44
|
extract_articles
|
19
45
|
load_lede
|
20
46
|
end
|
21
47
|
|
48
|
+
def path
|
49
|
+
pathname.to_s
|
50
|
+
end
|
51
|
+
|
22
52
|
def to_s
|
23
53
|
body
|
24
54
|
end
|
25
55
|
|
56
|
+
def next
|
57
|
+
entries[index.next]
|
58
|
+
end
|
59
|
+
|
60
|
+
def prev
|
61
|
+
entries[index.pred] unless index.pred < 0
|
62
|
+
end
|
63
|
+
|
64
|
+
def index
|
65
|
+
entries.index(self) || 0
|
66
|
+
end
|
67
|
+
|
26
68
|
private
|
27
69
|
|
28
70
|
def body_elements
|
@@ -41,16 +83,11 @@ class Retter::Entry
|
|
41
83
|
def extract_articles
|
42
84
|
@articles = body_elements.search('body > *').each_with_object([]) {|c, r|
|
43
85
|
if c.name == 'h1'
|
44
|
-
|
45
|
-
article.entry = self
|
46
|
-
article.id = c.attr('id')
|
47
|
-
article.title = c.text
|
48
|
-
article.body = ''
|
49
|
-
r << article
|
86
|
+
r << Article.new(entry: self, id: c.attr('id'), title: c.text, body: '')
|
50
87
|
else
|
51
|
-
|
52
|
-
next if article.nil?
|
88
|
+
next if r.empty?
|
53
89
|
|
90
|
+
article = r.last
|
54
91
|
article.body += c.to_s
|
55
92
|
end
|
56
93
|
} || []
|
@@ -59,7 +96,7 @@ class Retter::Entry
|
|
59
96
|
def load_lede
|
60
97
|
@lede = body_elements.search('body > *').each_with_object('') {|c, r|
|
61
98
|
break r if c.name == 'h1'
|
62
|
-
r<< c.to_s
|
99
|
+
r << c.to_s
|
63
100
|
}
|
64
101
|
end
|
65
102
|
end
|
Binary file
|
@@ -1,6 +1,19 @@
|
|
1
|
-
%article
|
1
|
+
%article.autopagerize_page_element
|
2
2
|
%h1.date
|
3
|
-
%a{href: entry_path(entry
|
3
|
+
%a{href: entry_path(entry)}= entry.date
|
4
|
+
|
4
5
|
%h1{id: article.id}
|
5
|
-
%a{href: article_path(
|
6
|
+
%a{href: article_path(article)}= article.title
|
7
|
+
|
6
8
|
= article
|
9
|
+
|
10
|
+
.nav
|
11
|
+
.prev
|
12
|
+
- if prev_article = article.prev
|
13
|
+
%link{href: article_path(prev_article), rel: :prev}
|
14
|
+
|
15
|
+
.next
|
16
|
+
- if next_article = article.next
|
17
|
+
%link{href: article_path(next_article), rel: :next}
|
18
|
+
|
19
|
+
.autopagerize_insert_before
|
@@ -2,8 +2,8 @@
|
|
2
2
|
%ul#entries
|
3
3
|
- entries.each do |entry|
|
4
4
|
%li
|
5
|
-
%a.entry{href: entry_path(entry
|
5
|
+
%a.entry{href: entry_path(entry)}= entry.date
|
6
6
|
%ul.titles
|
7
7
|
- entry.articles.each do |article|
|
8
8
|
%li
|
9
|
-
%a.title{href: article_path(
|
9
|
+
%a.title{href: article_path(article)}= article.title
|
@@ -1,9 +1,23 @@
|
|
1
|
-
%article
|
1
|
+
%article.autopagerize_page_element
|
2
2
|
%h1.date
|
3
|
-
%a{href: entry_path(entry
|
3
|
+
%a{href: entry_path(entry)}= entry.date
|
4
|
+
|
4
5
|
- unless entry.lede.empty?
|
5
6
|
= entry.lede
|
7
|
+
|
6
8
|
- entry.articles.each do |article|
|
7
9
|
%h1{id: article.id}
|
8
|
-
%a{href: article_path(
|
10
|
+
%a{href: article_path(article)}= article.title
|
11
|
+
|
9
12
|
= article
|
13
|
+
|
14
|
+
.nav
|
15
|
+
.prev
|
16
|
+
- if prev_entry = entry.prev
|
17
|
+
%link{href: entry_path(prev_entry), rel: :prev}
|
18
|
+
|
19
|
+
.next
|
20
|
+
- if next_entry = entry.next
|
21
|
+
%link{href: entry_path(next_entry), rel: :next}
|
22
|
+
|
23
|
+
.autopagerize_insert_before
|