writetheman 0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +61 -0
- data/Rakefile +1 -0
- data/lib/writetheman.rb +18 -0
- data/lib/writetheman/article/access.rb +60 -0
- data/lib/writetheman/article/base.rb +70 -0
- data/lib/writetheman/article/content.rb +95 -0
- data/lib/writetheman/article/file.rb +41 -0
- data/lib/writetheman/article/utils.rb +36 -0
- data/lib/writetheman/blog.rb +25 -0
- data/lib/writetheman/path.rb +35 -0
- data/lib/writetheman/version.rb +3 -0
- data/spec/article/access_spec.rb +61 -0
- data/spec/article/base_spec.rb +180 -0
- data/spec/article/file_spec.rb +91 -0
- data/spec/article/utils_spec.rb +6 -0
- data/spec/blog_spec.rb +54 -0
- data/spec/factories.rb +16 -0
- data/spec/shared_values.rb +57 -0
- data/spec/spec_helper.rb +24 -0
- data/writetheman.gemspec +26 -0
- metadata +158 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 davidtysman
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# Writetheman
|
2
|
+
|
3
|
+
Create, show and list the <a href='http://middlemanapp.com/basics/blogging/'>middleman blog</a> articles.
|
4
|
+
|
5
|
+
It's used by my middleman editor <a href='https://github.com/davidtysman/railstheman'>RailsTheMan</a> to manage articles in the browser.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'writetheman'
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install writetheman
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
### Init
|
24
|
+
|
25
|
+
Config the path of your local middleman :
|
26
|
+
|
27
|
+
article = Writetheman::Article::Base.new(yourpath)
|
28
|
+
blog = Writetheman::Blog.new(yourpath)
|
29
|
+
|
30
|
+
Init the article :
|
31
|
+
|
32
|
+
article.title = title
|
33
|
+
article.date = date
|
34
|
+
article.body = body
|
35
|
+
article.header = header # string
|
36
|
+
OR article.header_params = {'tags'=>tags}
|
37
|
+
|
38
|
+
### Operations
|
39
|
+
|
40
|
+
Create a new article :
|
41
|
+
|
42
|
+
article.create
|
43
|
+
|
44
|
+
Update an article :
|
45
|
+
|
46
|
+
article.update(oldfilename)
|
47
|
+
|
48
|
+
Read an article file
|
49
|
+
|
50
|
+
article.load_from_file(filename)
|
51
|
+
OR article.load_from_title(title, date)
|
52
|
+
|
53
|
+
After loading it you have access to the article attributes
|
54
|
+
|
55
|
+
List articles :
|
56
|
+
|
57
|
+
articles = blog.list_articles
|
58
|
+
|
59
|
+
## License
|
60
|
+
|
61
|
+
MIT, have fun
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/lib/writetheman.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require "date"
|
2
|
+
require "i18n"
|
3
|
+
require "pathname"
|
4
|
+
|
5
|
+
require "writetheman/version"
|
6
|
+
require "writetheman/path"
|
7
|
+
require "writetheman/blog"
|
8
|
+
require "writetheman/article/utils"
|
9
|
+
require "writetheman/article/access"
|
10
|
+
require "writetheman/article/content"
|
11
|
+
require "writetheman/article/file"
|
12
|
+
require "writetheman/article/base"
|
13
|
+
|
14
|
+
|
15
|
+
|
16
|
+
module Writetheman
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# Encoding: utf-8
|
2
|
+
module Writetheman
|
3
|
+
module Article
|
4
|
+
module Access
|
5
|
+
attr_accessor :title, :date
|
6
|
+
attr_reader :str_date
|
7
|
+
|
8
|
+
def init_filename
|
9
|
+
raise 'no extension to init filename' if @extension.nil? || @extension.empty?
|
10
|
+
@filename = filename_from_title if @filename.nil? || @filename.empty?
|
11
|
+
@filename += @extension if !@filename.include?('.')
|
12
|
+
end
|
13
|
+
|
14
|
+
def init_from_params(params)
|
15
|
+
raise 'params are empty to init' if params.nil? || params.empty?
|
16
|
+
remove_all!
|
17
|
+
@header_params = params['header']
|
18
|
+
@title = @header_params['title']
|
19
|
+
@body = params['body']
|
20
|
+
@date = DateTime.now if @date.nil?
|
21
|
+
end
|
22
|
+
|
23
|
+
def filename_from_title
|
24
|
+
raise 'no title to init filename' if @title.nil? || @title.empty?
|
25
|
+
raise 'no date to init filename' if @date.nil?
|
26
|
+
name = convert_title_to_filename
|
27
|
+
"#{format_date_file}-#{name}#{@extension}"
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def filemane_without_extension
|
32
|
+
@filename.match(/[^.]*/).to_s
|
33
|
+
end
|
34
|
+
|
35
|
+
def remove_access!
|
36
|
+
@title = ''
|
37
|
+
@date = nil
|
38
|
+
@str_date = ''
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def convert_title_to_filename
|
44
|
+
raise 'no title to convert' if @title.nil? || @title.empty?
|
45
|
+
I18n.transliterate(@title.gsub(" ", "-").gsub("'", "-").downcase)
|
46
|
+
end
|
47
|
+
|
48
|
+
def format_date_file
|
49
|
+
raise 'no date to format' if @date.nil?
|
50
|
+
@date.strftime("%Y-%m-%d")
|
51
|
+
end
|
52
|
+
|
53
|
+
def format_date_header
|
54
|
+
raise 'no date to format' if @date.nil?
|
55
|
+
@date.strftime("%Y-%m-%d %H:%M UTC")
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# Encoding: utf-8
|
2
|
+
module Writetheman
|
3
|
+
module Article
|
4
|
+
class Base
|
5
|
+
include Path
|
6
|
+
include Access
|
7
|
+
include Content
|
8
|
+
include File
|
9
|
+
include Utils
|
10
|
+
|
11
|
+
def initialize(path_application)
|
12
|
+
@path_application = path_application
|
13
|
+
@extension = ".html.markdown"
|
14
|
+
end
|
15
|
+
|
16
|
+
def create
|
17
|
+
init_header_from_params if @header.nil? || @header.empty?
|
18
|
+
init_content_from_header_body
|
19
|
+
init_filename if @filename.nil? || @filename.empty?
|
20
|
+
create_file
|
21
|
+
end
|
22
|
+
|
23
|
+
def create_from_params(params={})
|
24
|
+
remove_access!
|
25
|
+
init_from_params(params) if !params.empty?
|
26
|
+
create
|
27
|
+
end
|
28
|
+
|
29
|
+
def read
|
30
|
+
remove_content!
|
31
|
+
init_filename
|
32
|
+
read_file
|
33
|
+
init_header_body_from_content
|
34
|
+
@all_content
|
35
|
+
end
|
36
|
+
|
37
|
+
def load_from_file(filename)
|
38
|
+
remove_access!
|
39
|
+
@filename = filename
|
40
|
+
read
|
41
|
+
@title = @header_params['title']
|
42
|
+
@date = Date.parse(@header_params['date'])
|
43
|
+
end
|
44
|
+
|
45
|
+
def load_from_title(title, date)
|
46
|
+
remove_access!
|
47
|
+
@title = title
|
48
|
+
@date = date
|
49
|
+
read
|
50
|
+
end
|
51
|
+
|
52
|
+
def update(oldfilename)
|
53
|
+
delete_file(oldfilename)
|
54
|
+
create
|
55
|
+
end
|
56
|
+
|
57
|
+
def update_from_params(oldfilename, params={})
|
58
|
+
remove_access!
|
59
|
+
init_from_params(params) if !params.empty?
|
60
|
+
update(oldfilename)
|
61
|
+
end
|
62
|
+
|
63
|
+
def remove_all!
|
64
|
+
remove_access!
|
65
|
+
remove_content!
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# Encoding: utf-8
|
2
|
+
module Writetheman
|
3
|
+
module Article
|
4
|
+
module Content
|
5
|
+
attr_accessor :all_content, :body, :header, :header_params, :tags
|
6
|
+
|
7
|
+
def check_header_params_valid
|
8
|
+
raise "title is empty in header params #{@header_params}" if !@header_params.include?('title') || @header_params['title'].empty?
|
9
|
+
raise "date is empty in header params #{@header_params}" if !@header_params.include?('date') || @header_params['date'].empty?
|
10
|
+
end
|
11
|
+
|
12
|
+
def remove_content!
|
13
|
+
@all_content = ''
|
14
|
+
@body = ''
|
15
|
+
@header = ''
|
16
|
+
@header_params = {}
|
17
|
+
@tags = ''
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def init_header_from_params
|
23
|
+
init_header_params
|
24
|
+
@header = ""
|
25
|
+
@header_params.each_with_index do |(index, value), i|
|
26
|
+
@header += "#{index}: #{value}"
|
27
|
+
@header += "\n" if i < @header_params.count - 1
|
28
|
+
end
|
29
|
+
check_header_params_valid
|
30
|
+
@header
|
31
|
+
end
|
32
|
+
|
33
|
+
def init_content_from_header_body
|
34
|
+
raise 'no header to get content' if @header.nil? || @header.empty?
|
35
|
+
raise 'no body to get content' if @body.nil? || @body.empty?
|
36
|
+
@all_content = "---" + "\n" + @header + "\n" + "---" + "\n\n" + @body
|
37
|
+
end
|
38
|
+
|
39
|
+
def init_header_params
|
40
|
+
@header_params = {} if @header_params.nil?
|
41
|
+
@header_params['date'] = format_date_header if !header_params.include?('date')
|
42
|
+
@header_params['title'] = @title if !header_params.include?('title')
|
43
|
+
|
44
|
+
@title = @header_params['title'] if @title.nil?
|
45
|
+
@str_date = @header_params['date'] if @str_date.nil?
|
46
|
+
@tags = @header_params['tags'] if @header_params.include?('tags')
|
47
|
+
end
|
48
|
+
|
49
|
+
def init_header_params_from_content # get_header_params_from_content
|
50
|
+
ar_lines = get_header_lines_from_content
|
51
|
+
raise "no header lines from content #{@all_content}" if ar_lines.nil? || ar_lines.empty?
|
52
|
+
|
53
|
+
@header_params = {}
|
54
|
+
ar_lines.each do |value|
|
55
|
+
line_values = value.split(':', 2)
|
56
|
+
raise "line from header is invalid : #{line_values} from #{ar_lines}" if line_values.count != 2
|
57
|
+
@header_params[line_values[0]] = line_values[1].strip!
|
58
|
+
end
|
59
|
+
@header_params
|
60
|
+
end
|
61
|
+
|
62
|
+
def init_header_body_from_content
|
63
|
+
@header = get_header_from_content
|
64
|
+
raise "no header from content \n#{@all_content}" if @header.nil? || @header.empty?
|
65
|
+
@header_params = init_header_params_from_content
|
66
|
+
raise "no header params from header \n#{@header}\nand content \n#{@all_content}" if @header_params.nil? || @header_params.empty?
|
67
|
+
@body = get_body_from_content
|
68
|
+
raise "no body from content \n#{@all_content}" if @body.nil? || @body.empty?
|
69
|
+
end
|
70
|
+
|
71
|
+
def get_body_from_content
|
72
|
+
raise "content is empty" if @all_content.nil? || @all_content.empty?
|
73
|
+
begin
|
74
|
+
Utils::regex_body_from_content(@all_content).strip!
|
75
|
+
rescue Exception => e
|
76
|
+
raise "can't extract the body from content for the article #{@title} #{@filename} : \n#{e.message}"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def get_header_from_content
|
81
|
+
raise "content is empty" if @all_content.nil? || @all_content.empty?
|
82
|
+
begin
|
83
|
+
Utils::regex_header_from_content(@all_content)
|
84
|
+
rescue Exception => e
|
85
|
+
raise "can't extract the header from content for the article #{@title} #{@filename} : \n#{e.message}"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def get_header_lines_from_content
|
90
|
+
get_header_from_content.split("\n")
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# Encoding: utf-8
|
2
|
+
module Writetheman
|
3
|
+
module Article
|
4
|
+
module File
|
5
|
+
attr_accessor :filename, :extension
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def create_file
|
10
|
+
article_path = source_file_path
|
11
|
+
raise "File already exists : #{article_path}" if ::File.exist?(article_path)
|
12
|
+
raise "content is empty for create file #{@filename}" if @all_content.nil? || @all_content.empty?
|
13
|
+
file = ::File.open(article_path, 'w') { |f| f.write(@all_content) ; f.close }
|
14
|
+
end
|
15
|
+
|
16
|
+
def read_file
|
17
|
+
article_path = source_file_path
|
18
|
+
raise "File doesn't exist : #{article_path}" if !::File.exist?(article_path)
|
19
|
+
file = ::File.open(article_path, "rb")
|
20
|
+
@all_content = file.read
|
21
|
+
file.close
|
22
|
+
@all_content
|
23
|
+
end
|
24
|
+
|
25
|
+
def delete_file(filename='')
|
26
|
+
filename = @filename if filename.empty?
|
27
|
+
article_path = source_file_path(filename)
|
28
|
+
raise "File doesn't exist : #{article_path}" if !::File.exist?(article_path)
|
29
|
+
::File.delete article_path
|
30
|
+
end
|
31
|
+
|
32
|
+
def source_file_path(filename='')
|
33
|
+
filename = @filename if filename.empty?
|
34
|
+
raise "filename is empty" if filename.nil? || filename.empty?
|
35
|
+
check_path_source_blog
|
36
|
+
path_source_blog + '/' + filename
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Encoding: utf-8
|
2
|
+
module Writetheman
|
3
|
+
module Article
|
4
|
+
module Utils
|
5
|
+
REPLACE_CHARACTER = "|"
|
6
|
+
|
7
|
+
def self.regex_header_from_content(content)
|
8
|
+
#content = format_multibyte(content)
|
9
|
+
content.gsub("\n", REPLACE_CHARACTER).match(/---(.*)---/).to_s.gsub(REPLACE_CHARACTER, "\n")
|
10
|
+
.gsub("\r", "").gsub("---\n", "").gsub("\n---", "").gsub("---", "")
|
11
|
+
end
|
12
|
+
|
13
|
+
# if Windows-31J characters (don't need it with rich editor)
|
14
|
+
# ex problem of encoding : http://www.weeklystandard.com/articles/silicon-chasm_768037.html
|
15
|
+
# solution from http://stackoverflow.com/questions/225471/how-do-i-replace-accented-latin-characters-in-ruby
|
16
|
+
def self.encoding_from_windows(content)
|
17
|
+
return ActiveSupport::Multibyte::Chars.new(content).mb_chars.normalize(:kd).gsub(/[^\x00-\x7F]/n,'').to_s
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.special_encoding(content)
|
21
|
+
content = encoding_from_windows(content)
|
22
|
+
content
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.format_content_from_file(content)
|
26
|
+
content = special_encoding(content.force_encoding('utf-8')).gsub("\r", "")
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.regex_body_from_content(content)
|
30
|
+
content = format_content_from_file(content)
|
31
|
+
content.match(/$(\n---\n)\s*$(.*)/ms).to_s.gsub("\n---\n", "")
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Encoding: utf-8
|
2
|
+
module Writetheman
|
3
|
+
class Blog
|
4
|
+
include Path
|
5
|
+
|
6
|
+
def initialize(path_application)
|
7
|
+
@path_application = path_application
|
8
|
+
end
|
9
|
+
|
10
|
+
def new_article(filename='')
|
11
|
+
article = Article::Base.new(@path_application)
|
12
|
+
article.load_from_file(filename) if !filename.empty?
|
13
|
+
article
|
14
|
+
end
|
15
|
+
|
16
|
+
def list_articles
|
17
|
+
articles = []
|
18
|
+
list_source_files.each do |filepath|
|
19
|
+
articles << new_article(Pathname.new(filepath).basename.to_s)
|
20
|
+
end
|
21
|
+
articles
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Encoding: utf-8
|
2
|
+
module Writetheman
|
3
|
+
module Path
|
4
|
+
attr_accessor :path_application
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def path_source
|
9
|
+
raise "path application is empty" if @path_application.nil? || @path_application.empty?
|
10
|
+
@path_application + "/source"
|
11
|
+
end
|
12
|
+
|
13
|
+
def path_source_blog
|
14
|
+
path_source + "/blog"
|
15
|
+
end
|
16
|
+
|
17
|
+
def check_path_source_blog
|
18
|
+
raise "path application is empty" if @path_application.nil? || @path_application.empty?
|
19
|
+
raise "path source blog doesn't exist : #{path_source_blog}" if !::File.directory? path_source_blog
|
20
|
+
end
|
21
|
+
|
22
|
+
def list_source_files
|
23
|
+
sort_files(list_files)
|
24
|
+
end
|
25
|
+
|
26
|
+
def list_files(path=path_source_blog)
|
27
|
+
Dir.glob(::File.join(path, "*")).select { |f| File.file?(f) }
|
28
|
+
end
|
29
|
+
|
30
|
+
def sort_files(files)
|
31
|
+
files.sort_by{ |f| File.mtime(f) }.reverse
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Writetheman::Article::Access do
|
4
|
+
let(:article) { FactoryGirl.build( :article ) }
|
5
|
+
|
6
|
+
describe 'init filename' do
|
7
|
+
title = get_random_title
|
8
|
+
date = DateTime.now
|
9
|
+
filename = get_filename( title, date )
|
10
|
+
|
11
|
+
describe 'from title' do
|
12
|
+
it do
|
13
|
+
article.title = title
|
14
|
+
article.date = date
|
15
|
+
article.init_filename
|
16
|
+
article.filename.should eq( filename )
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe 'init params' do
|
22
|
+
title = get_random_title
|
23
|
+
date = DateTime.now
|
24
|
+
filename = get_filename( title, date )
|
25
|
+
filepath = get_filepath( filename )
|
26
|
+
tags = get_random_tags
|
27
|
+
header = get_header(title, tags, date)
|
28
|
+
header_params = get_header_params(title, tags, date)
|
29
|
+
body = get_random_body
|
30
|
+
content = get_content(header, body)
|
31
|
+
params = { 'header' => header_params, 'body' => body }
|
32
|
+
|
33
|
+
it do
|
34
|
+
article.init_from_params( params )
|
35
|
+
article.header_params.should eq(header_params)
|
36
|
+
article.title.should eq(title)
|
37
|
+
article.body.should eq(body)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe 'filename' do
|
42
|
+
describe 'set without extension' do
|
43
|
+
it do
|
44
|
+
filename_without_extention = "testfile"
|
45
|
+
filename = filename_without_extention + ".html.markdown"
|
46
|
+
article.filename = filename_without_extention
|
47
|
+
article.init_filename
|
48
|
+
article.filename.should eq(filename)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe 'get without extension' do
|
53
|
+
it do
|
54
|
+
filename_without_extention = "testfile"
|
55
|
+
filename = filename_without_extention + ".html.markdown"
|
56
|
+
article.filename = filename
|
57
|
+
article.filemane_without_extension.should eq(filename_without_extention)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,180 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Writetheman::Article::Base do
|
4
|
+
let(:article) { FactoryGirl.build( :article ) }
|
5
|
+
|
6
|
+
describe 'read' do
|
7
|
+
title = get_random_title
|
8
|
+
filename = get_filename( title )
|
9
|
+
filepath = get_filepath( filename )
|
10
|
+
tags = get_random_tags
|
11
|
+
date = DateTime.now
|
12
|
+
header = get_header(title, tags, date)
|
13
|
+
header_params = get_header_params(title, tags, date)
|
14
|
+
body = get_random_body
|
15
|
+
content = get_content(header, body)
|
16
|
+
|
17
|
+
before(:all) { file_create(filepath, content) }
|
18
|
+
after(:all) { file_delete(filepath) }
|
19
|
+
|
20
|
+
describe "header" do
|
21
|
+
describe "string" do
|
22
|
+
it do
|
23
|
+
article.title = title
|
24
|
+
article.date = date
|
25
|
+
article.read.should eq( content )
|
26
|
+
article.header.should eq( header )
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "params" do
|
31
|
+
it do
|
32
|
+
article.title = title
|
33
|
+
article.date = date
|
34
|
+
article.read.should eq( content )
|
35
|
+
article.header_params.should eq( header_params )
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "body" do
|
41
|
+
it do
|
42
|
+
article.title = title
|
43
|
+
article.date = date
|
44
|
+
article.read.should eq( content )
|
45
|
+
article.body.should eq( body )
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe 'load' do
|
51
|
+
title = get_random_title
|
52
|
+
date = DateTime.now
|
53
|
+
filename = get_filename( title, date )
|
54
|
+
filepath = get_filepath( filename )
|
55
|
+
tags = get_random_tags
|
56
|
+
header = get_header(title, tags, date)
|
57
|
+
header_params = get_header_params(title, tags, date)
|
58
|
+
body = get_random_body
|
59
|
+
content = get_content(header, body)
|
60
|
+
|
61
|
+
before(:all) { file_create(filepath, content) }
|
62
|
+
after(:all) { file_delete(filepath) }
|
63
|
+
|
64
|
+
describe 'from file' do
|
65
|
+
describe "access" do
|
66
|
+
it do
|
67
|
+
article.load_from_file(filename)
|
68
|
+
article.title.should eq(title)
|
69
|
+
article.date.strftime("%Y-%m-%d").should eq(date.strftime("%Y-%m-%d"))
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "content" do
|
74
|
+
it do
|
75
|
+
article.load_from_file(filename)
|
76
|
+
article.all_content.should eq( content )
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe 'from title' do
|
82
|
+
describe "access" do
|
83
|
+
it do
|
84
|
+
article.load_from_title(title, date)
|
85
|
+
article.title.should eq(title)
|
86
|
+
article.date.strftime("%Y-%m-%d").should eq(date.strftime("%Y-%m-%d"))
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "content" do
|
91
|
+
it do
|
92
|
+
article.load_from_title(title, date)
|
93
|
+
article.all_content.should eq( content )
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe 'create' do
|
100
|
+
describe 'from params' do
|
101
|
+
title = get_random_title
|
102
|
+
date = DateTime.now
|
103
|
+
filename = get_filename( title, date )
|
104
|
+
filepath = get_filepath( filename )
|
105
|
+
tags = get_random_tags
|
106
|
+
header = get_header(title, tags, date)
|
107
|
+
header_params = get_header_params(title, tags, date)
|
108
|
+
body = get_random_body
|
109
|
+
content = get_content(header, body)
|
110
|
+
params = { 'header' => header_params, 'body' => body }
|
111
|
+
|
112
|
+
before(:all) { file_delete(filepath) }
|
113
|
+
after(:all) { file_delete(filepath) }
|
114
|
+
|
115
|
+
it do
|
116
|
+
article.create_from_params( params )
|
117
|
+
|
118
|
+
File.exist?( filepath ).should be_true
|
119
|
+
File.open( filepath, "rb").read.should eq( content )
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe 'update' do
|
125
|
+
date = DateTime.now
|
126
|
+
oldtitle = get_random_title
|
127
|
+
oldfilename = get_filename( oldtitle, date )
|
128
|
+
oldfilepath = get_filepath( oldfilename )
|
129
|
+
oldcontent = get_content
|
130
|
+
newtitle = get_random_title
|
131
|
+
newfilename = get_filename( newtitle, date )
|
132
|
+
newfilepath = get_filepath( newfilename )
|
133
|
+
newtags = get_random_tags
|
134
|
+
newheader = get_header(newtitle, newtags, date)
|
135
|
+
newbody = get_random_body
|
136
|
+
newcontent = get_content( newheader, newbody )
|
137
|
+
newheader_params = get_header_params(newtitle, newtags, date)
|
138
|
+
newparams = { 'header' => newheader_params, 'body' => newbody }
|
139
|
+
|
140
|
+
describe 'from init' do
|
141
|
+
before(:all) { file_create(oldfilepath, oldcontent) }
|
142
|
+
after(:all) do
|
143
|
+
file_delete(oldfilepath)
|
144
|
+
file_delete(newfilepath)
|
145
|
+
end
|
146
|
+
|
147
|
+
it do
|
148
|
+
File.exist?( oldfilepath ).should be_true
|
149
|
+
File.open( oldfilepath, "rb").read.should_not eq( newcontent )
|
150
|
+
article.title = newtitle
|
151
|
+
article.date = date
|
152
|
+
article.header = newheader
|
153
|
+
article.body = newbody
|
154
|
+
article.update( oldfilename )
|
155
|
+
|
156
|
+
File.exist?( oldfilepath ).should be_false
|
157
|
+
File.exist?( newfilepath ).should be_true
|
158
|
+
File.open( newfilepath, "rb").read.should eq( newcontent )
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
describe "from params" do
|
163
|
+
before(:all) { file_create(oldfilepath, oldcontent) }
|
164
|
+
after(:all) do
|
165
|
+
file_delete(oldfilepath)
|
166
|
+
file_delete(newfilepath)
|
167
|
+
end
|
168
|
+
|
169
|
+
it do
|
170
|
+
File.exist?( oldfilepath ).should be_true
|
171
|
+
File.open( oldfilepath, "rb").read.should_not eq( newcontent )
|
172
|
+
|
173
|
+
article.update_from_params(oldfilename, newparams)
|
174
|
+
File.exist?( oldfilepath ).should be_false
|
175
|
+
File.exist?( newfilepath ).should be_true
|
176
|
+
File.open( newfilepath, "rb").read.should eq( newcontent )
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Writetheman::Article::File do
|
4
|
+
let(:article) { FactoryGirl.build( :article ) }
|
5
|
+
|
6
|
+
describe 'create' do
|
7
|
+
filename = get_filename
|
8
|
+
filepath = get_filepath( filename )
|
9
|
+
|
10
|
+
before(:all) { file_delete(filepath) }
|
11
|
+
after(:all) { file_delete(filepath) }
|
12
|
+
|
13
|
+
it do
|
14
|
+
content = get_content
|
15
|
+
article.filename = filename
|
16
|
+
article.all_content = content
|
17
|
+
File.exist?( filepath ).should be_false
|
18
|
+
article.send( :create_file )
|
19
|
+
|
20
|
+
File.exist?( filepath ).should be_true
|
21
|
+
File.open( filepath, "rb").read.should eq( content )
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'read' do
|
26
|
+
filename = get_filename
|
27
|
+
filepath = get_filepath( filename )
|
28
|
+
title = get_random_title
|
29
|
+
tags = get_random_tags
|
30
|
+
date = DateTime.now
|
31
|
+
header = get_header(title, tags, date)
|
32
|
+
header_params = get_header_params(title, tags, date)
|
33
|
+
content = get_content(header)
|
34
|
+
|
35
|
+
before(:all) { file_create(filepath, content) }
|
36
|
+
after(:all) { file_delete(filepath) }
|
37
|
+
|
38
|
+
describe "all" do
|
39
|
+
it do
|
40
|
+
article.filename = filename
|
41
|
+
article.send( :read_file ).should eq( content )
|
42
|
+
article.all_content.should eq( content )
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "header" do
|
47
|
+
describe "string" do
|
48
|
+
it do
|
49
|
+
article.filename = filename
|
50
|
+
article.send( :read_file ).should eq( content )
|
51
|
+
article.send( :get_header_from_content ).should eq( header )
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "params" do
|
56
|
+
it do
|
57
|
+
article.filename = filename
|
58
|
+
article.send( :read_file ).should eq( content )
|
59
|
+
article.send( :init_header_body_from_content )
|
60
|
+
article.header_params.should eq( header_params )
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "delete" do
|
67
|
+
filename = get_filename
|
68
|
+
filepath = get_filepath( filename )
|
69
|
+
|
70
|
+
describe "from init" do
|
71
|
+
before(:all) { file_create(filepath) }
|
72
|
+
after(:all) { file_delete(filepath) }
|
73
|
+
|
74
|
+
it do
|
75
|
+
article.filename = filename
|
76
|
+
article.send( :delete_file )
|
77
|
+
File.exist?( filepath ).should be_false
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "direct" do
|
82
|
+
before(:all) { file_create(filepath) }
|
83
|
+
after(:all) { file_delete(filepath) }
|
84
|
+
|
85
|
+
it do
|
86
|
+
article.send( :delete_file, filename )
|
87
|
+
File.exist?( filepath ).should be_false
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
data/spec/blog_spec.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Writetheman::Blog do
|
4
|
+
let(:blog) { FactoryGirl.build( :blog ) }
|
5
|
+
|
6
|
+
describe 'object' do
|
7
|
+
it { blog.should respond_to( :path_application ) }
|
8
|
+
end
|
9
|
+
|
10
|
+
describe 'paths' do
|
11
|
+
it { blog.path_application.should eq( PATH_APPLICATION ) }
|
12
|
+
it { blog.send( :path_source ).should eq( PATH_APPLICATION_SOURCE ) }
|
13
|
+
it { blog.send( :path_source_blog ).should eq( PATH_APPLICATION_SOURCE_BLOG ) }
|
14
|
+
it { blog.send( :check_path_source_blog ) }
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'list' do
|
18
|
+
tags = get_random_tags
|
19
|
+
date = DateTime.now
|
20
|
+
body = get_random_body
|
21
|
+
title1 = get_random_title
|
22
|
+
filename1 = get_filename(title1)
|
23
|
+
filepath1 = get_filepath(filename1)
|
24
|
+
header1 = get_header(title1, tags, date)
|
25
|
+
content1 = get_content(header1, body)
|
26
|
+
|
27
|
+
before(:all) do
|
28
|
+
file_create(filepath1, content1)
|
29
|
+
end
|
30
|
+
after(:all) do
|
31
|
+
file_delete(filepath1)
|
32
|
+
end
|
33
|
+
|
34
|
+
describe 'files' do
|
35
|
+
it do
|
36
|
+
files = blog.send( :list_source_files )
|
37
|
+
files.count.should eq(1)
|
38
|
+
files.should include(filepath1)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe 'articles' do
|
43
|
+
it do
|
44
|
+
articles = blog.list_articles
|
45
|
+
articles.count.should eq(1)
|
46
|
+
articles[0].title.should eq(title1)
|
47
|
+
articles[0].filename.should eq(filename1)
|
48
|
+
articles[0].all_content.should eq(content1)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
data/spec/factories.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'factory_girl'
|
2
|
+
require 'shared_values'
|
3
|
+
|
4
|
+
tmp_path = Dir.pwd + '/spec/tmp'
|
5
|
+
|
6
|
+
FactoryGirl.define do
|
7
|
+
factory :blog, class: Writetheman::Blog do
|
8
|
+
initialize_with { Writetheman::Blog.new(tmp_path) }
|
9
|
+
end
|
10
|
+
|
11
|
+
factory :article, class: Writetheman::Article::Base do
|
12
|
+
initialize_with { Writetheman::Article::Base.new(tmp_path) }
|
13
|
+
title { Faker::Lorem.sentence(3) }
|
14
|
+
date { DateTime.now }
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# Encoding: utf-8
|
2
|
+
|
3
|
+
PATH_APPLICATION = Dir.pwd + '/spec/tmp'
|
4
|
+
PATH_APPLICATION_SOURCE = PATH_APPLICATION + '/source'
|
5
|
+
PATH_APPLICATION_BUILD = PATH_APPLICATION + '/build'
|
6
|
+
PATH_APPLICATION_SOURCE_BLOG = PATH_APPLICATION_SOURCE + '/blog'
|
7
|
+
PATH_APPLICATION_BUILD_BLOG = PATH_APPLICATION_BUILD + '/blog'
|
8
|
+
|
9
|
+
def get_random_title(is_file=false)
|
10
|
+
title = Faker::Lorem.words(3)
|
11
|
+
is_file ? title = title.join('-') : title = title.join(' ')
|
12
|
+
title
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_random_tags
|
16
|
+
Faker::Lorem.words.join(', ')
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_random_body
|
20
|
+
'<p>'+Faker::Lorem.paragraphs(2).join("</p>\n<p>")+'é é</p>'
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
def get_filename(title=get_random_title(true), date=DateTime.now)
|
25
|
+
"#{date.strftime("%Y-%m-%d")}-#{title.gsub(" ", "-")}.html.markdown"
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_filepath(filename=get_filename)
|
29
|
+
raise "filename is empty" if filename.nil? || filename.empty?
|
30
|
+
PATH_APPLICATION_SOURCE_BLOG + "/" + filename
|
31
|
+
end
|
32
|
+
|
33
|
+
def get_date_header(date)
|
34
|
+
date.strftime("%Y-%m-%d %H:%M UTC")
|
35
|
+
end
|
36
|
+
|
37
|
+
def get_header(title=get_random_title, tags=get_random_tags, date=DateTime.now)
|
38
|
+
"title: " + title + "\ntags: " + tags + "\ndate: " + get_date_header(date)
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_header_params(title=get_random_title, tags=get_random_tags, date=DateTime.now)
|
42
|
+
{ 'title' => title, 'tags' => tags, 'date' => get_date_header(date) }
|
43
|
+
end
|
44
|
+
|
45
|
+
def get_content(header=get_header, body=get_random_body)
|
46
|
+
"---" + "\n" + header + "\n" + "---" + "\n\n" + body
|
47
|
+
end
|
48
|
+
|
49
|
+
def file_create(filepath, content=get_content)
|
50
|
+
raise "filepath is empty" if filepath.nil? || filepath.empty?
|
51
|
+
File.open( filepath, 'w' ) { |f| f.write( content ) ; f.close } if !File.exist?( filepath )
|
52
|
+
end
|
53
|
+
|
54
|
+
def file_delete(filepath)
|
55
|
+
raise "filepath is empty" if filepath.nil? || filepath.empty?
|
56
|
+
File.delete( filepath ) if File.exist?( filepath )
|
57
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require './lib/writetheman'
|
2
|
+
require 'factory_girl'
|
3
|
+
require 'faker'
|
4
|
+
require 'shared_values'
|
5
|
+
|
6
|
+
FactoryGirl.find_definitions
|
7
|
+
|
8
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
9
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
10
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
11
|
+
# loaded once.
|
12
|
+
#
|
13
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
14
|
+
RSpec.configure do |config|
|
15
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
16
|
+
config.run_all_when_everything_filtered = true
|
17
|
+
config.filter_run :focus
|
18
|
+
|
19
|
+
# Run specs in random order to surface order dependencies. If you find an
|
20
|
+
# order dependency and want to debug it, you can fix the order by providing
|
21
|
+
# the seed, which is printed after each run.
|
22
|
+
# --seed 1234
|
23
|
+
config.order = 'random'
|
24
|
+
end
|
data/writetheman.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'writetheman/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "writetheman"
|
8
|
+
spec.version = Writetheman::VERSION
|
9
|
+
spec.authors = ["davidtysman"]
|
10
|
+
spec.email = ["admin@davidtysman.com"]
|
11
|
+
spec.description = %q{Create, show and list articles for the middleman blog}
|
12
|
+
spec.summary = %q{Manage the middleman blog files}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
spec.add_development_dependency "faker"
|
25
|
+
spec.add_development_dependency "factory_girl"
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: writetheman
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.2'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- davidtysman
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-12-30 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1.3'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.3'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: faker
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: factory_girl
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
description: Create, show and list articles for the middleman blog
|
95
|
+
email:
|
96
|
+
- admin@davidtysman.com
|
97
|
+
executables: []
|
98
|
+
extensions: []
|
99
|
+
extra_rdoc_files: []
|
100
|
+
files:
|
101
|
+
- .gitignore
|
102
|
+
- .rspec
|
103
|
+
- Gemfile
|
104
|
+
- LICENSE.txt
|
105
|
+
- README.md
|
106
|
+
- Rakefile
|
107
|
+
- lib/writetheman.rb
|
108
|
+
- lib/writetheman/article/access.rb
|
109
|
+
- lib/writetheman/article/base.rb
|
110
|
+
- lib/writetheman/article/content.rb
|
111
|
+
- lib/writetheman/article/file.rb
|
112
|
+
- lib/writetheman/article/utils.rb
|
113
|
+
- lib/writetheman/blog.rb
|
114
|
+
- lib/writetheman/path.rb
|
115
|
+
- lib/writetheman/version.rb
|
116
|
+
- spec/article/access_spec.rb
|
117
|
+
- spec/article/base_spec.rb
|
118
|
+
- spec/article/file_spec.rb
|
119
|
+
- spec/article/utils_spec.rb
|
120
|
+
- spec/blog_spec.rb
|
121
|
+
- spec/factories.rb
|
122
|
+
- spec/shared_values.rb
|
123
|
+
- spec/spec_helper.rb
|
124
|
+
- writetheman.gemspec
|
125
|
+
homepage: ''
|
126
|
+
licenses:
|
127
|
+
- MIT
|
128
|
+
post_install_message:
|
129
|
+
rdoc_options: []
|
130
|
+
require_paths:
|
131
|
+
- lib
|
132
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
133
|
+
none: false
|
134
|
+
requirements:
|
135
|
+
- - ! '>='
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
139
|
+
none: false
|
140
|
+
requirements:
|
141
|
+
- - ! '>='
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '0'
|
144
|
+
requirements: []
|
145
|
+
rubyforge_project:
|
146
|
+
rubygems_version: 1.8.24
|
147
|
+
signing_key:
|
148
|
+
specification_version: 3
|
149
|
+
summary: Manage the middleman blog files
|
150
|
+
test_files:
|
151
|
+
- spec/article/access_spec.rb
|
152
|
+
- spec/article/base_spec.rb
|
153
|
+
- spec/article/file_spec.rb
|
154
|
+
- spec/article/utils_spec.rb
|
155
|
+
- spec/blog_spec.rb
|
156
|
+
- spec/factories.rb
|
157
|
+
- spec/shared_values.rb
|
158
|
+
- spec/spec_helper.rb
|