writetheman 0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in writetheman.gemspec
4
+ gemspec
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"
@@ -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,3 @@
1
+ module Writetheman
2
+ VERSION = "0.2"
3
+ 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
@@ -0,0 +1,6 @@
1
+ require 'spec_helper'
2
+
3
+ describe Writetheman::Article::Utils do
4
+ let(:article) { FactoryGirl.build( :article ) }
5
+
6
+ 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>")+'&eacute; &eacute;</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
@@ -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
@@ -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