retter 0.2.0 → 0.2.1

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.
@@ -1,17 +1,25 @@
1
1
  # coding: utf-8
2
2
 
3
- require 'active_support/core_ext/object'
3
+ require 'active_support/cache'
4
4
  require 'digest/sha1'
5
5
  require 'redcarpet'
6
+ require 'chronic'
6
7
 
7
8
  module Retter
8
9
  class EntryLoadError < RetterError; end
9
10
 
10
11
  class Entries < Array
11
- include Retter::Stationery
12
+ include Stationery
13
+ extend Configurable
14
+
15
+ configurable :renderer, :retters_dir, :wip_file
12
16
 
13
17
  def initialize
14
- load_entries config.retters_dir
18
+ load_entries retters_dir
19
+ end
20
+
21
+ def retter_file(date)
22
+ retters_dir.join(date ? date.strftime('%Y%m%d.md') : 'today.md')
15
23
  end
16
24
 
17
25
  def detect_by_string(str)
@@ -36,10 +44,10 @@ module Retter
36
44
 
37
45
  def detect_by_filename(filename)
38
46
  case filename
39
- when config.wip_file.basename.to_s
47
+ when wip_file.basename.to_path
40
48
  wip_entry
41
49
  else
42
- detect {|e| e.pathname.basename.to_s == filename }
50
+ detect {|e| e.pathname.basename.to_path == filename }
43
51
  end
44
52
  end
45
53
 
@@ -52,43 +60,37 @@ module Retter
52
60
  end
53
61
 
54
62
  def parse_date_string(date_str)
55
- case date_str
56
- when /^yesterday$/i then 1.day.ago
57
- when /^today$/i then 0.day.ago
58
- when /^tomorrow$/i then 1.day.since
59
- when /^[0-9]+[\.\s](?:days?|weeks?|months?|years?)[\.\s](?:ago|since)$/i
60
- eval(date_str.gsub(/\s+/, '.')).to_date
61
- else
62
- Date.parse(date_str)
63
- end
63
+ normalized = date_str.gsub(/\./, ' ')
64
+
65
+ (Chronic.parse(normalized) || Date.parse(normalized)).to_date
64
66
  end
65
67
 
66
68
  def wip_entry(date = nil)
67
- wip_file = config.retter_file(date)
68
- wip_date = date || Date.today
69
- wip_body = wip_file.exist? ? wip_file.read : ''
69
+ file = retter_file(date)
70
+ date = date || Date.today
71
+ body = file.exist? ? file.read : ''
70
72
 
71
- Retter::Entry.new date: wip_date, body: rendered_body(wip_body), pathname: wip_file
73
+ Entry.new date: date, body: rendered_body(body), pathname: file
72
74
  end
73
75
 
74
76
  def commit_wip_entry!
75
- if config.wip_file.exist?
76
- copy = config.wip_file.read
77
- config.retter_file(Date.today).open('a') {|f| f.puts copy }
78
- config.wip_file.unlink
77
+ if wip_file.exist?
78
+ copy = wip_file.read
79
+ retter_file(Date.today).open('a') {|f| f.puts copy }
80
+ wip_file.unlink
79
81
  end
80
82
 
81
- Retter.reset_entries!
83
+ Retter.reset!
82
84
  end
83
85
 
84
86
  def load_entries(path)
85
87
  date_files = find_markup_files(path).map {|file|
86
- date_str = file.basename('.*').to_s
88
+ date_str = file.basename('.*').to_path
87
89
  [Date.parse(date_str), file]
88
90
  }.sort_by(&:first)
89
91
 
90
92
  date_files.reverse_each {|date, file|
91
- self << Retter::Entry.new(date: date, body: rendered_body(file.read))
93
+ self << Entry.new(date: date, body: rendered_body(file.read))
92
94
  }
93
95
  end
94
96
 
@@ -102,7 +104,7 @@ module Retter
102
104
 
103
105
  config.cache.fetch(key) do
104
106
  Redcarpet::Markdown.new(
105
- config.renderer,
107
+ renderer,
106
108
  autolink: true,
107
109
  space_after_headers: true,
108
110
  fenced_code_blocks: true,
data/lib/retter/entry.rb CHANGED
@@ -2,103 +2,105 @@
2
2
 
3
3
  require 'nokogiri'
4
4
 
5
- class Retter::Entry
6
- class Article
7
- attr_accessor :entry, :id, :title, :body
5
+ module Retter
6
+ class Entry
7
+ class Article
8
+ attr_accessor :entry, :id, :title, :body
8
9
 
9
- def initialize(attrs = {})
10
- @id, @entry, @title, @body = attrs.values_at(:id, :entry, :title, :body)
11
- end
10
+ def initialize(attrs = {})
11
+ @id, @entry, @title, @body = attrs.values_at(:id, :entry, :title, :body)
12
+ end
12
13
 
13
- def to_s
14
- body
15
- end
14
+ def to_s
15
+ body
16
+ end
16
17
 
17
- def next
18
- articles[index.next] || (entry.next && entry.next.articles.first)
19
- end
18
+ def next
19
+ articles[index.next] || (entry.next && entry.next.articles.first)
20
+ end
20
21
 
21
- def prev
22
- index.pred < 0 ? (entry.prev && entry.prev.articles.last) : articles[index.pred]
23
- end
22
+ def prev
23
+ index.pred < 0 ? (entry.prev && entry.prev.articles.last) : articles[index.pred]
24
+ end
24
25
 
25
- def index
26
- articles.index(self)
27
- end
26
+ def index
27
+ articles.index(self)
28
+ end
28
29
 
29
- def articles
30
- @articles ||= entry.articles
30
+ def articles
31
+ @articles ||= entry.articles
32
+ end
31
33
  end
32
- end
33
34
 
34
- include Retter::Stationery
35
+ include Stationery
35
36
 
36
- attr_accessor :date, :lede, :body, :articles
37
- attr_reader :pathname
37
+ attr_accessor :date, :lede, :body, :articles
38
+ attr_reader :pathname
38
39
 
39
- def initialize(attrs={})
40
- @date, @body = attrs.values_at(:date, :body)
40
+ def initialize(attrs={})
41
+ @date, @body = attrs.values_at(:date, :body)
41
42
 
42
- pathname_by_date = Retter.config.retters_dir.join(date.strftime('%Y%m%d.md'))
43
- @pathname = attrs[:pathname] || pathname_by_date
43
+ pathname_by_date = Entries.retters_dir.join(date.strftime('%Y%m%d.md'))
44
+ @pathname = attrs[:pathname] || pathname_by_date
44
45
 
45
- attach_titles
46
- extract_articles
47
- load_lede
48
- end
49
-
50
- def path
51
- pathname.to_s
52
- end
46
+ attach_titles
47
+ extract_articles
48
+ load_lede
49
+ end
53
50
 
54
- def to_s
55
- body
56
- end
51
+ def path
52
+ pathname.to_path
53
+ end
57
54
 
58
- def next
59
- entries[index.next]
60
- end
55
+ def to_s
56
+ body
57
+ end
61
58
 
62
- def prev
63
- entries[index.pred] unless index.pred < 0
64
- end
59
+ def next
60
+ entries[index.next]
61
+ end
65
62
 
66
- def index
67
- entries.index(self) || 0
68
- end
63
+ def prev
64
+ entries[index.pred] unless index.pred < 0
65
+ end
69
66
 
70
- private
67
+ def index
68
+ entries.index(self) || 0
69
+ end
71
70
 
72
- def body_elements
73
- Nokogiri::HTML(body)
74
- end
71
+ private
75
72
 
76
- def attach_titles
77
- html = body_elements
78
- html.search('//h1').each_with_index do |h1, seq|
79
- h1.set_attribute 'id', "a#{seq}"
73
+ def body_elements
74
+ Nokogiri::HTML(body)
80
75
  end
81
76
 
82
- @body = html.search('//body/*').to_s
83
- end
77
+ def attach_titles
78
+ html = body_elements
79
+ html.search('//h1').each_with_index do |h1, seq|
80
+ h1.set_attribute 'id', "a#{seq}"
81
+ end
84
82
 
85
- def extract_articles
86
- @articles = body_elements.search('body > *').each_with_object([]) {|c, r|
87
- if c.name == 'h1'
88
- r << Article.new(entry: self, id: c.attr('id'), title: c.text, body: '')
89
- else
90
- next if r.empty?
83
+ @body = html.search('//body/*').to_s
84
+ end
91
85
 
92
- article = r.last
93
- article.body += c.to_s
94
- end
95
- } || []
96
- end
86
+ def extract_articles
87
+ @articles = body_elements.search('body > *').each_with_object([]) {|c, r|
88
+ if c.name == 'h1'
89
+ r << Article.new(entry: self, id: c.attr('id'), title: c.text, body: '')
90
+ else
91
+ next if r.empty?
92
+
93
+ article = r.last
94
+ article.body += c.to_s
95
+ end
96
+ } || []
97
+ end
97
98
 
98
- def load_lede
99
- @lede = body_elements.search('body > *').each_with_object('') {|c, r|
100
- break r if c.name == 'h1'
101
- r << c.to_s
102
- }
99
+ def load_lede
100
+ @lede = body_elements.search('body > *').each_with_object('') {|c, r|
101
+ break r if c.name == 'h1'
102
+ r << c.to_s
103
+ }
104
+ end
103
105
  end
104
106
  end
@@ -7,23 +7,32 @@ description '<%= name %>'
7
7
  author '<%= ENV["USER"] %>'
8
8
  renderer Retter::Renderers::PygmentsRenderer
9
9
 
10
- ## Callbacks for retter sub-command: edit, rebind, commit
11
- ##
12
- ## Syntax:
13
- ## after [command], [invoke command or proc]
10
+ # Callbacks for retter sub-command: edit, rebind, commit
14
11
  #
15
- ## Using symbol example:
16
- # after :rebind, :commit
12
+ # Syntax:
13
+ # after [command], [invoke command or proc]
17
14
  #
18
- ## Using proc example:
19
- # after :commit do
20
- # if yes?("Deploy now? [yes/no]")
21
- # system "cd #{config.retter_home}"
22
- # system 'git push origin master'
23
- # end
24
- # end
15
+ # Using symbol example:
16
+ # after :rebind, :commit
25
17
  #
26
- # after :edit do
27
- # ident = ARGV.pop || 'today'
28
- # preview ident if yes?("Preview now? [yes/no]")
29
- # end
18
+ # Using proc example:
19
+ # after :commit do
20
+ # if yes?("Deploy now? [yes/no]")
21
+ # system "cd #{config.retter_home}"
22
+ # system 'git push origin master'
23
+ # end
24
+ # end
25
+ #
26
+ # after :edit do
27
+ # Retter.reset!
28
+ # ident = ARGV.pop || 'today'
29
+ #
30
+ # preview ident if yes?("Preview now? [yes/no]")
31
+ # end
32
+ #
33
+ # Skip binding:
34
+ # examples:
35
+ # allow_binding :none
36
+ # allow_binding [:profile, :entries, :feed]
37
+ #
38
+ # Anyway index page will be bound.
@@ -1,14 +1,14 @@
1
1
  # coding: utf-8
2
2
 
3
- module Retter::Page
4
- module ViewHelper
5
- include Retter::Stationery
3
+ module Retter
4
+ module Page::ViewHelper
5
+ include Stationery
6
6
 
7
7
  def entry_path(*args)
8
8
  case args.first
9
9
  when Date, Time
10
10
  entry_path_by_date(*args)
11
- when Retter::Entry
11
+ when Entry
12
12
  entry_path_by_entry(args.first)
13
13
  else
14
14
  raise TypeError, "wrong argument type #{args.first.class} (expected Date, Time or Retter::Entry)"
@@ -19,7 +19,7 @@ module Retter::Page
19
19
  case args.first
20
20
  when Date, Time
21
21
  article_path_by_date_and_id(*args)
22
- when Retter::Entry::Article
22
+ when Entry::Article
23
23
  article_path_by_article(args.first)
24
24
  else
25
25
  raise TypeError, "wrong argument type #{args.first.class} (expected Date, Time or Retter::Entry::Article)"
data/lib/retter/page.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # coding: utf-8
2
2
 
3
+ require 'tilt'
3
4
  require 'haml'
4
5
  require 'nokogiri'
5
6
 
@@ -7,7 +8,7 @@ module Retter
7
8
  module Page
8
9
  require 'retter/page/view_helper'
9
10
 
10
- include Retter::Stationery
11
+ include Stationery
11
12
 
12
13
  attr_reader :path_prefix, :title
13
14
 
@@ -17,10 +18,10 @@ module Retter
17
18
  end
18
19
 
19
20
  def print
20
- part = Haml::Engine.new(
21
- part_layout_pathname.read,
21
+ part = Tilt.new(
22
+ part_layout_pathname.to_path,
22
23
  ugly: true,
23
- filename: part_layout_pathname.to_s
24
+ filename: part_layout_pathname.to_path
24
25
  ).render(view_scope)
25
26
 
26
27
  print_with_layout part
@@ -31,7 +32,7 @@ module Retter
31
32
  end
32
33
 
33
34
  def path
34
- pathname.to_s
35
+ pathname.to_path
35
36
  end
36
37
 
37
38
  def part_layout_pathname
@@ -48,7 +49,8 @@ module Retter
48
49
  end
49
50
 
50
51
  def layout_renderer
51
- @layout_renderer ||= Haml::Engine.new(config.layout_file.read, ugly: true, filename: config.layout_file.to_s)
52
+ layout_file = Pages.layout_file.to_path
53
+ @layout_renderer ||= Tilt.new(layout_file, ugly: true, filename: layout_file)
52
54
  end
53
55
 
54
56
  def fix_path(html, prefix='./')
@@ -1,39 +1,41 @@
1
1
  # coding: utf-8
2
2
 
3
- class Retter::Pages::Article
4
- include Retter::Page
5
-
6
- attr_reader :article
7
-
8
- def initialize(article)
9
- super()
10
- @path_prefix = '../../'
11
- @article = article
12
- @title = "#{article.title} - #{config.title}"
13
- end
14
-
15
- def pathname
16
- config.entry_dir(article.entry.date).join("#{article.id}.html")
17
- end
18
-
19
- def part_layout_pathname
20
- config.article_layout_file
21
- end
22
-
23
- def print
24
- options = {entry: article.entry, article: article}
25
- part = Haml::Engine.new(
26
- part_layout_pathname.read,
27
- ugly: true,
28
- filename: part_layout_pathname.to_s
29
- ).render(view_scope, options)
30
-
31
- mkdir
32
- print_with_layout part
33
- end
34
-
35
- def mkdir
36
- entry_dir = config.entry_dir(article.entry.date)
37
- entry_dir.mkdir unless entry_dir.directory?
3
+ module Retter
4
+ class Pages::Article
5
+ include Page
6
+
7
+ attr_reader :article
8
+
9
+ def initialize(article)
10
+ super()
11
+ @path_prefix = '../../'
12
+ @article = article
13
+ @title = "#{article.title} - #{config.title}"
14
+ end
15
+
16
+ def pathname
17
+ Pages.entry_dir(article.entry.date).join("#{article.id}.html")
18
+ end
19
+
20
+ def part_layout_pathname
21
+ Pages.find_layout_path('article')
22
+ end
23
+
24
+ def print
25
+ options = {entry: article.entry, article: article}
26
+ part = Tilt.new(
27
+ part_layout_pathname.to_path,
28
+ ugly: true,
29
+ filename: part_layout_pathname.to_path
30
+ ).render(view_scope, options)
31
+
32
+ mkdir
33
+ print_with_layout part
34
+ end
35
+
36
+ def mkdir
37
+ entry_dir = Pages.entry_dir(article.entry.date)
38
+ entry_dir.mkdir unless entry_dir.directory?
39
+ end
38
40
  end
39
41
  end
@@ -0,0 +1,15 @@
1
+ # coding: utf-8
2
+
3
+ module Retter
4
+ class Pages::Entries
5
+ include Page
6
+
7
+ def pathname
8
+ config.retter_home.join('entries.html')
9
+ end
10
+
11
+ def part_layout_pathname
12
+ Pages.find_layout_path('entries')
13
+ end
14
+ end
15
+ end
@@ -1,32 +1,35 @@
1
1
  # coding: utf-8
2
2
 
3
- class Retter::Pages::Entry
4
- include Retter::Page
3
+ module Retter
4
+ class Pages::Entry
5
+ include Page
5
6
 
6
- attr_reader :entry
7
+ attr_reader :entry
7
8
 
8
- def initialize(entry)
9
- super()
10
- @path_prefix = '../'
11
- @entry = entry
12
- @title = "#{entry.date} - #{config.title}"
13
- end
9
+ def initialize(entry)
10
+ super()
14
11
 
15
- def pathname
16
- config.entry_file(entry.date)
17
- end
12
+ @path_prefix = '../'
13
+ @entry = entry
14
+ @title = "#{entry.date} - #{config.title}"
15
+ end
18
16
 
19
- def part_layout_pathname
20
- config.entry_layout_file
21
- end
17
+ def pathname
18
+ Pages.entry_file(entry.date)
19
+ end
20
+
21
+ def part_layout_pathname
22
+ Pages.find_layout_path('entry')
23
+ end
22
24
 
23
- def print
24
- part = Haml::Engine.new(
25
- part_layout_pathname.read,
26
- ugly: true,
27
- filename: part_layout_pathname.to_s
28
- ).render(view_scope, entry: entry)
25
+ def print
26
+ part = Tilt.new(
27
+ part_layout_pathname.to_path,
28
+ ugly: true,
29
+ filename: part_layout_pathname.to_path
30
+ ).render(view_scope, entry: entry)
29
31
 
30
- print_with_layout part
32
+ print_with_layout part
33
+ end
31
34
  end
32
35
  end
@@ -3,45 +3,47 @@
3
3
  require 'builder'
4
4
  require 'uri'
5
5
 
6
- class Retter::Pages::Feed
7
- include Retter::Page
6
+ module Retter
7
+ class Pages::Feed
8
+ include Page
8
9
 
9
- def pathname
10
- config.feed_file
11
- end
10
+ def pathname
11
+ config.retter_home.join('entries.rss')
12
+ end
12
13
 
13
- def print
14
- pathname.open('w') {|f| f.puts rss }
15
- end
14
+ def print
15
+ pathname.open('w') {|f| f.puts rss }
16
+ end
16
17
 
17
- private
18
+ private
18
19
 
19
- def entry_url(date, id = nil)
20
- (URI.parse(config.url) + date.strftime('/entries/%Y%m%d.html')).to_s
21
- end
20
+ def entry_url(date, id = nil)
21
+ (URI.parse(config.url) + date.strftime('/entries/%Y%m%d.html')).to_s
22
+ end
22
23
 
23
- def rss
24
- xml = Builder::XmlMarkup.new
25
- xml.instruct!
26
- xml.rdf:RDF, :xmlns => 'http://purl.org/rss/1.0/',
27
- :'xmlns:rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
28
- :'xmlns:dc' => 'http://purl.org/dc/elements/1.1/',
29
- :'xml:lang' => 'ja' do
30
- xml.channel :'rdf:about' => config.url do
31
- xml.title config.title
32
- xml.link config.url
33
- xml.dc:date, entries.empty? ? nil : entries.first.date
34
- xml.description config.description
35
- xml.items { xml.rdf(:Seq) { entries.each {|e| xml.rdf:li, :'rdf:resource' => entry_url(e.date) } } }
36
- end
24
+ def rss
25
+ xml = Builder::XmlMarkup.new
26
+ xml.instruct!
27
+ xml.rdf:RDF, :xmlns => 'http://purl.org/rss/1.0/',
28
+ :'xmlns:rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
29
+ :'xmlns:dc' => 'http://purl.org/dc/elements/1.1/',
30
+ :'xml:lang' => 'ja' do
31
+ xml.channel :'rdf:about' => config.url do
32
+ xml.title config.title
33
+ xml.link config.url
34
+ xml.dc:date, entries.empty? ? nil : entries.first.date
35
+ xml.description config.description
36
+ xml.items { xml.rdf(:Seq) { entries.each {|e| xml.rdf:li, :'rdf:resource' => entry_url(e.date) } } }
37
+ end
37
38
 
38
- entries[0...20].each do |entry| # XXX hardcoding
39
- xml.item about: entry_url(entry.date) do
40
- xml.title entry.date.strftime('%Y/%m/%d')
41
- xml.description { xml.cdata! entry.body }
42
- xml.dc:date, entry.date
43
- xml.link entry_url(entry.date)
44
- xml.author config.author
39
+ entries[0...20].each do |entry| # XXX hardcoding
40
+ xml.item about: entry_url(entry.date) do
41
+ xml.title entry.date.strftime('%Y/%m/%d')
42
+ xml.description { xml.cdata! entry.body }
43
+ xml.dc:date, entry.date
44
+ xml.link entry_url(entry.date)
45
+ xml.author config.author
46
+ end
45
47
  end
46
48
  end
47
49
  end
@@ -1,13 +1,15 @@
1
1
  # coding: utf-8
2
2
 
3
- class Retter::Pages::Index
4
- include Retter::Page
3
+ module Retter
4
+ class Pages::Index
5
+ include Page
5
6
 
6
- def pathname
7
- config.index_file
8
- end
7
+ def pathname
8
+ config.retter_home.join('index.html')
9
+ end
9
10
 
10
- def part_layout_pathname
11
- config.index_layout_file
11
+ def part_layout_pathname
12
+ Pages.find_layout_path('index')
13
+ end
12
14
  end
13
15
  end