retter 0.0.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.
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .rvmrc
6
+ lib/generator/skel/.gitignore
7
+ lib/generator/skel/.preview.html
8
+ lib/generator/skel/retters/*.md
9
+ lib/generator/skel/tmp/*
10
+ lib/generator/skel/entries.*
11
+ lib/generator/skel/entries/*.html
12
+ lib/generator/skel/vendor
13
+ tmp
14
+ .DS_Store
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source :rubygems
2
+
3
+ gem 'redcarpet', '>= 2.0.0b3'
4
+ gemspec
data/Rakefile ADDED
File without changes
data/bin/retter ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ # coding: utf-8
3
+
4
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
5
+
6
+ require 'retter'
7
+
8
+ if ARGV[0] == 'new'
9
+ require 'generator/newretter'
10
+ Newretter.start ARGV[1..-1]
11
+ else
12
+ Retter::Command.start
13
+ end
@@ -0,0 +1,62 @@
1
+ # coding: utf-8
2
+
3
+ require 'thor/group'
4
+ require 'grit'
5
+ require 'bundler'
6
+ require 'bundler/cli'
7
+
8
+ class Newretter < Thor::Group
9
+ FILES = %w(
10
+ .gitignore
11
+ Gemfile
12
+ Retterfile
13
+ config.ru
14
+ layouts/entries.html.haml
15
+ layouts/entry.html.haml
16
+ layouts/profile.html.haml
17
+ layouts/index.html.haml
18
+ layouts/retter.html.haml
19
+ images/.gitkeep
20
+ index.html
21
+ entries/.gitkeep
22
+ javascripts/.gitkeep
23
+ stylesheets/application.css
24
+ retters/.gitkeep
25
+ )
26
+
27
+ include Thor::Actions
28
+
29
+ argument :name
30
+
31
+ def self.source_root
32
+ File.dirname(__FILE__)
33
+ end
34
+
35
+ def create_files
36
+ FILES.each do |file|
37
+ template("skel/#{file}", "#{name}/#{file}")
38
+ end
39
+ end
40
+
41
+ def bundle_install
42
+ pwd = Dir.pwd
43
+ FileUtils.cd name
44
+
45
+ Bundler::CLI.new.install
46
+
47
+ FileUtils.cd pwd
48
+ end
49
+
50
+ def git_init
51
+ Grit::Repo.init "#{Dir.pwd}/#{name}"
52
+ end
53
+
54
+ def notice_how_to_use
55
+ say <<-EOM, :green
56
+ -- Thanks for flying Retter :-> --
57
+ You have to set $RETTER_HOME variable to use #{name}.
58
+ example:
59
+ export RETTER_HOME=#{Dir.pwd}/#{name}
60
+ EOM
61
+ end
62
+ end
@@ -0,0 +1,2 @@
1
+ .preview.html
2
+ tmp/*
@@ -0,0 +1,5 @@
1
+ source :rubygems
2
+
3
+ gem 'rack'
4
+ gem 'thin' # for heroku
5
+
@@ -0,0 +1,6 @@
1
+ # coding: utf-8
2
+
3
+ url 'http://retter.example.com/'
4
+ title '<%= name %>'
5
+ description '<%= name %>'
6
+ author '<%= ENV["USER"] %>'
@@ -0,0 +1,28 @@
1
+ require 'rack'
2
+
3
+ use Rack::Static, root: '.', urls: %w(
4
+ /index.html
5
+ /profile.html
6
+ /entries.html
7
+ /entries.rss
8
+ /favicon.png
9
+ /entries
10
+ /stylesheets
11
+ /javascripts
12
+ /images
13
+ )
14
+
15
+ map '/' do
16
+ run ->(env) {
17
+ if env['PATH_INFO'] == '/'
18
+ [
19
+ 200,
20
+ {'Content-Type' => 'text/html', 'Cache-Control' => 'public, max-age=86400'},
21
+ File.open('index.html', File::RDONLY)
22
+ ]
23
+ else
24
+ [404, {'Content-Type' => 'text/plain'}, ['Not Found']]
25
+ end
26
+ }
27
+ end
28
+
File without changes
File without changes
@@ -0,0 +1 @@
1
+ :-)
File without changes
@@ -0,0 +1,9 @@
1
+ %article
2
+ %ul#entries
3
+ - entries.each do |entry|
4
+ %li
5
+ %a.entry{href: entry_path(entry.date)}= entry.date.strftime('%Y/%m/%d')
6
+ %ul.titles
7
+ - entry.titles.each do |id, title|
8
+ %li
9
+ %a.title{href: entry_path(entry.date, id)}= title
@@ -0,0 +1,4 @@
1
+ %article
2
+ .entry
3
+ %h1.date= entry.date.strftime('%Y/%m/%d')
4
+ = entry
@@ -0,0 +1,7 @@
1
+ #entries
2
+ - entries[0..5].each do |entry|
3
+ %article
4
+ .entry
5
+ %h1.date
6
+ %a{href: entry_path(entry.date)}= entry.date.strftime('%Y/%m/%d')
7
+ = entry
@@ -0,0 +1,6 @@
1
+ %article
2
+ %dl
3
+ %dt Author
4
+ %dd= config.author
5
+ %dt= config.title
6
+ %dd= config.description
@@ -0,0 +1,25 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ %title= config.title
5
+ %meta{:'http-equiv' => 'Content-Type', content: 'text/html', charset: 'utf-8'}
6
+ %link{rel: 'icon', type: 'image/png', href: '/favicon.png'}
7
+ %link{href: '/stylesheets/application.css', media: 'screen', rel: 'stylesheet', type: 'text/css'}
8
+ %link{rel: 'alternate', type: 'application/rss+xml', title: 'RSS', href: '/entries.rss'}
9
+ %body
10
+ #header
11
+ %h1
12
+ %a{href: '/'}= config.title
13
+ %ul#menu
14
+ %li
15
+ %a{href: '/'} Home
16
+ %li
17
+ %a{href: '/profile.html'} Profile
18
+ %li
19
+ %a{href: '/entries.html'} Archives
20
+ %li
21
+ %a{href: '/entries.rss'} RSS
22
+ #page
23
+ #content= content
24
+ #footer
25
+ #{config.title} (C) #{config.author}
File without changes
@@ -0,0 +1,114 @@
1
+ html {
2
+ height: 100%;
3
+ }
4
+
5
+ body {
6
+ margin: 0 auto 0 auto;
7
+ padding: 0;
8
+ font-family: sans-serif;
9
+ /*lbackground: rgb(55,65,60);*/
10
+ background: #EEE;
11
+ height: 100%;
12
+ }
13
+
14
+ ul {
15
+ list-style: none;
16
+ }
17
+
18
+ a {
19
+ text-decoration: none;
20
+ color: rgb(25,30,10);
21
+ }
22
+
23
+ #header {
24
+ width: 100%;
25
+ padding: 0;
26
+ margin: 0;
27
+ }
28
+
29
+ #header h1 {
30
+ width: 100%;
31
+ margin: 0;
32
+ padding: 0.2em 0 0.2em 1em;
33
+ background: rgb(25,30,10);
34
+ color: rgb(77,144,253);
35
+ }
36
+
37
+ #header h1 a {
38
+ color: rgb(77,144,253);
39
+ }
40
+
41
+ #header ul#menu {
42
+ margin: 0.5em 0 3em 0;
43
+ padding: 0 0 0 2em;
44
+ background: #FFF;
45
+ }
46
+
47
+ #header ul#menu li {
48
+ float: left;
49
+ margin-right: 1em;
50
+ }
51
+
52
+ #page {
53
+ clear: both;
54
+ margin: 0 auto 0 auto;
55
+ width: 800px;
56
+ position: relative;
57
+ min-height: 100%;
58
+ }
59
+
60
+ article {
61
+ background: rgb(228,239,192);
62
+ color: rgb(0,30,67);
63
+ border-radius: 20px;
64
+ border: 3px rgb(25,30,10) solid;
65
+ -moz-border-radius: 20px;
66
+ -webkit-border-radius: 20px;
67
+ padding: 1em 1.5em 1em 1.5em;
68
+ margin: 1em 0 1em 0;
69
+ width 100%;
70
+ }
71
+
72
+ article h1 {
73
+ margin-top: 2em;
74
+ }
75
+
76
+ article h1.date {
77
+ font-size: 1em;
78
+ text-align: right;
79
+ margin-top: 0.5em;
80
+ margin-bottom: -2em;
81
+ }
82
+
83
+ article ul#entries > li {
84
+ margin-top: 1em;
85
+ }
86
+
87
+ article ul#entries {
88
+ line-height: 1.5em;
89
+ }
90
+
91
+ #entries {
92
+ width 100%;
93
+ }
94
+
95
+ pre {
96
+ background: #EEE;
97
+ color: rgb(0,30,67);
98
+ padding: 1em;
99
+ border-radius: 10px;
100
+ border: 1px #000 solid;
101
+ -moz-border-radius: 10px;
102
+ -webkit-border-radius: 10px;
103
+ }
104
+
105
+ #footer {
106
+ text-align: center;
107
+ margin: 1em 0 0 0;
108
+ padding: 0.5em 0.5em 0.5em 1em;
109
+ width: 100%;
110
+ background: rgb(0,40,40);
111
+ color: rgb(77,144,253);
112
+ position: relative; bottom: 0;
113
+ }
114
+
@@ -0,0 +1,74 @@
1
+ # coding: utf-8
2
+
3
+ class Retter::Command < Thor
4
+ desc 'edit', 'Edit current entry with $EDITOR'
5
+ method_options date: :string
6
+ def edit
7
+ system config.editor, detected_retter_file.to_s
8
+ end
9
+
10
+ default_task :edit
11
+
12
+ desc 'preview', 'Preview current entry'
13
+ method_options date: :string
14
+ def preview
15
+ preview = Retter::Stationery.previewer(detected_date, config)
16
+
17
+ preview.print
18
+ Launchy.open preview.file_path.to_s
19
+ end
20
+
21
+ desc 'open', 'Open site statically'
22
+ def open
23
+ Launchy.open config.index_file.to_s
24
+ end
25
+
26
+ desc 'rebind', 'Re generate site pages'
27
+ def rebind
28
+ binder = Retter::Stationery.binder(config)
29
+
30
+ binder.commit_wip_file
31
+ binder.rebind!
32
+ end
33
+
34
+ desc 'bind', 'Generate site pages'
35
+ alias_method :bind, :rebind
36
+
37
+ desc 'new', 'Create new site'
38
+ def new
39
+ end
40
+
41
+ private
42
+
43
+ def detected_retter_file
44
+ if options[:date]
45
+ config.retter_file(Date.parse(options[:date]), '.md')
46
+ else
47
+ todays_file = config.retter_file(Date.today, '.md')
48
+ todays_file.exist? ? todays_file : config.wip_file
49
+ end
50
+ end
51
+
52
+ def detected_date
53
+ options[:date] ? Date.parse(options[:date]) : Date.today
54
+ end
55
+
56
+ def config
57
+ @retter_config ||= Retter::Config.new(ENV)
58
+ rescue Retter::EnvError
59
+ say 'Set $RETTER_HOME and $EDITOR, first.', :red
60
+ say <<-EOM, :green
61
+ usage:
62
+ export EDITOR=`which vim` # or other editor
63
+ cd /path/to/dir
64
+ retter new my_sweet_diary
65
+ export RETTER_HOME=/path/to/dir/my_sweet_diary
66
+ cd my_sweet_diary
67
+ retter # Write the article with markdown, and save.
68
+ retter preview # Draft article will be opened in your default browser.
69
+ retter bind # Your actual website will be generated.
70
+ bundle exec rackup # Open your browser, and visit http://localhost:9292/ .
71
+ EOM
72
+ exit 1
73
+ end
74
+ end
@@ -0,0 +1,89 @@
1
+ # coding: utf-8
2
+
3
+ class Retter::Config
4
+ [:editor, :retter_home, :title, :description, :url, :author].each do |att|
5
+ class_eval <<-EOM
6
+ def #{att}(val = nil)
7
+ val ? @options[:#{att}] = val : @options[:#{att}]
8
+ end
9
+ EOM
10
+ end
11
+
12
+ def initialize(env)
13
+ @env, @options = env, {}
14
+
15
+ detect_retter_home
16
+ raise Retter::EnvError unless env.values_at('EDITOR', 'RETTER_HOME').all?
17
+
18
+ editor env['EDITOR']
19
+ retter_home Pathname.new(env['RETTER_HOME'])
20
+ url 'http://example.com'
21
+
22
+ retterfile = retter_home.join('Retterfile')
23
+ instance_eval retterfile.read if retterfile.exist?
24
+ end
25
+
26
+ def detect_retter_home
27
+ @env['RETTER_HOME'] = Dir.pwd if File.exist? 'Retterfile'
28
+ end
29
+
30
+ def retters_dir
31
+ retter_home.join 'retters/'
32
+ end
33
+
34
+ def wip_file
35
+ retters_dir.join 'today.md'
36
+ end
37
+
38
+ def retter_file(date, suf)
39
+ retters_dir.join(date ? date.strftime("%Y%m%d#{suf}") : "today#{suf}")
40
+ end
41
+
42
+ def layouts_dir
43
+ retter_home.join 'layouts/'
44
+ end
45
+
46
+ def layout_file
47
+ layouts_dir.join 'retter.html.haml'
48
+ end
49
+
50
+ def profile_layout_file
51
+ layouts_dir.join 'profile.html.haml'
52
+ end
53
+
54
+ def entry_layout_file
55
+ layouts_dir.join 'entry.html.haml'
56
+ end
57
+
58
+ def entries_layout_file
59
+ layouts_dir.join 'entries.html.haml'
60
+ end
61
+
62
+ def index_layout_file
63
+ layouts_dir.join 'index.html.haml'
64
+ end
65
+
66
+ def entries_dir
67
+ retter_home.join 'entries/'
68
+ end
69
+
70
+ def entry_file(date)
71
+ entries_dir.join date.strftime('%Y%m%d.html')
72
+ end
73
+
74
+ def profile_file
75
+ retter_home.join 'profile.html'
76
+ end
77
+
78
+ def index_file
79
+ retter_home.join 'index.html'
80
+ end
81
+
82
+ def entries_file
83
+ retter_home.join 'entries.html'
84
+ end
85
+
86
+ def feed_file
87
+ retter_home.join 'entries.rss'
88
+ end
89
+ end
@@ -0,0 +1,37 @@
1
+ # coding: utf-8
2
+
3
+ class Retter::Entry
4
+ attr_accessor :date, :body, :titles
5
+
6
+ def initialize(attrs={})
7
+ @date, @body = attrs.values_at(:date, :body)
8
+
9
+ attach_titles
10
+ load_titles
11
+ end
12
+
13
+ def to_s
14
+ body
15
+ end
16
+
17
+ private
18
+
19
+ def body_elements
20
+ Nokogiri::HTML(body)
21
+ end
22
+
23
+ def attach_titles
24
+ html = body_elements
25
+ html.search('//h1').each_with_index do |h1, seq|
26
+ h1.set_attribute 'id', "a#{seq}"
27
+ end
28
+
29
+ @body = html.search('//body/*').to_s
30
+ end
31
+
32
+ def load_titles
33
+ @titles = body_elements.search('//h1').each_with_object({}) {|h1, titles|
34
+ titles[h1.attr('id')] = h1.text
35
+ }
36
+ end
37
+ end
@@ -0,0 +1,130 @@
1
+ # coding: utf-8
2
+
3
+ module Retter::Stationery
4
+ class Binder
5
+ attr_reader :config, :entries
6
+
7
+ def initialize(config)
8
+ @config = config
9
+ end
10
+
11
+ def view_scope
12
+ @view_scope ||= View::Scope.new(config, entries: entries)
13
+ end
14
+
15
+ def renderer
16
+ Haml::Engine.new(config.layout_file.read, ugly: true)
17
+ end
18
+
19
+ def entries_renderer
20
+ Haml::Engine.new(config.entries_layout_file.read, ugly: true)
21
+ end
22
+
23
+ def entry_renderer
24
+ Haml::Engine.new(config.entry_layout_file.read, ugly: true)
25
+ end
26
+
27
+ def index_renderer
28
+ Haml::Engine.new(config.index_layout_file.read, ugly: true)
29
+ end
30
+
31
+ def profile_renderer
32
+ Haml::Engine.new(config.profile_layout_file.read, ugly: true)
33
+ end
34
+
35
+ def rebind!
36
+ commit_wip_file
37
+
38
+ @entries = Retter::Stationery.scan(config.retters_dir)
39
+
40
+ bind_entries
41
+ print_index
42
+ print_profile
43
+ print_rss
44
+ end
45
+
46
+ def commit_wip_file
47
+ if config.wip_file.exist?
48
+ html = config.wip_file.read
49
+ config.retter_file(Date.today, '.md').open('a') {|f| f.puts html }
50
+ config.wip_file.unlink
51
+ end
52
+ end
53
+
54
+ def bind_entries
55
+ @entries.each {|entry| print_entry entry }
56
+ print_toc
57
+ end
58
+
59
+ def print_entry(entry)
60
+ part = entry_renderer.render(view_scope, entry: entry)
61
+ html = renderer.render(view_scope, content: part)
62
+
63
+ config.entry_file(entry.date).open('w') do |f|
64
+ f.puts View::Helper.fix_path(html, '../')
65
+ end
66
+ end
67
+
68
+ def print_index
69
+ part = index_renderer.render(view_scope)
70
+ html = renderer.render(view_scope, content: part)
71
+
72
+ config.index_file.open('w') do |f|
73
+ f.puts View::Helper.fix_path(html, './')
74
+ end
75
+ end
76
+
77
+ def print_profile
78
+ part = profile_renderer.render(view_scope)
79
+ html = renderer.render(view_scope, content: part)
80
+
81
+ config.profile_file.open('w') do |f|
82
+ f.puts View::Helper.fix_path(html, './')
83
+ end
84
+ end
85
+
86
+ def print_toc
87
+ part = entries_renderer.render(view_scope)
88
+ html = renderer.render(view_scope, content: part)
89
+
90
+ config.entries_file.open('w') do |f|
91
+ f.puts View::Helper.fix_path(html, './')
92
+ end
93
+ end
94
+
95
+ def print_rss
96
+ config.feed_file.open('w') {|f| f.puts rss }
97
+ end
98
+
99
+ def rss
100
+ xml = Builder::XmlMarkup.new
101
+ xml.instruct!
102
+ xml.rdf:RDF, :xmlns => 'http://purl.org/rss/1.0/',
103
+ :'xmlns:rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
104
+ :'xmlns:dc' => 'http://purl.org/dc/elements/1.1/',
105
+ :'xml:lang' => 'ja' do
106
+ xml.channel :'rdf:about' => config.url do
107
+ xml.title config.title
108
+ xml.link config.url
109
+ xml.dc:date, entries.first.date
110
+ xml.description config.description
111
+ xml.items { xml.rdf(:Seq) { entries.each {|e| xml.rdf:li, :'rdf:resource' => entry_url(e.date) } } }
112
+ end
113
+
114
+ entries.each do |entry|
115
+ xml.item about: entry_url(entry.date) do
116
+ xml.title entry.date.strftime('%Y/%m/%d')
117
+ xml.description { xml.cdata! entry.body }
118
+ xml.dc:date, entry.date
119
+ xml.link entry_url(entry.date)
120
+ xml.author config.author
121
+ end
122
+ end
123
+ end
124
+ end
125
+
126
+ def entry_url(date, id = nil)
127
+ (URI.parse(config.url) + date.strftime('/entries/%Y%m%d.html')).to_s
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,59 @@
1
+ # coding: utf-8
2
+
3
+ module Retter::Stationery
4
+ class Previewer
5
+ attr_reader :config
6
+
7
+ def initialize(date, config)
8
+ @config, @date = config, date
9
+ @body, @entry = *nil
10
+
11
+ load_retter_file
12
+ load_wip_entry_if_needed
13
+ end
14
+
15
+ def file_path
16
+ config.retter_home.join '.preview.html'
17
+ end
18
+
19
+ def renderer
20
+ Haml::Engine.new(config.layout_file.read, ugly: true)
21
+ end
22
+
23
+ def entry_renderer
24
+ Haml::Engine.new(config.entry_layout_file.read, ugly: true)
25
+ end
26
+
27
+ def print
28
+ build_entry
29
+ print_html
30
+ end
31
+
32
+ private
33
+
34
+ def print_html
35
+ scope = View::Scope.new(config)
36
+ part = entry_renderer.render(scope, entry: @entry)
37
+ html = renderer.render(scope, content: part, entries: [@entry])
38
+
39
+ file_path.open('w') do |file|
40
+ file.puts View::Helper.fix_path(html, './')
41
+ end
42
+ end
43
+
44
+ def build_entry
45
+ @entry = Retter::Entry.new(date: @date, body: Retter::Stationery.parser.render(@body))
46
+ end
47
+
48
+ def load_retter_file
49
+ retter_file = config.retter_file(@date, '.md')
50
+ @body = retter_file.exist? ? retter_file.read : ''
51
+ end
52
+
53
+ def load_wip_entry_if_needed
54
+ if @date == Date.today && config.wip_file.exist?
55
+ @body = [@body, config.wip_file.read].join("\n")
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,9 @@
1
+ # coding: utf-8
2
+
3
+ module Retter::Stationery
4
+ class Renderer < ::Redcarpet::Render::HTML
5
+ def block_code(code, lang)
6
+ ::CodeRay.scan(code, lang ? lang.intern : :plain).div#.div(line_numbers: :table)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,52 @@
1
+ # coding: utf-8
2
+
3
+ module Retter::Stationery::View
4
+ module Helper
5
+ extend self
6
+
7
+ def fix_path(html, prefix='./')
8
+ elements = Nokogiri::HTML(html)
9
+
10
+ elements.search("[src!=''][src!='']").each do |el|
11
+ src = el.attr('src').scan(/[^\.\/]{3}.*/).first
12
+ next if src =~ /^(?:http|https):\/\//
13
+
14
+ el.set_attribute 'src', [prefix, src].join
15
+ end
16
+
17
+ elements.search("[href][href!='#']").each do |el|
18
+ href = el.attr('href')
19
+ next if href =~ /^(?:http|https):\/\//
20
+
21
+ if href == '/'
22
+ el.set_attribute 'href', [prefix, 'index.html'].join
23
+ else
24
+ el.set_attribute 'href', [prefix, href.scan(/[^\.\/]{3}.*/).first].join
25
+ end
26
+ end
27
+
28
+ elements.to_s
29
+ end
30
+
31
+ def entry_path(date, id = nil)
32
+ date.strftime('/entries/%Y%m%d.html') + (id ? "##{id}" : '')
33
+ end
34
+ end
35
+
36
+ class Scope
37
+ attr_reader :config
38
+ attr_accessor :assigns
39
+
40
+ include Helper
41
+
42
+ [:entries].each do |meth|
43
+ define_method meth do
44
+ @assigns[meth]
45
+ end
46
+ end
47
+
48
+ def initialize(config, assigns = {})
49
+ @config, @assigns = config, assigns
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,47 @@
1
+ # coding: utf-8
2
+
3
+ module Retter::Stationery
4
+ class << self
5
+ def scan(path)
6
+ entries = find_markup_files(path).map {|file|
7
+ date = file.basename('.*').to_s
8
+ mkup = File.open(file, &:read)
9
+ Retter::Entry.new date: Date.parse(date), body: parser.render(mkup)
10
+ }
11
+
12
+ entries.sort_by(&:date).reverse
13
+ end
14
+
15
+ def find_markup_files(path)
16
+ path = Pathname.new(path).realpath
17
+ 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 }
18
+ end
19
+
20
+ def parser
21
+ @parser ||= ::Redcarpet::Markdown.new(
22
+ Renderer,
23
+ autolink: true,
24
+ space_after_headers: true,
25
+ fenced_code_blocks: true,
26
+ strikethrough: true,
27
+ superscript: true,
28
+ fenced_code_blocks: true,
29
+ tables: true
30
+ )
31
+ end
32
+
33
+ def previewer(date, config)
34
+ Previewer.new date, config
35
+ end
36
+
37
+ def binder(config)
38
+ Binder.new config
39
+ end
40
+ end
41
+ end
42
+
43
+ require 'retter/stationery/renderer'
44
+ require 'retter/stationery/view'
45
+ require 'retter/stationery/previewer'
46
+ require 'retter/stationery/binder'
47
+
@@ -0,0 +1,3 @@
1
+ module Retter
2
+ VERSION = '0.0.0'
3
+ end
data/lib/retter.rb ADDED
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+
3
+ here = File.dirname(__FILE__)
4
+ $LOAD_PATH.unshift here unless $LOAD_PATH.include?(here)
5
+
6
+ module Retter
7
+ class EnvError < RuntimeError; end
8
+ end
9
+
10
+ require 'date'
11
+ require 'time'
12
+ require 'builder'
13
+ require 'pathname'
14
+ require 'thor'
15
+ require 'redcarpet'
16
+ require 'coderay'
17
+ require 'nokogiri'
18
+ require 'launchy'
19
+ require 'haml'
20
+ require 'uri'
21
+ require 'retter/version'
22
+ require 'retter/entry'
23
+ require 'retter/stationery'
24
+ require 'retter/config'
25
+ require 'retter/command'
data/retter.gemspec ADDED
@@ -0,0 +1,34 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "retter/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "retter"
7
+ s.version = Retter::VERSION
8
+ s.authors = ["hibariya"]
9
+ s.email = ["celluloid.key@gmail.com"]
10
+ s.homepage = "http://retter.heroku.com"
11
+ s.summary = %q{Lightweight diary workflow}
12
+ s.description = %q{Lightweight diary workflow}
13
+
14
+ #s.rubyforge_project = "retter"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_runtime_dependency 'thor'
22
+ s.add_runtime_dependency 'builder'
23
+ s.add_runtime_dependency 'redcarpet', ['>= 2.0.0b3']
24
+ s.add_runtime_dependency 'coderay'
25
+ s.add_runtime_dependency 'nokogiri'
26
+ s.add_runtime_dependency 'launchy'
27
+ s.add_runtime_dependency 'haml'
28
+ s.add_runtime_dependency 'bundler'
29
+ s.add_runtime_dependency 'grit'
30
+
31
+ s.add_development_dependency 'ir_b'
32
+ s.add_development_dependency 'tapp'
33
+ s.add_development_dependency 'rspec'
34
+ end
@@ -0,0 +1,52 @@
1
+ # coding: utf-8
2
+
3
+ require File.dirname(__FILE__) + '/../spec_helper'
4
+
5
+ describe 'Retter::Command#edit', clean: :all do
6
+ let(:command) { Retter::Command.new }
7
+ let(:wip_file) { retter_config.wip_file }
8
+
9
+ before do
10
+ command.stub!(:config) { retter_config }
11
+ end
12
+
13
+ context 'no options' do
14
+ before do
15
+ command.edit
16
+ end
17
+
18
+ it { wip_file.should be_exist }
19
+ end
20
+
21
+ context 'no options after rebind' do
22
+ let(:date) { '20110101' }
23
+
24
+ before do
25
+ Date.stub!(:today).and_return(Date.parse(date))
26
+
27
+ command.edit
28
+ command.bind
29
+ command.edit
30
+ end
31
+
32
+ it { wip_file.should_not be_exist }
33
+ it { retter_config.retters_dir.join("#{date}.md").should be_exist }
34
+ end
35
+
36
+ context 'with date' do
37
+ let(:date) { '20110101' }
38
+
39
+ before do
40
+ command.stub!(:options) { {date: date} }
41
+ command.edit
42
+ end
43
+
44
+ it { wip_file.should_not be_exist }
45
+
46
+ describe 'target date file' do
47
+ subject { retter_config.retters_dir.join("#{date}.md") }
48
+
49
+ it { should be_exist }
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,43 @@
1
+ # coding: utf-8
2
+
3
+ require File.dirname(__FILE__) + '/../spec_helper'
4
+
5
+ describe 'Retter::Command#preview', clean: :all do
6
+ let(:command) { Retter::Command.new }
7
+ let(:preview) { retter_config.retter_home.join('.preview.html').read }
8
+ let(:wip_file) { retter_config.wip_file }
9
+ let(:date_file) { retter_config.retter_file(Date.parse(date), '.md') }
10
+
11
+ before do
12
+ command.stub!(:config) { retter_config }
13
+ end
14
+
15
+ context 'no options' do
16
+ let(:article) { 'w00t!' }
17
+
18
+ before do
19
+ wip_file.open('w') {|f| f.puts article }
20
+ Launchy.stub!(:open).with(anything)
21
+
22
+ command.preview
23
+ end
24
+
25
+ it { preview.should =~ /<body.*#{article}.*\/body>/mi }
26
+ end
27
+
28
+ context 'with date' do
29
+ let(:article) { 'おはようございます' }
30
+ let(:date) { '20110101' }
31
+
32
+ before do
33
+ wip_file.open('w') {|f| f.puts 'おやすみなさい' }
34
+ date_file.open('w') {|f| f.puts article }
35
+ Launchy.stub!(:open).with(anything)
36
+
37
+ command.preview
38
+ end
39
+
40
+ it { preview =~ /#{article}/mi }
41
+ it { preview !~ /おやすみなさい/mi }
42
+ end
43
+ end
@@ -0,0 +1,53 @@
1
+ # coding: utf-8
2
+
3
+ require File.dirname(__FILE__) + '/../spec_helper'
4
+
5
+ describe 'Retter::Command#rebind', clean: :all do
6
+ let(:command) { Retter::Command.new }
7
+ let(:wip_file) { retter_config.wip_file }
8
+ let(:date_file) { retter_config.retter_file(Date.parse(date), '.md') }
9
+ let(:date_html) { retter_config.retter_home.join('entries', "#{date}.html") }
10
+
11
+ before do
12
+ command.stub!(:config) { retter_config }
13
+ end
14
+
15
+ context 'first post' do
16
+ let(:date) { '20110101' }
17
+ let(:article) { <<-EOM }
18
+ # 朝11時
19
+
20
+ おはようございます
21
+
22
+ # 夜1時
23
+
24
+ おやすみなさい
25
+ EOM
26
+
27
+ before do
28
+ wip_file.open('w') {|f| f.puts article }
29
+ Date.stub!(:today).and_return(Date.parse(date))
30
+
31
+ command.rebind
32
+ end
33
+
34
+ describe 'today.md' do
35
+ it { wip_file.should_not be_exist }
36
+ end
37
+
38
+ describe 'index.html' do
39
+ subject { Nokogiri::HTML(retter_config.retter_home.join('index.html').read) }
40
+
41
+ it { subject.search('body').text.should =~ /おはようございます/ }
42
+ it { subject.search('.entry h1.date').first.text.should be_include('2011/01/01') }
43
+ it { subject.search('.entry h1').map(&:text).map(&:strip).should == %w(2011/01/01 朝11時 夜1時) }
44
+ end
45
+
46
+ describe 'entries.html' do
47
+ subject { Nokogiri::HTML(retter_config.retter_home.join('entries.html').read) }
48
+
49
+ it { subject.search('a.entry').first.text.should be_include('2011/01/01') }
50
+ it { subject.search('a.title').map(&:text).map(&:strip).should == %w(朝11時 夜1時) }
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,37 @@
1
+ # coding: utf-8
2
+
3
+ RETTER_ROOT = Pathname.new(File.dirname(__FILE__) + '/../').realpath
4
+
5
+ require RETTER_ROOT.join('lib', 'retter')
6
+ require 'tapp'
7
+
8
+ module Retter::ConfigSupport
9
+ def retter_config
10
+ return @config if @config
11
+
12
+ env = {
13
+ 'EDITOR' => 'touch',
14
+ 'RETTER_HOME' => RETTER_ROOT.join('tmp', 'test').to_s
15
+ }
16
+
17
+ @config = Retter::Config.new(env)
18
+ end
19
+ end
20
+
21
+ RSpec.configure do |config|
22
+ config.filter_run focus: true
23
+ config.run_all_when_everything_filtered = true
24
+
25
+ retter_home = RETTER_ROOT.join('tmp', 'test')
26
+ skel = RETTER_ROOT.join('lib', 'generator', 'skel')
27
+
28
+ config.after(:each, clean: :all) do
29
+ FileUtils.cp_r skel, retter_home.dirname.join('test')
30
+ end
31
+
32
+ config.after(:each, clean: :all) do
33
+ FileUtils.rm_rf retter_home
34
+ end
35
+
36
+ config.include Retter::ConfigSupport
37
+ end
metadata ADDED
@@ -0,0 +1,217 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: retter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - hibariya
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-09-08 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: thor
16
+ requirement: &70260599810340 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70260599810340
25
+ - !ruby/object:Gem::Dependency
26
+ name: builder
27
+ requirement: &70260599899920 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70260599899920
36
+ - !ruby/object:Gem::Dependency
37
+ name: redcarpet
38
+ requirement: &70260599902380 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: 2.0.0b3
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70260599902380
47
+ - !ruby/object:Gem::Dependency
48
+ name: coderay
49
+ requirement: &70260599904040 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *70260599904040
58
+ - !ruby/object:Gem::Dependency
59
+ name: nokogiri
60
+ requirement: &70260599913220 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :runtime
67
+ prerelease: false
68
+ version_requirements: *70260599913220
69
+ - !ruby/object:Gem::Dependency
70
+ name: launchy
71
+ requirement: &70260599914340 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: *70260599914340
80
+ - !ruby/object:Gem::Dependency
81
+ name: haml
82
+ requirement: &70260599913880 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ type: :runtime
89
+ prerelease: false
90
+ version_requirements: *70260599913880
91
+ - !ruby/object:Gem::Dependency
92
+ name: bundler
93
+ requirement: &70260599913440 !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ type: :runtime
100
+ prerelease: false
101
+ version_requirements: *70260599913440
102
+ - !ruby/object:Gem::Dependency
103
+ name: grit
104
+ requirement: &70260599912660 !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :runtime
111
+ prerelease: false
112
+ version_requirements: *70260599912660
113
+ - !ruby/object:Gem::Dependency
114
+ name: ir_b
115
+ requirement: &70260599910020 !ruby/object:Gem::Requirement
116
+ none: false
117
+ requirements:
118
+ - - ! '>='
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ type: :development
122
+ prerelease: false
123
+ version_requirements: *70260599910020
124
+ - !ruby/object:Gem::Dependency
125
+ name: tapp
126
+ requirement: &70260599907780 !ruby/object:Gem::Requirement
127
+ none: false
128
+ requirements:
129
+ - - ! '>='
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: *70260599907780
135
+ - !ruby/object:Gem::Dependency
136
+ name: rspec
137
+ requirement: &70260599907300 !ruby/object:Gem::Requirement
138
+ none: false
139
+ requirements:
140
+ - - ! '>='
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ type: :development
144
+ prerelease: false
145
+ version_requirements: *70260599907300
146
+ description: Lightweight diary workflow
147
+ email:
148
+ - celluloid.key@gmail.com
149
+ executables:
150
+ - retter
151
+ extensions: []
152
+ extra_rdoc_files: []
153
+ files:
154
+ - .gitignore
155
+ - Gemfile
156
+ - Rakefile
157
+ - bin/retter
158
+ - lib/generator/newretter.rb
159
+ - lib/generator/skel/.gitignore
160
+ - lib/generator/skel/Gemfile
161
+ - lib/generator/skel/Retterfile
162
+ - lib/generator/skel/config.ru
163
+ - lib/generator/skel/entries/.gitkeep
164
+ - lib/generator/skel/images/.gitkeep
165
+ - lib/generator/skel/index.html
166
+ - lib/generator/skel/javascripts/.gitkeep
167
+ - lib/generator/skel/layouts/entries.html.haml
168
+ - lib/generator/skel/layouts/entry.html.haml
169
+ - lib/generator/skel/layouts/index.html.haml
170
+ - lib/generator/skel/layouts/profile.html.haml
171
+ - lib/generator/skel/layouts/retter.html.haml
172
+ - lib/generator/skel/retters/.gitkeep
173
+ - lib/generator/skel/stylesheets/application.css
174
+ - lib/retter.rb
175
+ - lib/retter/command.rb
176
+ - lib/retter/config.rb
177
+ - lib/retter/entry.rb
178
+ - lib/retter/stationery.rb
179
+ - lib/retter/stationery/binder.rb
180
+ - lib/retter/stationery/previewer.rb
181
+ - lib/retter/stationery/renderer.rb
182
+ - lib/retter/stationery/view.rb
183
+ - lib/retter/version.rb
184
+ - retter.gemspec
185
+ - spec/command/edit_spec.rb
186
+ - spec/command/preview_spec.rb
187
+ - spec/command/rebind_spec.rb
188
+ - spec/spec_helper.rb
189
+ homepage: http://retter.heroku.com
190
+ licenses: []
191
+ post_install_message:
192
+ rdoc_options: []
193
+ require_paths:
194
+ - lib
195
+ required_ruby_version: !ruby/object:Gem::Requirement
196
+ none: false
197
+ requirements:
198
+ - - ! '>='
199
+ - !ruby/object:Gem::Version
200
+ version: '0'
201
+ required_rubygems_version: !ruby/object:Gem::Requirement
202
+ none: false
203
+ requirements:
204
+ - - ! '>='
205
+ - !ruby/object:Gem::Version
206
+ version: '0'
207
+ requirements: []
208
+ rubyforge_project:
209
+ rubygems_version: 1.8.6
210
+ signing_key:
211
+ specification_version: 3
212
+ summary: Lightweight diary workflow
213
+ test_files:
214
+ - spec/command/edit_spec.rb
215
+ - spec/command/preview_spec.rb
216
+ - spec/command/rebind_spec.rb
217
+ - spec/spec_helper.rb