retter 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/.gitignore +1 -0
  2. data/.travis.yml +1 -0
  3. data/README.md +54 -4
  4. data/bin/retter +2 -0
  5. data/lib/retter/command.rb +37 -41
  6. data/lib/retter/config.rb +94 -84
  7. data/lib/retter/entries.rb +93 -0
  8. data/lib/retter/entry.rb +46 -9
  9. data/lib/retter/generator/skel/images/orange/ic_li01.gif +0 -0
  10. data/lib/retter/generator/skel/layouts/article.html.haml +16 -3
  11. data/lib/retter/generator/skel/layouts/entries.html.haml +2 -2
  12. data/lib/retter/generator/skel/layouts/entry.html.haml +17 -3
  13. data/lib/retter/generator/skel/layouts/index.html.haml +14 -4
  14. data/lib/retter/generator/skel/stylesheets/base.css +1 -1
  15. data/lib/retter/generator/skel/stylesheets/orange.css +17 -2
  16. data/lib/retter/page/view_helper.rb +33 -0
  17. data/lib/retter/page.rb +86 -0
  18. data/lib/retter/pages/archive.rb +13 -0
  19. data/lib/retter/pages/article.rb +35 -0
  20. data/lib/retter/pages/entry.rb +28 -0
  21. data/lib/retter/pages/feed.rb +46 -0
  22. data/lib/retter/pages/index.rb +13 -0
  23. data/lib/retter/pages/profile.rb +13 -0
  24. data/lib/retter/pages.rb +40 -0
  25. data/lib/retter/preprint.rb +21 -0
  26. data/lib/retter/{stationery/renderer.rb → renderer.rb} +1 -1
  27. data/lib/retter/repository.rb +21 -0
  28. data/lib/retter/version.rb +1 -1
  29. data/lib/retter.rb +36 -3
  30. data/retter.gemspec +31 -0
  31. data/spec/command/callback_spec.rb +1 -1
  32. data/spec/command/commit_spec.rb +1 -1
  33. data/spec/command/edit_spec.rb +1 -1
  34. data/spec/command/invoke_after_spec.rb +2 -2
  35. data/spec/command/list_spec.rb +47 -0
  36. data/spec/command/open_spec.rb +1 -1
  37. data/spec/command/preview_spec.rb +1 -1
  38. data/spec/command/rebind_spec.rb +8 -8
  39. data/spec/spec_helper.rb +2 -0
  40. data/spec/support/stream_capture.rb +16 -0
  41. metadata +84 -39
  42. data/lib/retter/stationery/binder.rb +0 -150
  43. data/lib/retter/stationery/previewer.rb +0 -64
  44. data/lib/retter/stationery/view.rb +0 -68
  45. data/lib/retter/stationery.rb +0 -47
@@ -1,11 +1,21 @@
1
- #entries
2
- - entries[0..5].each do |entry|
1
+ #entries.autopagerize_page_element
2
+ - recent_entries = entries[0..4]
3
+ - recent_entries.each do |entry|
3
4
  %article
4
5
  %h1.date
5
- %a{href: entry_path(entry.date)}= entry.date.strftime('%Y/%m/%d')
6
+ %a{href: entry_path(entry)}= entry.date
7
+
6
8
  - unless entry.lede.empty?
7
9
  = entry.lede
10
+
8
11
  - entry.articles.each do |article|
9
12
  %h1{id: article.id}
10
- %a{href: article_path(entry.date, article.id)}= article.title
13
+ %a{href: article_path(article)}= article.title
11
14
  = article
15
+
16
+ .nav
17
+ .next
18
+ - if next_entry = recent_entries.last.next
19
+ %link{href: entry_path(next_entry), rel: :next}
20
+
21
+ .autopagerize_insert_before
@@ -4,5 +4,5 @@ dl dd {
4
4
  }
5
5
 
6
6
  pre {
7
- overflow: scroll;
7
+ overflow: hidden;
8
8
  }
@@ -11,6 +11,7 @@ body {
11
11
  background: #EEE;
12
12
  background-image:url("../images/orange/bg_body.jpg");
13
13
  height: 100%;
14
+ line-height:1.4;
14
15
  }
15
16
 
16
17
  ul {
@@ -22,6 +23,10 @@ a {
22
23
  color: rgb(25,30,10);
23
24
  }
24
25
 
26
+ code{
27
+ padding:0 5px;
28
+ }
29
+
25
30
  #header {
26
31
  padding: 0;
27
32
  margin: 0;
@@ -84,6 +89,18 @@ article {
84
89
  position:relative;
85
90
  }
86
91
 
92
+ article ul li {
93
+ list-style-image:url("../images/orange/ic_li01.gif");
94
+ }
95
+
96
+ article p a {
97
+ color:#F30;
98
+ }
99
+
100
+ article p a:hover {
101
+ color:#F93;
102
+ }
103
+
87
104
  article .date {
88
105
  font-size: 1em;
89
106
  text-align: center;
@@ -91,7 +108,6 @@ article .date {
91
108
  padding:10px;
92
109
  width:100px;
93
110
  float:right;
94
-
95
111
  position:absolute;
96
112
  top:-24px;
97
113
  left:650px;
@@ -151,4 +167,3 @@ pre {
151
167
  #footer a:hover {
152
168
  color: #669;
153
169
  }
154
-
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+
3
+ module Retter::Page
4
+ module ViewHelper
5
+ include Retter::Stationery
6
+
7
+ def entry_path(*args)
8
+ case args.first
9
+ when Date, Time
10
+ date, id = *args
11
+ date.strftime('/entries/%Y%m%d.html') + (id ? "##{id}" : '')
12
+ when Retter::Entry
13
+ entry = args.first
14
+ entry_path(entry.date)
15
+ else
16
+ raise TypeError, "wrong argument type #{args.first.class} (expected Date, Time or Retter::Entry)"
17
+ end
18
+ end
19
+
20
+ def article_path(*args)
21
+ case args.first
22
+ when Date, Time
23
+ date, id = *args
24
+ date.strftime("/entries/%Y%m%d/#{id}.html")
25
+ when Retter::Entry::Article
26
+ article = args.first
27
+ article_path(article.entry.date, article.id)
28
+ else
29
+ raise TypeError, "wrong argument type #{args.first.class} (expected Date, Time or Retter::Entry::Article)"
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,86 @@
1
+ # coding: utf-8
2
+
3
+ module Retter
4
+ module Page
5
+ require 'retter/page/view_helper'
6
+
7
+ include Retter::Stationery
8
+
9
+ attr_reader :path_prefix, :title
10
+
11
+ def initialize
12
+ @path_prefix = './'
13
+ @title = config.title
14
+ end
15
+
16
+ def print
17
+ part = Haml::Engine.new(part_layout_pathname.read, ugly: true).render(view_scope)
18
+
19
+ print_with_layout part
20
+ end
21
+
22
+ def pathname
23
+ raise NotImplementedError
24
+ end
25
+
26
+ def path
27
+ pathname.to_s
28
+ end
29
+
30
+ def part_layout_pathname
31
+ raise NotImplementedError
32
+ end
33
+
34
+ private
35
+
36
+ def print_with_layout(content)
37
+ draft = layout_renderer.render(view_scope, content: content, title: title)
38
+ path_fixed = fix_path(draft, path_prefix)
39
+
40
+ pathname.open('w') {|f| f.puts path_fixed }
41
+ end
42
+
43
+ def layout_renderer
44
+ @layout_renderer ||= Haml::Engine.new(config.layout_file.read, ugly: true)
45
+ end
46
+
47
+ def fix_path(html, prefix='./')
48
+ elements = Nokogiri::HTML(html)
49
+
50
+ fix_href_path(fix_src_path(elements, prefix), prefix).to_s
51
+ end
52
+
53
+ def fix_src_path(elements, prefix = './')
54
+ elements.search("[src!=''][src!='']").each do |el|
55
+ src = el.attr('src').scan(/[^\.\/]{3}.*/).first
56
+ next if src =~ /^(?:http|https):\/\//
57
+
58
+ el.set_attribute 'src', [prefix, src].join
59
+ end
60
+
61
+ elements
62
+ end
63
+
64
+ def fix_href_path(elements, prefix = './')
65
+ elements.search("[href][href!='#']").each do |el|
66
+ href = el.attr('href')
67
+ next if href =~ /^(?:http|https):\/\//
68
+
69
+ if href == '/'
70
+ el.set_attribute 'href', [prefix, 'index.html'].join
71
+ else
72
+ el.set_attribute 'href', [prefix, href.scan(/[^\.\/]{3}.*/).first].join
73
+ end
74
+ end
75
+
76
+ elements
77
+ end
78
+
79
+ view_scope = Object.new
80
+ view_scope.extend ViewHelper
81
+
82
+ define_method :view_scope do
83
+ view_scope
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,13 @@
1
+ # coding: utf-8
2
+
3
+ class Retter::Pages::Archive
4
+ include Retter::Page
5
+
6
+ def pathname
7
+ config.entries_file
8
+ end
9
+
10
+ def part_layout_pathname
11
+ config.entries_layout_file
12
+ end
13
+ end
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
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(part_layout_pathname.read, ugly: true).render(view_scope, options)
26
+
27
+ mkdir
28
+ print_with_layout part
29
+ end
30
+
31
+ def mkdir
32
+ entry_dir = config.entry_dir(article.entry.date)
33
+ entry_dir.mkdir unless entry_dir.directory?
34
+ end
35
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+
3
+ class Retter::Pages::Entry
4
+ include Retter::Page
5
+
6
+ attr_reader :entry
7
+
8
+ def initialize(entry)
9
+ super()
10
+ @path_prefix = '../'
11
+ @entry = entry
12
+ @title = "#{entry.date} - #{config.title}"
13
+ end
14
+
15
+ def pathname
16
+ config.entry_file(entry.date)
17
+ end
18
+
19
+ def part_layout_pathname
20
+ config.entry_layout_file
21
+ end
22
+
23
+ def print
24
+ part = Haml::Engine.new(part_layout_pathname.read, ugly: true).render(view_scope, entry: entry)
25
+
26
+ print_with_layout part
27
+ end
28
+ end
@@ -0,0 +1,46 @@
1
+ # coding: utf-8
2
+
3
+ class Retter::Pages::Feed
4
+ include Retter::Page
5
+
6
+ def pathname
7
+ config.feed_file
8
+ end
9
+
10
+ def print
11
+ pathname.open('w') {|f| f.puts rss }
12
+ end
13
+
14
+ private
15
+
16
+ def entry_url(date, id = nil)
17
+ (URI.parse(config.url) + date.strftime('/entries/%Y%m%d.html')).to_s
18
+ end
19
+
20
+ def rss
21
+ xml = Builder::XmlMarkup.new
22
+ xml.instruct!
23
+ xml.rdf:RDF, :xmlns => 'http://purl.org/rss/1.0/',
24
+ :'xmlns:rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
25
+ :'xmlns:dc' => 'http://purl.org/dc/elements/1.1/',
26
+ :'xml:lang' => 'ja' do
27
+ xml.channel :'rdf:about' => config.url do
28
+ xml.title config.title
29
+ xml.link config.url
30
+ xml.dc:date, entries.empty? ? nil : entries.first.date
31
+ xml.description config.description
32
+ xml.items { xml.rdf(:Seq) { entries.each {|e| xml.rdf:li, :'rdf:resource' => entry_url(e.date) } } }
33
+ end
34
+
35
+ entries.each do |entry|
36
+ xml.item about: entry_url(entry.date) do
37
+ xml.title entry.date.strftime('%Y/%m/%d')
38
+ xml.description { xml.cdata! entry.body }
39
+ xml.dc:date, entry.date
40
+ xml.link entry_url(entry.date)
41
+ xml.author config.author
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,13 @@
1
+ # coding: utf-8
2
+
3
+ class Retter::Pages::Index
4
+ include Retter::Page
5
+
6
+ def pathname
7
+ config.index_file
8
+ end
9
+
10
+ def part_layout_pathname
11
+ config.index_layout_file
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # coding: utf-8
2
+
3
+ class Retter::Pages::Profile
4
+ include Retter::Page
5
+
6
+ def pathname
7
+ config.profile_file
8
+ end
9
+
10
+ def part_layout_pathname
11
+ config.profile_layout_file
12
+ end
13
+ end
@@ -0,0 +1,40 @@
1
+ # coding: utf-8
2
+
3
+ module Retter
4
+ class Pages
5
+ require 'retter/pages/index'
6
+ require 'retter/pages/profile'
7
+ require 'retter/pages/archive'
8
+ require 'retter/pages/feed'
9
+ require 'retter/pages/entry'
10
+ require 'retter/pages/article'
11
+
12
+ include Retter::Stationery
13
+
14
+ attr_reader :index, :profile, :archive, :feed, :singleton_pages
15
+
16
+ def initialize
17
+ @singleton_pages = [Index, Profile, Archive, Feed].map(&:new)
18
+ @index, @profile, @archive, @feed = *singleton_pages
19
+ end
20
+
21
+ def bind!
22
+ print_entries
23
+
24
+ singleton_pages.each(&:print)
25
+ end
26
+
27
+
28
+ def print_entries
29
+ entries.each do |entry|
30
+ entry_page = Entry.new(entry)
31
+ entry_page.print
32
+
33
+ entry.articles.each do |article|
34
+ article_page = Article.new(article)
35
+ article_page.print
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,21 @@
1
+ # coding: utf-8
2
+
3
+ module Retter
4
+ class Preprint
5
+ include Retter::Page
6
+
7
+ def pathname
8
+ config.retter_home.join '.preview.html'
9
+ end
10
+
11
+ def part_layout_pathname
12
+ config.entry_layout_file
13
+ end
14
+
15
+ def print(entry)
16
+ part = Haml::Engine.new(part_layout_pathname.read, ugly: true).render(view_scope, entry: entry)
17
+
18
+ print_with_layout part
19
+ end
20
+ end
21
+ end
@@ -1,6 +1,6 @@
1
1
  # coding: utf-8
2
2
 
3
- module Retter::Stationery
3
+ module Retter
4
4
  class Renderer < ::Redcarpet::Render::HTML
5
5
  def block_code(code, lang)
6
6
  ::CodeRay.scan(code, lang ? lang.intern : :plain).div
@@ -0,0 +1,21 @@
1
+ # coding: utf-8
2
+
3
+ module Retter
4
+ class Repository
5
+ include Retter::Stationery
6
+
7
+ def initialize
8
+ working_dir = config.retter_home.to_s
9
+ @repo = Grit::Repo.new(working_dir)
10
+ end
11
+
12
+ def open
13
+ pwd = Dir.pwd
14
+ Dir.chdir @repo.working_dir
15
+
16
+ yield @repo
17
+
18
+ Dir.chdir pwd
19
+ end
20
+ end
21
+ end
@@ -1,3 +1,3 @@
1
1
  module Retter
2
- VERSION = '0.1.0'
2
+ VERSION = '0.1.1'
3
3
  end
data/lib/retter.rb CHANGED
@@ -4,7 +4,34 @@ here = File.dirname(__FILE__)
4
4
  $LOAD_PATH.unshift here unless $LOAD_PATH.include?(here)
5
5
 
6
6
  module Retter
7
- class EnvError < RuntimeError; end
7
+ module Stationery
8
+ [:config, :entries, :preprint, :pages, :repository].each do |meth|
9
+ define_method meth do
10
+ Retter.send meth
11
+ end
12
+ end
13
+ end
14
+
15
+ class << self
16
+ def load_config(env)
17
+ @config = Config.new(env)
18
+ end
19
+
20
+ def config
21
+ @config
22
+ end
23
+
24
+ def reset_entries!
25
+ @entries = nil
26
+ end
27
+
28
+ singletons = [:entries, :preprint, :pages, :repository]
29
+ singletons.each do |sym|
30
+ define_method sym do
31
+ eval "@#{sym} ||= #{sym.capitalize}.new"
32
+ end
33
+ end
34
+ end
8
35
 
9
36
  autoload :Generator, 'retter/generator'
10
37
  end
@@ -22,8 +49,14 @@ require 'haml'
22
49
  require 'uri'
23
50
  require 'forwardable'
24
51
  require 'grit'
52
+
25
53
  require 'retter/version'
26
- require 'retter/entry'
27
54
  require 'retter/config'
28
- require 'retter/stationery'
55
+ require 'retter/renderer'
56
+ require 'retter/entry'
57
+ require 'retter/entries'
58
+ require 'retter/page'
59
+ require 'retter/pages'
60
+ require 'retter/preprint'
61
+ require 'retter/repository'
29
62
  require 'retter/command'
data/retter.gemspec CHANGED
@@ -11,6 +11,35 @@ Gem::Specification.new do |s|
11
11
  s.summary = %q{Flyweight diary workflow}
12
12
  s.description = %q{Flyweight diary workflow. ruby-1.9.2 or later is required.}
13
13
 
14
+
15
+ s.post_install_message = <<-EOM
16
+ **Important** Some features were added or updated.
17
+
18
+ * Article has Permlink in retter-0.1.0 or later.
19
+ If error occured, try overwrite templates by `retter gen $RETTER_HOME`. (overwrite layouts/*.html.haml)
20
+
21
+ * Relative date is now available in `--date` option.
22
+ Examples:
23
+ $ retter edit yesterday
24
+ $ retter edit today
25
+ $ retter edit tomorrow
26
+ $ retter preview 2.days.ago
27
+
28
+ * `--key` option is now available in edit (and preview).
29
+ Examples:
30
+ $ retter list
31
+ [e0] 2011-10-12 article3, article4
32
+ [e1] 2011-10-10 article1, article2
33
+ $ retter edit --key e0
34
+ ... or ...
35
+ $ retter edit e0
36
+
37
+ * Default date format has changed.
38
+ 2011/01/01 -> 2011-01-01
39
+
40
+ -- Thanks for flying Retter :-> --
41
+ EOM
42
+
14
43
  #s.rubyforge_project = "retter"
15
44
 
16
45
  s.files = `git ls-files`.split("\n")
@@ -27,6 +56,8 @@ Gem::Specification.new do |s|
27
56
  s.add_runtime_dependency 'haml', ['>= 3.1.3']
28
57
  s.add_runtime_dependency 'bundler', ['>= 1.0']
29
58
  s.add_runtime_dependency 'grit', ['>= 2.4.1']
59
+ s.add_runtime_dependency 'activesupport', ['>= 3.1.0']
60
+ s.add_runtime_dependency 'i18n', ['>= 0.6.0']
30
61
 
31
62
  s.add_development_dependency 'rake', ['>= 0.9.2']
32
63
  s.add_development_dependency 'ir_b', ['>= 1.4.0']
@@ -6,7 +6,7 @@ describe 'Retter::Command#callback', clean: :all do
6
6
  let(:command) { Retter::Command.new }
7
7
 
8
8
  before do
9
- command.stub!(:config) { retter_config }
9
+ Retter.stub!(:config) { retter_config }
10
10
 
11
11
  retter_config.after(:edit) { commit }
12
12
  command.should_receive(:commit).and_return(true)
@@ -11,7 +11,7 @@ describe 'Retter::Command#commit', clean: :all do
11
11
  before do
12
12
  Grit::Repo.init retter_config.retter_home.to_s
13
13
 
14
- command.stub!(:config) { retter_config }
14
+ Retter.stub!(:config) { retter_config }
15
15
  command.stub!(:say) { true }
16
16
  wip_file.open('w') {|f| f.puts article }
17
17
  command.rebind
@@ -7,7 +7,7 @@ describe 'Retter::Command#edit', clean: :all do
7
7
  let(:wip_file) { retter_config.wip_file }
8
8
 
9
9
  before do
10
- command.stub!(:config) { retter_config }
10
+ Retter.stub!(:config) { retter_config }
11
11
  end
12
12
 
13
13
  context 'no options' do
@@ -7,7 +7,7 @@ describe 'Retter::Command#invoke_after', clean: :all do
7
7
 
8
8
  context 'invoke with proc' do
9
9
  before do
10
- command.stub!(:config) { retter_config }
10
+ Retter.stub!(:config) { retter_config }
11
11
 
12
12
  retter_config.after(:edit) { commit }
13
13
  command.should_receive(:commit).and_return(true)
@@ -18,7 +18,7 @@ describe 'Retter::Command#invoke_after', clean: :all do
18
18
 
19
19
  context 'invoke with symbol' do
20
20
  before do
21
- command.stub!(:config) { retter_config }
21
+ Retter.stub!(:config) { retter_config }
22
22
 
23
23
  retter_config.after(:edit, :commit)
24
24
  command.should_receive(:invoke).with(:commit).and_return(true)
@@ -0,0 +1,47 @@
1
+ # coding: utf-8
2
+
3
+ require File.dirname(__FILE__) + '/../spec_helper'
4
+
5
+ describe 'Retter::Command#list', clean: :all do
6
+ let(:command) { Retter::Command.new }
7
+ let(:wip_file) { retter_config.wip_file }
8
+
9
+ before do
10
+ Retter.stub!(:config) { retter_config }
11
+ end
12
+
13
+ context 'happy case' do
14
+ before do
15
+ retter_config.retter_file(Date.parse('20110101')).open('w') do |f|
16
+ f.puts <<-EOM
17
+ # 朝11時
18
+
19
+ おはようございます
20
+
21
+ # 夜1時
22
+
23
+ おやすみなさい
24
+ EOM
25
+ end
26
+
27
+ retter_config.retter_file(Date.parse('20110222')).open('w') do |f|
28
+ f.puts <<-EOM
29
+ # 朝11時30分
30
+
31
+ おはようございます
32
+
33
+ # 夜1時30分
34
+
35
+ おやすみなさい
36
+ EOM
37
+ end
38
+ end
39
+
40
+ subject { capture(:stdout) { command.list }.split(/\n+/) }
41
+
42
+ its([0]) { should match /\[e0\]\s+2011\-02\-22/ }
43
+ its([1]) { should match /朝11時30分, 夜1時30分/ }
44
+ its([2]) { should match /\[e1\]\s+2011\-01\-01/ }
45
+ its([3]) { should match /朝11時, 夜1時/ }
46
+ end
47
+ end
@@ -7,7 +7,7 @@ describe 'Retter::Command#open', clean: :all do
7
7
  let(:wip_file) { retter_config.wip_file }
8
8
 
9
9
  before do
10
- command.stub!(:config) { retter_config }
10
+ Retter.stub!(:config) { retter_config }
11
11
  end
12
12
 
13
13
  it 'should be open application' do
@@ -9,7 +9,7 @@ describe 'Retter::Command#preview', clean: :all do
9
9
  let(:date_file) { retter_config.retter_file(Date.parse(date_str)) }
10
10
 
11
11
  before do
12
- command.stub!(:config) { retter_config }
12
+ Retter.stub!(:config) { retter_config }
13
13
  end
14
14
 
15
15
  context 'no options' do