ruhoh 0.3.0 → 1.0.0.alpha
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/Gemfile +1 -0
- data/README.md +0 -33
- data/dash.html +1 -0
- data/history.json +29 -0
- data/lib/ruhoh/client/client.rb +30 -22
- data/lib/ruhoh/client/help.yml +6 -2
- data/lib/ruhoh/compiler.rb +8 -20
- data/lib/ruhoh/compilers/rss.rb +36 -0
- data/lib/ruhoh/compilers/theme.rb +41 -0
- data/lib/ruhoh/config.rb +49 -0
- data/lib/ruhoh/converters/converter.rb +17 -4
- data/lib/ruhoh/converters/markdown.rb +2 -2
- data/lib/ruhoh/db.rb +29 -2
- data/lib/ruhoh/deployers/s3.rb +1 -1
- data/lib/ruhoh/logger.rb +1 -1
- data/lib/ruhoh/page.rb +38 -22
- data/lib/ruhoh/parsers/javascripts.rb +67 -0
- data/lib/ruhoh/parsers/layouts.rb +6 -10
- data/lib/ruhoh/parsers/pages.rb +17 -24
- data/lib/ruhoh/parsers/partials.rb +6 -14
- data/lib/ruhoh/parsers/payload.rb +47 -0
- data/lib/ruhoh/parsers/posts.rb +27 -29
- data/lib/ruhoh/parsers/site.rb +2 -2
- data/lib/ruhoh/parsers/stylesheets.rb +75 -0
- data/lib/ruhoh/parsers/widgets.rb +104 -0
- data/lib/ruhoh/paths.rb +75 -0
- data/lib/ruhoh/previewer.rb +11 -5
- data/lib/ruhoh/program.rb +35 -4
- data/lib/ruhoh/templaters/asset_helpers.rb +66 -0
- data/lib/ruhoh/templaters/base_helpers.rb +143 -0
- data/lib/ruhoh/templaters/helpers.rb +1 -148
- data/lib/ruhoh/templaters/rmustache.rb +45 -4
- data/lib/ruhoh/urls.rb +46 -0
- data/lib/ruhoh/utils.rb +59 -17
- data/lib/ruhoh/version.rb +2 -2
- data/lib/ruhoh/watch.rb +26 -14
- data/lib/ruhoh.rb +38 -96
- data/ruhoh.gemspec +29 -10
- data/scaffolds/draft.html +9 -0
- data/scaffolds/page.html +0 -2
- data/scaffolds/post.html +0 -4
- data/scaffolds/theme/{images → javascripts}/.gitkeep +0 -0
- data/scaffolds/theme/layouts/default.html +2 -4
- data/scaffolds/theme/layouts/page.html +1 -1
- data/scaffolds/theme/layouts/post.html +1 -1
- data/scaffolds/theme/{css/style.css → media/.gitkeep} +0 -0
- data/scaffolds/theme/stylesheets/style.css +0 -0
- data/scaffolds/theme/theme.yml +27 -0
- data/scaffolds/theme/widgets/.gitkeep +0 -0
- data/spec/config_spec.rb +50 -0
- data/spec/db_spec.rb +28 -14
- data/spec/page_spec.rb +24 -35
- data/spec/parsers/layouts_spec.rb +5 -13
- data/spec/parsers/pages_spec.rb +13 -11
- data/spec/parsers/posts_spec.rb +34 -29
- data/spec/parsers/routes_spec.rb +2 -1
- data/spec/parsers/site_spec.rb +6 -5
- data/spec/setup_spec.rb +3 -47
- data/widgets/analytics/config.yml +5 -0
- data/{system_partials/analytics/getclicky → widgets/analytics/layouts/getclicky.html} +2 -2
- data/{system_partials/analytics/google → widgets/analytics/layouts/google.html} +1 -1
- data/widgets/comments/config.yml +12 -0
- data/{system_partials/comments/disqus → widgets/comments/layouts/disqus.html} +2 -2
- data/{system_partials/comments/facebook → widgets/comments/layouts/facebook.html} +1 -1
- data/{system_partials/comments/intensedebate → widgets/comments/layouts/intensedebate.html} +1 -1
- data/{system_partials/comments/livefyre → widgets/comments/layouts/livefyre.html} +1 -1
- data/widgets/google_prettify/config.yml +1 -0
- data/widgets/google_prettify/layouts/google_prettify.html +10 -0
- metadata +54 -31
- data/lib/ruhoh/templaters/base.rb +0 -57
- data/system_partials/syntax/google_prettify +0 -11
@@ -0,0 +1,67 @@
|
|
1
|
+
class Ruhoh
|
2
|
+
module Parsers
|
3
|
+
# Collect all the javascripts.
|
4
|
+
# Themes explicitly define which javascripts to load via theme.yml.
|
5
|
+
# Additionally, widgets may register javascript dependencies, which are resolved here.
|
6
|
+
module Javascripts
|
7
|
+
|
8
|
+
# Generates mappings to all registered javascripts.
|
9
|
+
# Returns Hash with layout names as keys and Array of asset Objects as values
|
10
|
+
def self.generate
|
11
|
+
theme_config = self.theme_config
|
12
|
+
assets = self.theme_javascripts(theme_config)
|
13
|
+
assets[Ruhoh.names.widgets] = self.widget_javascripts(theme_config)
|
14
|
+
assets
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.theme_javascripts(theme_config)
|
18
|
+
return {} unless theme_config[Ruhoh.names.javascripts].is_a? Hash
|
19
|
+
assets = {}
|
20
|
+
theme_config[Ruhoh.names.javascripts].each do |key, value|
|
21
|
+
next if key == Ruhoh.names.widgets # Widgets are handled separately.
|
22
|
+
assets[key] = Array(value).map { |v|
|
23
|
+
{
|
24
|
+
"url" => "#{Ruhoh.urls.theme_javascripts}/#{v}",
|
25
|
+
"id" => File.join(Ruhoh.paths.theme_javascripts, v)
|
26
|
+
}
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
assets
|
31
|
+
end
|
32
|
+
|
33
|
+
# Notes:
|
34
|
+
# The automatic script inclusion is currently handled within the widget parser.
|
35
|
+
# This differs from the auto-stylesheet inclusion relative to themes,
|
36
|
+
# which is handled in the stylesheet parser.
|
37
|
+
# Make sure there are some standards with this.
|
38
|
+
def self.widget_javascripts(theme_config)
|
39
|
+
assets = []
|
40
|
+
Ruhoh::DB.widgets.each_value do |widget|
|
41
|
+
next unless widget[Ruhoh.names.javascripts]
|
42
|
+
assets += Array(widget[Ruhoh.names.javascripts]).map {|path|
|
43
|
+
{
|
44
|
+
"url" => [Ruhoh.urls.widgets, widget['name'], Ruhoh.names.javascripts, path].join('/'),
|
45
|
+
"id" => File.join(Ruhoh.paths.widgets, widget['name'], Ruhoh.names.javascripts, path)
|
46
|
+
}
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
assets
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.theme_config
|
54
|
+
theme_config = Ruhoh::Utils.parse_yaml_file(Ruhoh.paths.theme_config_data)
|
55
|
+
if theme_config.nil?
|
56
|
+
Ruhoh::Friend.say{
|
57
|
+
yellow "WARNING: theme.yml config file not found:"
|
58
|
+
yellow " #{Ruhoh.paths.theme_config_data}"
|
59
|
+
}
|
60
|
+
return {}
|
61
|
+
end
|
62
|
+
return {} unless theme_config.is_a? Hash
|
63
|
+
theme_config
|
64
|
+
end
|
65
|
+
end #Javascripts
|
66
|
+
end #Parsers
|
67
|
+
end #Ruhoh
|
@@ -5,23 +5,20 @@ class Ruhoh
|
|
5
5
|
# Generate layouts only from the active theme.
|
6
6
|
def self.generate
|
7
7
|
layouts = {}
|
8
|
-
invalid = []
|
9
8
|
self.files.each do |filename|
|
10
9
|
id = File.basename(filename, File.extname(filename))
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
error = "Invalid YAML Front Matter. Ensure this page has valid YAML, even if it's empty."
|
15
|
-
invalid << [filename, error]
|
16
|
-
end
|
10
|
+
data = Ruhoh::Utils.parse_layout_file(Ruhoh.paths.theme_layouts, filename)
|
11
|
+
data['id'] = id
|
12
|
+
layouts[id] = data
|
17
13
|
end
|
18
14
|
|
19
|
-
Ruhoh::Utils.report('Layouts', layouts,
|
15
|
+
Ruhoh::Utils.report('Layouts', layouts, [])
|
20
16
|
layouts
|
21
17
|
end
|
22
18
|
|
23
19
|
def self.files
|
24
|
-
|
20
|
+
return [] unless FileTest.directory?(Ruhoh.paths.theme_layouts)
|
21
|
+
FileUtils.cd(Ruhoh.paths.theme_layouts) {
|
25
22
|
return Dir["**/*.*"].select { |filename|
|
26
23
|
next if FileTest.directory?(filename)
|
27
24
|
next if ['_','.'].include? filename[0]
|
@@ -30,7 +27,6 @@ class Ruhoh
|
|
30
27
|
}
|
31
28
|
end
|
32
29
|
|
33
|
-
|
34
30
|
end #Layouts
|
35
31
|
end #Parsers
|
36
32
|
end #Ruhoh
|
data/lib/ruhoh/parsers/pages.rb
CHANGED
@@ -8,32 +8,30 @@ class Ruhoh
|
|
8
8
|
Ruhoh.ensure_setup
|
9
9
|
|
10
10
|
pages = self.files
|
11
|
-
invalid = []
|
12
11
|
dictionary = {}
|
13
12
|
|
14
13
|
pages.each do |filename|
|
15
14
|
id = self.make_id(filename)
|
16
15
|
parsed_page = ''
|
17
|
-
FileUtils.cd(Ruhoh.paths.
|
18
|
-
if parsed_page.empty?
|
19
|
-
error = "Invalid Yaml Front Matter.\n Ensure this page has valid YAML, even if it's empty."
|
20
|
-
invalid << [filename, error] ; next
|
21
|
-
end
|
16
|
+
FileUtils.cd(Ruhoh.paths.base) { parsed_page = Ruhoh::Utils.parse_page_file(filename) }
|
22
17
|
|
23
18
|
parsed_page['data']['id'] = id
|
24
19
|
parsed_page['data']['url'] = self.permalink(parsed_page['data'])
|
25
20
|
parsed_page['data']['title'] = parsed_page['data']['title'] || self.to_title(filename)
|
26
|
-
|
21
|
+
if parsed_page['data']['layout'].nil?
|
22
|
+
parsed_page['data']['layout'] = Ruhoh.config.pages_layout
|
23
|
+
end
|
24
|
+
|
27
25
|
dictionary[id] = parsed_page['data']
|
28
26
|
end
|
29
27
|
|
30
|
-
Ruhoh::Utils.report('Pages', dictionary,
|
28
|
+
Ruhoh::Utils.report('Pages', dictionary, [])
|
31
29
|
dictionary
|
32
30
|
end
|
33
31
|
|
34
32
|
def self.files
|
35
|
-
FileUtils.cd(Ruhoh.paths.
|
36
|
-
return Dir["#{Ruhoh.
|
33
|
+
FileUtils.cd(Ruhoh.paths.base) {
|
34
|
+
return Dir["#{Ruhoh.names.pages}/**/*.*"].select { |filename|
|
37
35
|
next unless self.is_valid_page?(filename)
|
38
36
|
true
|
39
37
|
}
|
@@ -43,40 +41,35 @@ class Ruhoh
|
|
43
41
|
def self.is_valid_page?(filepath)
|
44
42
|
return false if FileTest.directory?(filepath)
|
45
43
|
return false if ['.'].include? filepath[0]
|
46
|
-
Ruhoh.
|
44
|
+
Ruhoh.config.pages_exclude.each {|regex| return false if filepath =~ regex }
|
47
45
|
true
|
48
46
|
end
|
49
47
|
|
50
48
|
def self.make_id(filename)
|
51
|
-
filename.gsub(Regexp.new("^#{Ruhoh.
|
49
|
+
filename.gsub(Regexp.new("^#{Ruhoh.names.pages}/"), '')
|
52
50
|
end
|
53
51
|
|
54
52
|
def self.to_title(filename)
|
55
53
|
name = File.basename( filename, File.extname(filename) )
|
56
54
|
name = filename.split('/')[-2] if name == 'index' && !filename.index('/').nil?
|
57
|
-
name.gsub(/[
|
55
|
+
name.gsub(/[^\p{Word}+]/u, ' ').gsub(/\b\w/){$&.upcase}
|
58
56
|
end
|
59
57
|
|
60
58
|
# Build the permalink for the given page.
|
61
|
-
# Only recognize
|
59
|
+
# Only recognize extensions registered from a 'convertable' module.
|
62
60
|
# This means 'non-convertable' extensions should pass-through.
|
63
61
|
#
|
64
62
|
# Returns [String] the permalink for this page.
|
65
63
|
def self.permalink(page)
|
66
|
-
url = '/'
|
67
64
|
ext = File.extname(page['id'])
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
end
|
73
|
-
|
74
|
-
url = url.split('/').reject{ |part| part[0] == '.' }.join('/')
|
75
|
-
url = url.gsub(/\/index.html$/, '')
|
65
|
+
name = page['id'].gsub(Regexp.new("#{ext}$"), '')
|
66
|
+
ext = '.html' if Ruhoh::Converter.extensions.include?(ext)
|
67
|
+
url = name.split('/').map {|p| Ruhoh::Urls.to_url_slug(p) }.join('/')
|
68
|
+
url = "/#{url}#{ext}".gsub(/\/index.html$/, '')
|
76
69
|
if page['permalink'] == 'pretty' || Ruhoh.config.pages_permalink == 'pretty'
|
77
70
|
url = url.gsub(/\.html$/, '')
|
78
71
|
end
|
79
|
-
url =
|
72
|
+
url = '/' if url.empty?
|
80
73
|
|
81
74
|
url
|
82
75
|
end
|
@@ -1,25 +1,19 @@
|
|
1
1
|
class Ruhoh
|
2
|
-
|
3
2
|
module Parsers
|
4
|
-
|
5
3
|
module Partials
|
6
4
|
|
7
5
|
def self.generate
|
8
|
-
self.
|
6
|
+
self.global_partials.merge(self.theme_partials)
|
9
7
|
end
|
10
|
-
|
8
|
+
|
11
9
|
def self.theme_partials
|
12
|
-
self.process(Ruhoh.paths.
|
10
|
+
self.process(Ruhoh.paths.theme_partials)
|
13
11
|
end
|
14
12
|
|
15
13
|
def self.global_partials
|
16
|
-
self.process(Ruhoh.paths.
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.system_partials
|
20
|
-
self.process(File.join(Ruhoh::Root, 'system_partials'))
|
14
|
+
self.process(Ruhoh.paths.partials)
|
21
15
|
end
|
22
|
-
|
16
|
+
|
23
17
|
def self.process(path)
|
24
18
|
return {} unless File.exist?(path)
|
25
19
|
|
@@ -28,14 +22,12 @@ class Ruhoh
|
|
28
22
|
Dir.glob("**/*").each { |filename|
|
29
23
|
next if FileTest.directory?(filename)
|
30
24
|
next if ['.'].include? filename[0]
|
31
|
-
File.open(filename) { |f| partials[filename] = f.read }
|
25
|
+
File.open(filename, 'r:UTF-8') { |f| partials[filename] = f.read }
|
32
26
|
}
|
33
27
|
}
|
34
28
|
partials
|
35
29
|
end
|
36
30
|
|
37
31
|
end #Partials
|
38
|
-
|
39
32
|
end #Parsers
|
40
|
-
|
41
33
|
end #Ruhoh
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class Ruhoh
|
2
|
+
module Parsers
|
3
|
+
module Payload
|
4
|
+
|
5
|
+
def self.generate
|
6
|
+
{
|
7
|
+
"db" => {
|
8
|
+
"pages" => Ruhoh::DB.pages,
|
9
|
+
"posts" => self.determine_category_and_tag_urls,
|
10
|
+
},
|
11
|
+
"site" => Ruhoh::DB.site,
|
12
|
+
'page' => {},
|
13
|
+
"urls" => {
|
14
|
+
"theme_stylesheets" => Ruhoh.urls.theme_stylesheets,
|
15
|
+
"theme_javascripts" => Ruhoh.urls.theme_javascripts,
|
16
|
+
"theme_media" => Ruhoh.urls.theme_media,
|
17
|
+
"media" => Ruhoh.urls.media,
|
18
|
+
}
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
# This is an ugly hack to determine the proper category and tag urls.
|
23
|
+
# TODO: Refactor this out.
|
24
|
+
def self.determine_category_and_tag_urls
|
25
|
+
return nil unless Ruhoh::DB.routes && Ruhoh::DB.posts
|
26
|
+
categories_url = nil
|
27
|
+
['/categories', '/categories.html'].each { |url|
|
28
|
+
categories_url = url and break if Ruhoh::DB.routes.key?(url)
|
29
|
+
}
|
30
|
+
Ruhoh::DB.posts['categories'].each do |key, value|
|
31
|
+
Ruhoh::DB.posts['categories'][key]['url'] = "#{categories_url}##{value['name']}-ref"
|
32
|
+
end
|
33
|
+
|
34
|
+
tags_url = nil
|
35
|
+
['/tags', '/tags.html'].each { |url|
|
36
|
+
tags_url = url and break if Ruhoh::DB.routes.key?(url)
|
37
|
+
}
|
38
|
+
Ruhoh::DB.posts['tags'].each do |key, value|
|
39
|
+
Ruhoh::DB.posts['tags'][key]['url'] = "#{tags_url}##{value['name']}-ref"
|
40
|
+
end
|
41
|
+
|
42
|
+
Ruhoh::DB.posts
|
43
|
+
end
|
44
|
+
|
45
|
+
end #Payload
|
46
|
+
end #Parsers
|
47
|
+
end #Ruhoh
|
data/lib/ruhoh/parsers/posts.rb
CHANGED
@@ -30,14 +30,10 @@ class Ruhoh
|
|
30
30
|
|
31
31
|
self.files.each do |filename|
|
32
32
|
parsed_page = ''
|
33
|
-
FileUtils.cd(Ruhoh.paths.
|
34
|
-
if parsed_page.empty?
|
35
|
-
error = "Invalid YAML Front Matter. Ensure this page has valid YAML, even if it's empty."
|
36
|
-
invalid << [filename, error] ; next
|
37
|
-
end
|
33
|
+
FileUtils.cd(Ruhoh.paths.base) { parsed_page = Ruhoh::Utils.parse_page_file(filename) }
|
38
34
|
data = parsed_page['data']
|
39
35
|
|
40
|
-
filename_data = self.
|
36
|
+
filename_data = self.parse_page_filename(filename)
|
41
37
|
if filename_data.empty?
|
42
38
|
error = "Invalid Filename Format. Format should be: my-post-title.ext"
|
43
39
|
invalid << [filename, error] ; next
|
@@ -59,6 +55,7 @@ class Ruhoh
|
|
59
55
|
data['id'] = filename
|
60
56
|
data['title'] = data['title'] || filename_data['title']
|
61
57
|
data['url'] = self.permalink(data)
|
58
|
+
data['layout'] = Ruhoh.config.posts_layout if data['layout'].nil?
|
62
59
|
dictionary[filename] = data
|
63
60
|
end
|
64
61
|
|
@@ -77,8 +74,8 @@ class Ruhoh
|
|
77
74
|
end
|
78
75
|
|
79
76
|
def self.files
|
80
|
-
FileUtils.cd(Ruhoh.paths.
|
81
|
-
return Dir["#{Ruhoh.
|
77
|
+
FileUtils.cd(Ruhoh.paths.base) {
|
78
|
+
return Dir["#{Ruhoh.names.posts}/**/*.*"].select { |filename|
|
82
79
|
next unless self.is_valid_page?(filename)
|
83
80
|
true
|
84
81
|
}
|
@@ -88,7 +85,7 @@ class Ruhoh
|
|
88
85
|
def self.is_valid_page?(filepath)
|
89
86
|
return false if FileTest.directory?(filepath)
|
90
87
|
return false if ['.'].include? filepath[0]
|
91
|
-
Ruhoh.
|
88
|
+
Ruhoh.config.posts_exclude.each {|regex| return false if filepath =~ regex }
|
92
89
|
true
|
93
90
|
end
|
94
91
|
|
@@ -102,7 +99,7 @@ class Ruhoh
|
|
102
99
|
ordered_posts
|
103
100
|
end
|
104
101
|
|
105
|
-
def self.
|
102
|
+
def self.parse_page_filename(filename)
|
106
103
|
data = *filename.match(DateMatcher)
|
107
104
|
data = *filename.match(Matcher) if data.empty?
|
108
105
|
return {} if data.empty?
|
@@ -127,41 +124,44 @@ class Ruhoh
|
|
127
124
|
|
128
125
|
# my-post-title ===> My Post Title
|
129
126
|
def self.to_title(file_slug)
|
130
|
-
file_slug.gsub(/[
|
127
|
+
file_slug.gsub(/[^\p{Word}+]/u, ' ').gsub(/\b\w/){$&.upcase}
|
131
128
|
end
|
132
129
|
|
133
|
-
# My Post Title ===> my-post-title
|
134
|
-
def self.to_slug(title)
|
135
|
-
title.downcase.strip.gsub(/\s/, '-').gsub(/[^\w-]/, '')
|
136
|
-
end
|
137
|
-
|
138
130
|
# Used in the client implementation to turn a draft into a post.
|
139
131
|
def self.to_filename(data)
|
140
|
-
File.join(Ruhoh.paths.posts, "#{
|
132
|
+
File.join(Ruhoh.paths.posts, "#{Ruhoh::Urls.to_slug(data['title'])}.#{data['ext']}")
|
141
133
|
end
|
142
134
|
|
143
135
|
# Another blatently stolen method from Jekyll
|
136
|
+
# The category is only the first one if multiple categories exist.
|
144
137
|
def self.permalink(post)
|
145
138
|
date = Date.parse(post['date'])
|
146
|
-
title = post['title']
|
147
|
-
format = post['permalink'] || Ruhoh.config.
|
139
|
+
title = Ruhoh::Urls.to_url_slug(post['title'])
|
140
|
+
format = post['permalink'] || Ruhoh.config.posts_permalink || "/:categories/:year/:month/:day/:title.html"
|
141
|
+
|
142
|
+
# Use the literal permalink if it is a non-tokenized string.
|
143
|
+
unless format.include?(':')
|
144
|
+
url = format.gsub(/^\//, '').split('/').map {|p| CGI::escape(p) }.join('/')
|
145
|
+
return "/#{url}"
|
146
|
+
end
|
147
|
+
|
148
|
+
filename = File.basename(post['id'], File.extname(post['id']))
|
149
|
+
category = Array(post['categories'])[0]
|
150
|
+
category = category.split('/').map {|c| Ruhoh::Urls.to_url_slug(c) }.join('/') if category
|
148
151
|
|
149
152
|
url = {
|
150
153
|
"year" => date.strftime("%Y"),
|
151
154
|
"month" => date.strftime("%m"),
|
152
155
|
"day" => date.strftime("%d"),
|
153
|
-
"title" =>
|
156
|
+
"title" => title,
|
157
|
+
"filename" => filename,
|
154
158
|
"i_day" => date.strftime("%d").to_i.to_s,
|
155
159
|
"i_month" => date.strftime("%m").to_i.to_s,
|
156
|
-
"categories" =>
|
157
|
-
"output_ext" => 'html' # what's this for?
|
160
|
+
"categories" => category || '',
|
158
161
|
}.inject(format) { |result, token|
|
159
162
|
result.gsub(/:#{Regexp.escape token.first}/, token.last)
|
160
|
-
}.gsub(
|
163
|
+
}.gsub(/\/+/, "/")
|
161
164
|
|
162
|
-
# sanitize url
|
163
|
-
url = url.split('/').reject{ |part| part =~ /^\.+$/ }.join('/')
|
164
|
-
url += "/" if url =~ /\/$/
|
165
165
|
url
|
166
166
|
end
|
167
167
|
|
@@ -223,7 +223,6 @@ class Ruhoh
|
|
223
223
|
tags[tag] = {
|
224
224
|
'count' => 1,
|
225
225
|
'name' => tag,
|
226
|
-
'url' => "/tags.html##{tag}-ref",
|
227
226
|
'posts' => []
|
228
227
|
}
|
229
228
|
end
|
@@ -236,7 +235,7 @@ class Ruhoh
|
|
236
235
|
|
237
236
|
def self.parse_categories(ordered_posts)
|
238
237
|
categories = {}
|
239
|
-
|
238
|
+
|
240
239
|
ordered_posts.each do |post|
|
241
240
|
Array(post['categories']).each do |cat|
|
242
241
|
cat = Array(cat).join('/')
|
@@ -246,7 +245,6 @@ class Ruhoh
|
|
246
245
|
categories[cat] = {
|
247
246
|
'count' => 1,
|
248
247
|
'name' => cat,
|
249
|
-
'url' => "/categories.html##{cat}-ref",
|
250
248
|
'posts' => []
|
251
249
|
}
|
252
250
|
end
|
data/lib/ruhoh/parsers/site.rb
CHANGED
@@ -6,8 +6,8 @@ class Ruhoh
|
|
6
6
|
module Site
|
7
7
|
|
8
8
|
def self.generate
|
9
|
-
site = Ruhoh::Utils.
|
10
|
-
config = Ruhoh::Utils.
|
9
|
+
site = Ruhoh::Utils.parse_yaml_file(Ruhoh.paths.site_data) || {}
|
10
|
+
config = Ruhoh::Utils.parse_yaml_file(Ruhoh.paths.config_data)
|
11
11
|
site['config'] = config
|
12
12
|
site
|
13
13
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
class Ruhoh
|
2
|
+
module Parsers
|
3
|
+
# Collect all registered stylesheets.
|
4
|
+
# Themes explicitly define which stylesheets to load via theme.yml.
|
5
|
+
# All styling is managed by the theme, including widget styles.
|
6
|
+
# If the theme provides widget stylesheets they will load automatically.
|
7
|
+
# theme.yml may also specify an explicit widget stylesheet to load.
|
8
|
+
module Stylesheets
|
9
|
+
|
10
|
+
# Generates mappings to all registered stylesheets.
|
11
|
+
# Returns Hash with layout names as keys and Array of asset Objects as values
|
12
|
+
def self.generate
|
13
|
+
theme_config = self.theme_config
|
14
|
+
assets = self.theme_stylesheets(theme_config)
|
15
|
+
assets[Ruhoh.names.widgets] = self.widget_stylesheets(theme_config)
|
16
|
+
assets
|
17
|
+
end
|
18
|
+
|
19
|
+
# Create mappings for stylesheets registered to the theme layouts.
|
20
|
+
# Themes register stylesheets relative to their layouts.
|
21
|
+
# Returns Hash with layout names as keys and Array of asset Objects as values.
|
22
|
+
def self.theme_stylesheets(theme_config)
|
23
|
+
return {} unless theme_config[Ruhoh.names.stylesheets].is_a? Hash
|
24
|
+
assets = {}
|
25
|
+
theme_config[Ruhoh.names.stylesheets].each do |key, value|
|
26
|
+
next if key == Ruhoh.names.widgets # Widgets are handled separately.
|
27
|
+
assets[key] = Array(value).map { |v|
|
28
|
+
{
|
29
|
+
"url" => "#{Ruhoh.urls.theme_stylesheets}/#{v}",
|
30
|
+
"id" => File.join(Ruhoh.paths.theme_stylesheets, v)
|
31
|
+
}
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
assets
|
36
|
+
end
|
37
|
+
|
38
|
+
# Create mappings for stylesheets registered to a given widget.
|
39
|
+
# A theme may provide widget stylesheets which will load automatically,
|
40
|
+
# provided they adhere to the default naming rules.
|
41
|
+
# Themes may also specify an explicit widget stylesheet to load.
|
42
|
+
#
|
43
|
+
# Returns Array of asset objects.
|
44
|
+
def self.widget_stylesheets(theme_config)
|
45
|
+
assets = []
|
46
|
+
Ruhoh::DB.widgets.each_key do |name|
|
47
|
+
default_name = "#{name}.css"
|
48
|
+
stylesheet = theme_config[Ruhoh.names.stylesheets][Ruhoh.names.widgets][name] rescue default_name
|
49
|
+
stylesheet ||= default_name
|
50
|
+
file = File.join(Ruhoh.paths.theme_widgets, name, Ruhoh.names.stylesheets, stylesheet)
|
51
|
+
next unless File.exists?(file)
|
52
|
+
assets << {
|
53
|
+
"url" => [Ruhoh.urls.theme_widgets, name, Ruhoh.names.stylesheets, stylesheet].join('/'),
|
54
|
+
"id" => file
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
assets
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.theme_config
|
62
|
+
theme_config = Ruhoh::Utils.parse_yaml_file(Ruhoh.paths.theme_config_data)
|
63
|
+
if theme_config.nil?
|
64
|
+
Ruhoh::Friend.say{
|
65
|
+
yellow "WARNING: theme.yml config file not found:"
|
66
|
+
yellow " #{Ruhoh.paths.theme_config_data}"
|
67
|
+
}
|
68
|
+
return {}
|
69
|
+
end
|
70
|
+
return {} unless theme_config.is_a? Hash
|
71
|
+
theme_config
|
72
|
+
end
|
73
|
+
end #Stylesheets
|
74
|
+
end #Parsers
|
75
|
+
end #Ruhoh
|
@@ -0,0 +1,104 @@
|
|
1
|
+
class Ruhoh
|
2
|
+
module Parsers
|
3
|
+
module Widgets
|
4
|
+
WidgetStructure = Struct.new(
|
5
|
+
:name,
|
6
|
+
:config,
|
7
|
+
:javascripts,
|
8
|
+
:layout
|
9
|
+
)
|
10
|
+
|
11
|
+
# Process available widgets into widget dictionary.
|
12
|
+
#
|
13
|
+
# Returns Dictionary of widget data.
|
14
|
+
def self.generate
|
15
|
+
widgets = {}
|
16
|
+
self.widgets.each do |name|
|
17
|
+
config = self.process_config(name)
|
18
|
+
widgets[name] = WidgetStructure.new(
|
19
|
+
name,
|
20
|
+
config,
|
21
|
+
self.process_javascripts(config, name),
|
22
|
+
self.process_layout(config, name)
|
23
|
+
)
|
24
|
+
end
|
25
|
+
Ruhoh::Utils.report('Widgets', widgets, [])
|
26
|
+
|
27
|
+
widgets
|
28
|
+
end
|
29
|
+
|
30
|
+
# Find the widgets.
|
31
|
+
#
|
32
|
+
# Returns Array of widget names.
|
33
|
+
def self.widgets
|
34
|
+
names = []
|
35
|
+
if FileTest.directory?(Ruhoh.paths.widgets)
|
36
|
+
FileUtils.cd(Ruhoh.paths.widgets) { names += Dir["*"] }
|
37
|
+
end
|
38
|
+
if FileTest.directory?(Ruhoh.paths.system_widgets)
|
39
|
+
FileUtils.cd(Ruhoh.paths.system_widgets) { names += Dir["*"] }
|
40
|
+
end
|
41
|
+
names.uniq!
|
42
|
+
names
|
43
|
+
end
|
44
|
+
|
45
|
+
# Process the widget configuration params.
|
46
|
+
#
|
47
|
+
# Returns Hash of configuration params.
|
48
|
+
def self.process_config(widget_name)
|
49
|
+
system_config = Ruhoh::Utils.parse_yaml_file(Ruhoh.paths.system_widgets, widget_name, Ruhoh.names.config_data) || {}
|
50
|
+
user_config = Ruhoh::Utils.parse_yaml_file(Ruhoh.paths.widgets, widget_name, Ruhoh.names.config_data) || {}
|
51
|
+
config = Ruhoh::Utils.deep_merge(system_config, user_config)
|
52
|
+
config['layout'] ||= widget_name
|
53
|
+
config['stylesheet'] ||= widget_name
|
54
|
+
config
|
55
|
+
end
|
56
|
+
|
57
|
+
# Process widget script dependencies.
|
58
|
+
# Script dependencies may be set in the config.
|
59
|
+
# Look for default script at: scripts/{widget_name}.js if no config.
|
60
|
+
# If found, we include it, else no javascripts will load.
|
61
|
+
#
|
62
|
+
# Returns Array of script filenames to load.
|
63
|
+
def self.process_javascripts(config, widget_name)
|
64
|
+
scripts = config[Ruhoh.names.javascripts] ? Array(config[Ruhoh.names.javascripts]) : []
|
65
|
+
|
66
|
+
# Try for the default script if no config.
|
67
|
+
if scripts.empty?
|
68
|
+
script_file = File.join(Ruhoh.paths.widgets, widget_name, Ruhoh.names.javascripts, "#{widget_name}.js")
|
69
|
+
if File.exist?(script_file)
|
70
|
+
scripts << "#{widget_name}.js"
|
71
|
+
else
|
72
|
+
script_file = File.join(Ruhoh.paths.system_widgets, widget_name, Ruhoh.names.javascripts, "#{widget_name}.js")
|
73
|
+
scripts << "#{widget_name}.js" if File.exist?(script_file)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
scripts
|
78
|
+
end
|
79
|
+
|
80
|
+
# Determine and process the correct widget layout.
|
81
|
+
# The layout may be manually configured by the user,
|
82
|
+
# else system defaults will be used.
|
83
|
+
# Layouts cascade from: theme -> blog -> system
|
84
|
+
#
|
85
|
+
# Returns String of rendered layout content.
|
86
|
+
def self.process_layout(config, widget_name)
|
87
|
+
layout = nil
|
88
|
+
layout_path = File.join(widget_name, 'layouts', "#{config['layout']}.html")
|
89
|
+
[
|
90
|
+
File.join(Ruhoh.paths.theme_widgets, layout_path),
|
91
|
+
File.join(Ruhoh.paths.widgets, layout_path),
|
92
|
+
File.join(Ruhoh.paths.system_widgets, layout_path)
|
93
|
+
].each do |path|
|
94
|
+
layout = path and break if File.exist?(path)
|
95
|
+
end
|
96
|
+
|
97
|
+
return '' unless layout
|
98
|
+
content = File.open(layout, 'r:UTF-8') { |f| f.read }
|
99
|
+
Mustache.render(content, {'config' => config})
|
100
|
+
end
|
101
|
+
|
102
|
+
end #Widgets
|
103
|
+
end #Parsers
|
104
|
+
end #Ruhoh
|