writetheman 0.2

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,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