ruhoh 0.0.3 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +41 -0
- data/bin/ruhoh +6 -0
- data/lib/ruhoh/client/client.rb +26 -9
- data/lib/ruhoh/client/help.yml +4 -0
- data/lib/ruhoh/compiler.rb +7 -5
- data/lib/ruhoh/logger.rb +37 -0
- data/lib/ruhoh/page.rb +4 -4
- data/lib/ruhoh/parsers/pages.rb +9 -4
- data/lib/ruhoh/templaters/base.rb +12 -8
- data/lib/ruhoh/templaters/helpers.rb +59 -63
- data/lib/ruhoh/utils.rb +6 -1
- data/lib/ruhoh/version.rb +2 -1
- data/lib/ruhoh.rb +27 -18
- data/ruhoh.gemspec +1 -29
- data/spec/db_spec.rb +1 -1
- data/spec/page_spec.rb +1 -1
- data/spec/parsers/layouts_spec.rb +1 -1
- data/spec/parsers/pages_spec.rb +5 -5
- data/spec/parsers/posts_spec.rb +1 -1
- data/spec/parsers/routes_spec.rb +1 -1
- data/spec/parsers/site_spec.rb +1 -1
- data/system_partials/syntax/google_prettify +1 -1
- metadata +11 -39
- data/scaffolds/blog/_config.yml +0 -33
- data/scaffolds/blog/_drafts/.gitkeep +0 -0
- data/scaffolds/blog/_posts/.gitkeep +0 -0
- data/scaffolds/blog/_site.yml +0 -16
- data/scaffolds/blog/_templates/partials/categories_list +0 -3
- data/scaffolds/blog/_templates/partials/pages_list +0 -7
- data/scaffolds/blog/_templates/partials/posts_collate +0 -9
- data/scaffolds/blog/_templates/partials/posts_list +0 -1
- data/scaffolds/blog/_templates/partials/tags_list +0 -3
- data/scaffolds/blog/_templates/syntax/google_prettify/default.css +0 -52
- data/scaffolds/blog/_templates/syntax/google_prettify/desert.css +0 -34
- data/scaffolds/blog/_templates/syntax/google_prettify/sons-of-obsidian.css +0 -117
- data/scaffolds/blog/_templates/syntax/google_prettify/sunburst.css +0 -51
- data/scaffolds/blog/_templates/syntax/google_prettify/twitter-bootstrap.css +0 -30
- data/scaffolds/blog/_templates/themes/twitter/bootstrap/css/bootstrap.min.css +0 -689
- data/scaffolds/blog/_templates/themes/twitter/bootstrap/img/glyphicons-halflings-white.png +0 -0
- data/scaffolds/blog/_templates/themes/twitter/bootstrap/img/glyphicons-halflings.png +0 -0
- data/scaffolds/blog/_templates/themes/twitter/css/style.css +0 -68
- data/scaffolds/blog/_templates/themes/twitter/layouts/default.html +0 -64
- data/scaffolds/blog/_templates/themes/twitter/layouts/page.html +0 -13
- data/scaffolds/blog/_templates/themes/twitter/layouts/post.html +0 -55
- data/scaffolds/blog/_templates/themes/twitter/manifest.yml +0 -11
- data/scaffolds/blog/about.md +0 -5
- data/scaffolds/blog/archive.html +0 -11
- data/scaffolds/blog/categories.html +0 -21
- data/scaffolds/blog/config.ru +0 -9
- data/scaffolds/blog/index.html +0 -13
- data/scaffolds/blog/pages.html +0 -14
- data/scaffolds/blog/tags.html +0 -21
data/README.md
CHANGED
@@ -7,3 +7,44 @@
|
|
7
7
|
|
8
8
|
$ gem install ruhoh
|
9
9
|
$ ruhoh help
|
10
|
+
|
11
|
+
|
12
|
+
# SIMPLIFY SIMPLIFY SIMPLIFY
|
13
|
+
|
14
|
+
# Fronts
|
15
|
+
|
16
|
+
## ruhoh hosting
|
17
|
+
|
18
|
+
User Workflow:
|
19
|
+
|
20
|
+
- user auths with ruhoh.com
|
21
|
+
ruhoh expects a users blog to be in the GitHub repo: username.ruhoh.com
|
22
|
+
- user gives GitHub the ruhoh.com POST receive hook for his username.ruhoh.com repo
|
23
|
+
|
24
|
+
Implementation:
|
25
|
+
|
26
|
+
Sinatra app
|
27
|
+
handle POST requests from GitHub post receive hook.
|
28
|
+
oAuth via GitHub provider.
|
29
|
+
user accounts via GitHub oAuth.
|
30
|
+
wildcard domain name mapping: *.ruhoh.com
|
31
|
+
|
32
|
+
git clone/fetch repositories and compile the blog for hosting.
|
33
|
+
|
34
|
+
|
35
|
+
x] create server on linode
|
36
|
+
x] host sinatra app at app.ruhoh.com
|
37
|
+
send post receive hook to app.ruhoh.com
|
38
|
+
|
39
|
+
hook should trigger git clone if repo does not exist.
|
40
|
+
hook should trigger git pull/fetch if repo does exist
|
41
|
+
repo should compile after repo update
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
## Sbvtle
|
46
|
+
|
47
|
+
Adopt the admin UI at /\_drafts
|
48
|
+
|
49
|
+
|
50
|
+
|
data/bin/ruhoh
CHANGED
@@ -20,6 +20,12 @@ opt_parser = OptionParser.new do |opts|
|
|
20
20
|
options.verbose = v
|
21
21
|
end
|
22
22
|
|
23
|
+
opts.on("--version", "Display current gem and ruhoh specification versions.") do
|
24
|
+
puts "ruhoh " + Ruhoh::VERSION
|
25
|
+
puts "RuhohSpec " + Ruhoh::RuhohSpec
|
26
|
+
exit 0
|
27
|
+
end
|
28
|
+
|
23
29
|
end
|
24
30
|
opt_parser.parse!
|
25
31
|
|
data/lib/ruhoh/client/client.rb
CHANGED
@@ -3,7 +3,8 @@ require 'ruhoh/compiler'
|
|
3
3
|
class Ruhoh
|
4
4
|
class Client
|
5
5
|
|
6
|
-
Paths = Struct.new(:
|
6
|
+
Paths = Struct.new(:page_template, :post_template, :layout_template, :theme_template)
|
7
|
+
BlogScaffold = 'git://github.com/ruhoh/blog.git'
|
7
8
|
|
8
9
|
def initialize(data)
|
9
10
|
self.setup_paths
|
@@ -29,7 +30,6 @@ class Ruhoh
|
|
29
30
|
|
30
31
|
def setup_paths
|
31
32
|
@paths = Paths.new
|
32
|
-
@paths.blog_template = File.join(Ruhoh::Root, "scaffolds", "blog")
|
33
33
|
@paths.page_template = File.join(Ruhoh::Root, "scaffolds", "page.html")
|
34
34
|
@paths.post_template = File.join(Ruhoh::Root, "scaffolds", "post.html")
|
35
35
|
@paths.layout_template = File.join(Ruhoh::Root, "scaffolds", "layout.html")
|
@@ -60,7 +60,7 @@ class Ruhoh
|
|
60
60
|
def draft
|
61
61
|
filename = File.join(Ruhoh.paths.drafts, "#{Time.now.to_i}.#{@options.ext}")
|
62
62
|
if File.exist?(filename)
|
63
|
-
sleep 1 ; self.
|
63
|
+
sleep 1 ; self.draft(args) ; exit
|
64
64
|
end
|
65
65
|
|
66
66
|
FileUtils.mkdir_p File.dirname(filename)
|
@@ -73,6 +73,7 @@ class Ruhoh
|
|
73
73
|
Ruhoh::Friend.say {
|
74
74
|
green "New draft:"
|
75
75
|
green Ruhoh.relative_path(filename)
|
76
|
+
green 'View drafts at the URL: /_drafts'
|
76
77
|
}
|
77
78
|
end
|
78
79
|
|
@@ -129,7 +130,7 @@ class Ruhoh
|
|
129
130
|
exit
|
130
131
|
} if (name.nil? || name.gsub(/\s/, '').empty?)
|
131
132
|
|
132
|
-
filename = File.join(Ruhoh.paths.
|
133
|
+
filename = File.join(Ruhoh.paths.pages, name.gsub(/\s/, '-'))
|
133
134
|
filename = File.join(filename, "index.#{@options.ext}") if File.extname(filename) == ""
|
134
135
|
if File.exist?(filename)
|
135
136
|
abort("Create new page: aborted!") if ask("#{filename} already exists. Do you want to overwrite?", ['y', 'n']) == 'n'
|
@@ -169,13 +170,20 @@ class Ruhoh
|
|
169
170
|
plain " Specify another directory or `rm -rf` this directory first."
|
170
171
|
exit
|
171
172
|
} if File.exist?(target_directory)
|
172
|
-
|
173
|
-
FileUtils.mkdir target_directory
|
174
|
-
FileUtils.cp_r "#{@paths.blog_template}/.", target_directory
|
175
173
|
|
176
174
|
Ruhoh::Friend.say {
|
177
|
-
|
178
|
-
|
175
|
+
plain "Trying this command:"
|
176
|
+
cyan " git clone #{BlogScaffold} #{target_directory}"
|
177
|
+
|
178
|
+
if system('git', 'clone', BlogScaffold, target_directory)
|
179
|
+
green "Success! Now do..."
|
180
|
+
cyan " cd #{target_directory}"
|
181
|
+
cyan " rackup -p9292"
|
182
|
+
cyan " http://localhost:9292"
|
183
|
+
else
|
184
|
+
red "Could not git clone blog scaffold. Please try it manually:"
|
185
|
+
cyan " git clone git://github.com/ruhoh/blog.git #{target_directory}"
|
186
|
+
end
|
179
187
|
}
|
180
188
|
end
|
181
189
|
|
@@ -245,6 +253,15 @@ class Ruhoh
|
|
245
253
|
self.list(:pages)
|
246
254
|
end
|
247
255
|
|
256
|
+
# Return the payload hash for inspection/study.
|
257
|
+
def payload
|
258
|
+
require 'pp'
|
259
|
+
Ruhoh::DB.update!
|
260
|
+
Ruhoh::Friend.say {
|
261
|
+
plain Ruhoh::Templaters::Base.build_payload.pretty_inspect
|
262
|
+
}
|
263
|
+
end
|
264
|
+
|
248
265
|
# Internal: Outputs a list of the given data-type to the terminal.
|
249
266
|
def list(type)
|
250
267
|
Ruhoh::DB.update(type)
|
data/lib/ruhoh/client/help.yml
CHANGED
@@ -42,6 +42,10 @@ commands:
|
|
42
42
|
"command" : "pages"
|
43
43
|
"desc" : |
|
44
44
|
List all pages.
|
45
|
+
-
|
46
|
+
"command" : "payload"
|
47
|
+
"desc" : |
|
48
|
+
List the full payload hash as given to the templater. Note page is blank for example purposes.
|
45
49
|
-
|
46
50
|
"command" : "layout <name>"
|
47
51
|
"desc" : |
|
data/lib/ruhoh/compiler.rb
CHANGED
@@ -8,18 +8,18 @@ class Ruhoh
|
|
8
8
|
@page = Ruhoh::Page.new
|
9
9
|
end
|
10
10
|
|
11
|
+
# TODO: seems rather dangerous to delete the incoming target directory?
|
11
12
|
def compile
|
12
13
|
FileUtils.rm_r @target if File.exist?(@target)
|
13
|
-
FileUtils.
|
14
|
+
FileUtils.mkdir_p @target
|
14
15
|
self.theme
|
15
16
|
self.pages
|
16
17
|
self.media
|
17
18
|
self.syntax
|
19
|
+
true
|
18
20
|
end
|
19
21
|
|
20
22
|
def pages
|
21
|
-
processed = []
|
22
|
-
|
23
23
|
FileUtils.cd(@target) {
|
24
24
|
Ruhoh::DB.posts['dictionary'].merge(Ruhoh::DB.pages).each_value do |p|
|
25
25
|
@page.change(p['id'])
|
@@ -27,7 +27,6 @@ class Ruhoh
|
|
27
27
|
FileUtils.mkdir_p File.dirname(@page.compiled_path)
|
28
28
|
File.open(@page.compiled_path, 'w') { |p| p.puts @page.render }
|
29
29
|
|
30
|
-
processed << p
|
31
30
|
Ruhoh::Friend.say { green "processed: #{p['id']}" }
|
32
31
|
end
|
33
32
|
}
|
@@ -35,16 +34,19 @@ class Ruhoh
|
|
35
34
|
end
|
36
35
|
|
37
36
|
def theme
|
37
|
+
return unless FileTest.directory? Ruhoh.paths.theme
|
38
38
|
FileUtils.mkdir_p File.join(@target, Ruhoh.config.theme_path)
|
39
39
|
FileUtils.cp_r Ruhoh.paths.theme, File.join(@target, Ruhoh.folders.templates, Ruhoh.folders.themes)
|
40
40
|
end
|
41
41
|
|
42
42
|
def media
|
43
|
+
return unless FileTest.directory? Ruhoh.paths.media
|
43
44
|
FileUtils.mkdir_p File.join(@target, Ruhoh.folders.media)
|
44
|
-
FileUtils.cp_r Ruhoh.paths.media, @target
|
45
|
+
FileUtils.cp_r Ruhoh.paths.media, @target
|
45
46
|
end
|
46
47
|
|
47
48
|
def syntax
|
49
|
+
return unless FileTest.directory? Ruhoh.paths.syntax
|
48
50
|
syntax_path = File.join(@target, Ruhoh.folders.templates, Ruhoh.folders.syntax)
|
49
51
|
FileUtils.mkdir_p syntax_path
|
50
52
|
FileUtils.cp_r "#{Ruhoh.paths.syntax}/.", syntax_path
|
data/lib/ruhoh/logger.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
class Ruhoh
|
2
|
+
class Logger
|
3
|
+
|
4
|
+
attr_reader :buffer
|
5
|
+
attr_accessor :log_file
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@buffer = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def error(string=nil)
|
12
|
+
message = ""
|
13
|
+
message << string if string
|
14
|
+
message << "\n" unless message[-1] == ?\n
|
15
|
+
@buffer << message
|
16
|
+
|
17
|
+
self.on_error
|
18
|
+
end
|
19
|
+
|
20
|
+
def on_error
|
21
|
+
msg = @buffer[0]
|
22
|
+
Ruhoh::Friend.say { red msg }
|
23
|
+
self.to_file
|
24
|
+
exit -1
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_file
|
28
|
+
return unless self.log_file && @buffer.size > 0
|
29
|
+
File.open(self.log_file, "a") { |f|
|
30
|
+
f.puts '---'
|
31
|
+
f.puts Time.now.utc
|
32
|
+
f.puts @buffer.slice!(0..-1).join
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
end #Logger
|
37
|
+
end #Ruhoh
|
data/lib/ruhoh/page.rb
CHANGED
@@ -12,12 +12,13 @@ class Ruhoh
|
|
12
12
|
# Public: Change this page using an id.
|
13
13
|
def change(id)
|
14
14
|
@data = nil
|
15
|
-
|
15
|
+
@path = id
|
16
16
|
@data = if id =~ Regexp.new("^#{Ruhoh.folders.posts}")
|
17
17
|
Ruhoh::DB.posts['dictionary'][id]
|
18
18
|
elsif id =~ Regexp.new("^#{Ruhoh.folders.drafts}")
|
19
19
|
Ruhoh::DB.drafts[id]
|
20
20
|
else
|
21
|
+
@path = "#{Ruhoh.folders.pages}/#{id}"
|
21
22
|
Ruhoh::DB.pages[id]
|
22
23
|
end
|
23
24
|
|
@@ -32,7 +33,6 @@ class Ruhoh
|
|
32
33
|
else
|
33
34
|
Ruhoh::DB.routes[url]
|
34
35
|
end
|
35
|
-
|
36
36
|
raise "Page id not found for url: #{url}" unless id
|
37
37
|
self.change(id)
|
38
38
|
end
|
@@ -62,8 +62,8 @@ class Ruhoh
|
|
62
62
|
# Converters (markdown) always choke on the templating language.
|
63
63
|
def process_content
|
64
64
|
raise "ID is null: Id must be set via page.change(id) or page.change_with_url(url)" if @id.nil?
|
65
|
-
data = Ruhoh::Utils.parse_file(Ruhoh.paths.site_source, @
|
66
|
-
raise "Invalid Frontmatter in page: #{@
|
65
|
+
data = Ruhoh::Utils.parse_file(Ruhoh.paths.site_source, @path)
|
66
|
+
raise "Invalid Frontmatter in page: #{@path}" if data.empty?
|
67
67
|
|
68
68
|
@content = @templater.parse(data['content'], self)
|
69
69
|
@content = @converter.convert(self)
|
data/lib/ruhoh/parsers/pages.rb
CHANGED
@@ -14,17 +14,18 @@ class Ruhoh
|
|
14
14
|
dictionary = {}
|
15
15
|
|
16
16
|
pages.each do |filename|
|
17
|
+
id = self.make_id(filename)
|
17
18
|
parsed_page = Ruhoh::Utils.parse_file(filename)
|
18
19
|
if parsed_page.empty?
|
19
20
|
error = "Invalid Yaml Front Matter.\n Ensure this page has valid YAML, even if it's empty."
|
20
21
|
invalid << [filename, error] ; next
|
21
22
|
end
|
22
23
|
|
23
|
-
parsed_page['data']['id'] =
|
24
|
+
parsed_page['data']['id'] = id
|
24
25
|
parsed_page['data']['url'] = self.permalink(parsed_page['data'])
|
25
26
|
parsed_page['data']['title'] = parsed_page['data']['title'] || self.titleize(filename)
|
26
27
|
|
27
|
-
dictionary[
|
28
|
+
dictionary[id] = parsed_page['data']
|
28
29
|
end
|
29
30
|
|
30
31
|
report = "#{pages.count - invalid.count }/#{pages.count} pages processed."
|
@@ -45,7 +46,7 @@ class Ruhoh
|
|
45
46
|
|
46
47
|
def self.files
|
47
48
|
FileUtils.cd(Ruhoh.paths.site_source) {
|
48
|
-
return Dir["
|
49
|
+
return Dir["#{Ruhoh.folders.pages}/**/*.*"].select { |filename|
|
49
50
|
next unless self.is_valid_page?(filename)
|
50
51
|
true
|
51
52
|
}
|
@@ -54,12 +55,16 @@ class Ruhoh
|
|
54
55
|
|
55
56
|
def self.is_valid_page?(filepath)
|
56
57
|
return false if FileTest.directory?(filepath)
|
57
|
-
return false if ['
|
58
|
+
return false if ['.'].include? filepath[0]
|
58
59
|
return false if Ruhoh.filters.pages['names'].include? filepath
|
59
60
|
Ruhoh.filters.pages['regexes'].each {|regex| return false if filepath =~ regex }
|
60
61
|
true
|
61
62
|
end
|
62
63
|
|
64
|
+
def self.make_id(filename)
|
65
|
+
filename.gsub(Regexp.new("^#{Ruhoh.folders.pages}/"), '')
|
66
|
+
end
|
67
|
+
|
63
68
|
def self.titleize(filename)
|
64
69
|
name = File.basename( filename, File.extname(filename) )
|
65
70
|
name = filename.split('/')[-2] if name == 'index' && !filename.index('/').nil?
|
@@ -4,15 +4,19 @@ class Ruhoh
|
|
4
4
|
|
5
5
|
module Base
|
6
6
|
|
7
|
-
def self.build_payload(page)
|
7
|
+
def self.build_payload(page=nil)
|
8
8
|
{
|
9
|
-
"
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
"
|
14
|
-
"
|
15
|
-
"
|
9
|
+
"db" => {
|
10
|
+
"pages" => Ruhoh::DB.pages,
|
11
|
+
"posts" => Ruhoh::DB.posts,
|
12
|
+
},
|
13
|
+
"page" => (page ? page.attributes : {}),
|
14
|
+
"site" => Ruhoh::DB.site,
|
15
|
+
"paths" => {
|
16
|
+
"theme" => Ruhoh.config.theme_path,
|
17
|
+
"syntax" => Ruhoh.config.syntax_path,
|
18
|
+
"media" => Ruhoh.config.media_path
|
19
|
+
}
|
16
20
|
}
|
17
21
|
end
|
18
22
|
|
@@ -1,15 +1,35 @@
|
|
1
1
|
require 'pp'
|
2
2
|
|
3
3
|
class Ruhoh
|
4
|
-
|
5
4
|
module Templaters
|
6
|
-
|
7
5
|
module Helpers
|
8
|
-
|
6
|
+
|
9
7
|
def partial(name)
|
10
8
|
Ruhoh::DB.partials[name.to_s]
|
11
9
|
end
|
12
|
-
|
10
|
+
|
11
|
+
def pages
|
12
|
+
pages = []
|
13
|
+
self.context['db']['pages'].each_value {|page| pages << page }
|
14
|
+
self.mark_active_page(pages)
|
15
|
+
end
|
16
|
+
|
17
|
+
def posts
|
18
|
+
self.to_posts(self.context['db']['posts']['chronological'])
|
19
|
+
end
|
20
|
+
|
21
|
+
def categories
|
22
|
+
cats = []
|
23
|
+
self.context['db']['posts']['categories'].each_value { |cat| cats << cat }
|
24
|
+
cats
|
25
|
+
end
|
26
|
+
|
27
|
+
def tags
|
28
|
+
tags = []
|
29
|
+
self.context['db']['posts']['categories'].each_value { |tag| tags << tag }
|
30
|
+
tags
|
31
|
+
end
|
32
|
+
|
13
33
|
def raw_code(sub_context)
|
14
34
|
code = sub_context.gsub('{', '{').gsub('}', '}').gsub('<', '<').gsub('>', '>')
|
15
35
|
"<pre><code>#{code}</code></pre>"
|
@@ -25,84 +45,51 @@ class Ruhoh
|
|
25
45
|
"<pre>#{sub_context.class}\n#{sub_context.pretty_inspect}</pre>"
|
26
46
|
end
|
27
47
|
|
28
|
-
def to_tags(sub_context)
|
29
|
-
if sub_context.is_a?(Array)
|
30
|
-
sub_context.map { |id|
|
31
|
-
self.context['_posts']['tags'][id] if self.context['_posts']['tags'][id]
|
32
|
-
}
|
33
|
-
else
|
34
|
-
tags = []
|
35
|
-
self.context['_posts']['tags'].each_value { |tag|
|
36
|
-
tags << tag
|
37
|
-
}
|
38
|
-
tags
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
48
|
def to_posts(sub_context)
|
43
|
-
sub_context
|
44
|
-
|
45
|
-
|
46
|
-
self.context['_posts']['dictionary'][id] if self.context['_posts']['dictionary'][id]
|
47
|
-
}
|
49
|
+
Array(sub_context).map { |id|
|
50
|
+
self.context['db']['posts']['dictionary'][id]
|
51
|
+
}.compact
|
48
52
|
end
|
49
53
|
|
50
54
|
def to_pages(sub_context)
|
51
|
-
pages =
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
pages << self.context[:pages][id]
|
56
|
-
end
|
57
|
-
end
|
58
|
-
else
|
59
|
-
self.context[:pages].each_value {|page| pages << page }
|
60
|
-
end
|
61
|
-
|
62
|
-
pages.each_with_index do |page, i|
|
63
|
-
next unless page['id'] == self.context[:page]['id']
|
64
|
-
active_page = page.dup
|
65
|
-
active_page['is_active_page'] = true
|
66
|
-
pages[i] = active_page
|
67
|
-
end
|
68
|
-
|
69
|
-
pages
|
55
|
+
pages = Array(sub_context).map { |id|
|
56
|
+
self.context['db']['pages'][id]
|
57
|
+
}.compact
|
58
|
+
self.mark_active_page(pages)
|
70
59
|
end
|
71
|
-
|
60
|
+
|
72
61
|
def to_categories(sub_context)
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
}
|
77
|
-
else
|
78
|
-
cats = []
|
79
|
-
self.context['_posts']['categories'].each_value { |cat|
|
80
|
-
cats << cat
|
81
|
-
}
|
82
|
-
cats
|
83
|
-
end
|
62
|
+
Array(sub_context).map { |id|
|
63
|
+
self.context['db']['posts']['categories'][id]
|
64
|
+
}.compact
|
84
65
|
end
|
85
|
-
|
66
|
+
|
67
|
+
def to_tags(sub_context)
|
68
|
+
Array(sub_context).map { |id|
|
69
|
+
self.context['db']['posts']['tags'][id]
|
70
|
+
}.compact
|
71
|
+
end
|
72
|
+
|
86
73
|
def next(sub_context)
|
87
74
|
return unless sub_context.is_a?(String) || sub_context.is_a?(Hash)
|
88
75
|
id = sub_context.is_a?(Hash) ? sub_context['id'] : sub_context
|
89
76
|
return unless id
|
90
|
-
index = self.context['
|
77
|
+
index = self.context['db']['posts']['chronological'].index(id)
|
91
78
|
return unless index && (index-1 >= 0)
|
92
|
-
next_id = self.context['
|
79
|
+
next_id = self.context['db']['posts']['chronological'][index-1]
|
93
80
|
return unless next_id
|
94
|
-
self.to_posts(
|
81
|
+
self.to_posts(next_id)
|
95
82
|
end
|
96
83
|
|
97
84
|
def previous(sub_context)
|
98
85
|
return unless sub_context.is_a?(String) || sub_context.is_a?(Hash)
|
99
86
|
id = sub_context.is_a?(Hash) ? sub_context['id'] : sub_context
|
100
87
|
return unless id
|
101
|
-
index = self.context['
|
88
|
+
index = self.context['db']['posts']['chronological'].index(id)
|
102
89
|
return unless index && (index+1 >= 0)
|
103
|
-
prev_id = self.context['
|
90
|
+
prev_id = self.context['db']['posts']['chronological'][index+1]
|
104
91
|
return unless prev_id
|
105
|
-
self.to_posts(
|
92
|
+
self.to_posts(prev_id)
|
106
93
|
end
|
107
94
|
|
108
95
|
def analytics
|
@@ -152,8 +139,17 @@ class Ruhoh
|
|
152
139
|
self.render(code)
|
153
140
|
end
|
154
141
|
|
142
|
+
# Marks the active page if exists in the given pages Array
|
143
|
+
def mark_active_page(pages)
|
144
|
+
pages.each_with_index do |page, i|
|
145
|
+
next unless page['id'] == self.context[:page]['id']
|
146
|
+
active_page = page.dup
|
147
|
+
active_page['is_active_page'] = true
|
148
|
+
pages[i] = active_page
|
149
|
+
end
|
150
|
+
pages
|
151
|
+
end
|
152
|
+
|
155
153
|
end #Helpers
|
156
|
-
|
157
154
|
end #Templaters
|
158
|
-
|
159
155
|
end #Ruhoh
|
data/lib/ruhoh/utils.rb
CHANGED
@@ -12,8 +12,10 @@ class Ruhoh
|
|
12
12
|
file = File.open(filepath)
|
13
13
|
yaml = YAML.load(file) || {}
|
14
14
|
file.close
|
15
|
-
|
16
15
|
yaml
|
16
|
+
rescue Psych::SyntaxError => e
|
17
|
+
Ruhoh.log.error("ERROR in #{filepath}: #{e.message}")
|
18
|
+
nil
|
17
19
|
end
|
18
20
|
|
19
21
|
def self.parse_file(*args)
|
@@ -33,6 +35,9 @@ class Ruhoh
|
|
33
35
|
"data" => self.format_meta(data),
|
34
36
|
"content" => page.gsub(FMregex, '')
|
35
37
|
}
|
38
|
+
rescue Psych::SyntaxError => e
|
39
|
+
Ruhoh.log.error("ERROR in #{path}: #{e.message}")
|
40
|
+
nil
|
36
41
|
end
|
37
42
|
|
38
43
|
def self.format_meta(data)
|
data/lib/ruhoh/version.rb
CHANGED
data/lib/ruhoh.rb
CHANGED
@@ -6,6 +6,7 @@ require 'fileutils'
|
|
6
6
|
|
7
7
|
require 'mustache'
|
8
8
|
|
9
|
+
require 'ruhoh/logger'
|
9
10
|
require 'ruhoh/utils'
|
10
11
|
require 'ruhoh/friend'
|
11
12
|
require 'ruhoh/parsers/drafts'
|
@@ -26,17 +27,23 @@ require 'ruhoh/watch'
|
|
26
27
|
|
27
28
|
class Ruhoh
|
28
29
|
|
29
|
-
class << self
|
30
|
+
class << self
|
31
|
+
attr_accessor :log
|
32
|
+
attr_reader :folders, :files, :config, :paths, :filters
|
33
|
+
end
|
34
|
+
|
35
|
+
@log = Ruhoh::Logger.new
|
30
36
|
|
31
37
|
Root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
32
38
|
DefaultExclude = ['Gemfile', 'Gemfile.lock', 'config.ru', 'README.md']
|
33
|
-
Folders = Struct.new(:database, :posts, :drafts, :templates, :themes, :layouts, :partials, :media, :syntax, :compiled)
|
39
|
+
Folders = Struct.new(:database, :pages, :posts, :drafts, :templates, :themes, :layouts, :partials, :media, :syntax, :compiled)
|
34
40
|
Files = Struct.new(:site, :config)
|
35
41
|
Filters = Struct.new(:posts, :pages, :static)
|
36
42
|
Config = Struct.new(:permalink, :theme, :theme_path, :media_path, :syntax_path, :exclude)
|
37
43
|
Paths = Struct.new(
|
38
44
|
:site_source,
|
39
45
|
:database,
|
46
|
+
:pages,
|
40
47
|
:posts,
|
41
48
|
:drafts,
|
42
49
|
:theme,
|
@@ -49,20 +56,18 @@ class Ruhoh
|
|
49
56
|
)
|
50
57
|
|
51
58
|
|
52
|
-
# Public: Setup Ruhoh utilities relative to the current directory
|
53
|
-
#
|
54
|
-
|
55
|
-
|
59
|
+
# Public: Setup Ruhoh utilities relative to the current application directory.
|
60
|
+
# Returns boolean on success/failure
|
61
|
+
def self.setup(opts={})
|
62
|
+
@log.log_file = opts[:log_file] if opts[:log_file]
|
56
63
|
self.reset
|
64
|
+
@site_source = opts[:source] if opts[:source]
|
57
65
|
|
58
|
-
|
59
|
-
self.setup_config
|
60
|
-
self.setup_paths
|
61
|
-
self.setup_filters
|
66
|
+
!!(self.setup_config && self.setup_paths && self.setup_filters)
|
62
67
|
end
|
63
68
|
|
64
69
|
def self.reset
|
65
|
-
@folders = Folders.new('_database', '_posts', '_drafts', '_templates', 'themes', 'layouts', 'partials', "_media", "syntax", '_compiled')
|
70
|
+
@folders = Folders.new('_database', '_pages', '_posts', '_drafts', '_templates', 'themes', 'layouts', 'partials', "_media", "syntax", '_compiled')
|
66
71
|
@files = Files.new('_site.yml', '_config.yml')
|
67
72
|
@filters = Filters.new
|
68
73
|
@config = Config.new
|
@@ -72,17 +77,18 @@ class Ruhoh
|
|
72
77
|
|
73
78
|
def self.setup_config
|
74
79
|
site_config = Ruhoh::Utils.parse_file_as_yaml(@site_source, @files.config)
|
80
|
+
|
75
81
|
unless site_config
|
76
|
-
Ruhoh
|
77
|
-
|
78
|
-
red "Please ensure ./#{Ruhoh.files.config} exists and contains valid YAML"
|
79
|
-
}
|
80
|
-
exit
|
82
|
+
Ruhoh.log.error("Empty site_config.\nEnsure ./#{Ruhoh.files.config} exists and contains valid YAML")
|
83
|
+
return false
|
81
84
|
end
|
82
85
|
|
83
86
|
theme = site_config['theme'] ? site_config['theme'].to_s.gsub(/\s/, '') : ''
|
84
|
-
|
85
|
-
|
87
|
+
if theme.empty?
|
88
|
+
Ruhoh.log.error("Theme not specified in _config.yml")
|
89
|
+
return false
|
90
|
+
end
|
91
|
+
|
86
92
|
@config.theme = theme
|
87
93
|
@config.theme_path = File.join('/', @folders.templates, @folders.themes, @config.theme)
|
88
94
|
@config.media_path = File.join('/', @folders.media)
|
@@ -94,6 +100,7 @@ class Ruhoh
|
|
94
100
|
def self.setup_paths
|
95
101
|
@paths.site_source = @site_source
|
96
102
|
@paths.database = self.absolute_path(@folders.database)
|
103
|
+
@paths.pages = self.absolute_path(@folders.pages)
|
97
104
|
@paths.posts = self.absolute_path(@folders.posts)
|
98
105
|
@paths.drafts = self.absolute_path(@folders.drafts)
|
99
106
|
|
@@ -104,6 +111,7 @@ class Ruhoh
|
|
104
111
|
@paths.media = self.absolute_path(@folders.media)
|
105
112
|
@paths.syntax = self.absolute_path(@folders.templates, @folders.syntax)
|
106
113
|
@paths.compiled = self.absolute_path(@folders.compiled)
|
114
|
+
@paths
|
107
115
|
end
|
108
116
|
|
109
117
|
# filename filters
|
@@ -116,6 +124,7 @@ class Ruhoh
|
|
116
124
|
@filters.pages['names'] << node if node.is_a?(String)
|
117
125
|
@filters.pages['regexes'] << node if node.is_a?(Regexp)
|
118
126
|
}
|
127
|
+
@filters
|
119
128
|
end
|
120
129
|
|
121
130
|
def self.absolute_path(*args)
|