ruhoh 0.3.0 → 1.0.0.alpha
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/lib/ruhoh/paths.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
class Ruhoh
|
2
|
+
# Structured container for all paths to relevant directories and files in the system.
|
3
|
+
# Paths are based on the ruhohspec for the Universal Blog API.
|
4
|
+
# Additionally we store some system (gem) level paths for cascading to default functionality,
|
5
|
+
# such as default widgets, default dashboard view, etc.
|
6
|
+
module Paths
|
7
|
+
Paths = Struct.new(
|
8
|
+
:base,
|
9
|
+
:compiled,
|
10
|
+
:config_data,
|
11
|
+
:dashboard_file,
|
12
|
+
:media,
|
13
|
+
:pages,
|
14
|
+
:partials,
|
15
|
+
:plugins,
|
16
|
+
:posts,
|
17
|
+
:site_data,
|
18
|
+
:themes,
|
19
|
+
:widgets,
|
20
|
+
|
21
|
+
:theme,
|
22
|
+
:theme_config_data,
|
23
|
+
:theme_dashboard_file,
|
24
|
+
:theme_layouts,
|
25
|
+
:theme_media,
|
26
|
+
:theme_partials,
|
27
|
+
:theme_javascripts,
|
28
|
+
:theme_stylesheets,
|
29
|
+
:theme_widgets,
|
30
|
+
|
31
|
+
:system_dashboard_file,
|
32
|
+
:system_widgets
|
33
|
+
)
|
34
|
+
|
35
|
+
def self.generate(config, base)
|
36
|
+
paths = Paths.new
|
37
|
+
paths.base = base
|
38
|
+
paths.config_data = File.join(base, Ruhoh.names.config_data)
|
39
|
+
paths.pages = File.join(base, Ruhoh.names.pages)
|
40
|
+
paths.posts = File.join(base, Ruhoh.names.posts)
|
41
|
+
paths.partials = File.join(base, Ruhoh.names.partials)
|
42
|
+
paths.media = File.join(base, Ruhoh.names.media)
|
43
|
+
paths.widgets = File.join(base, Ruhoh.names.widgets)
|
44
|
+
paths.compiled = File.join(base, Ruhoh.names.compiled)
|
45
|
+
paths.dashboard_file = File.join(base, Ruhoh.names.dashboard_file)
|
46
|
+
paths.site_data = File.join(base, Ruhoh.names.site_data)
|
47
|
+
paths.themes = File.join(base, Ruhoh.names.themes)
|
48
|
+
paths.plugins = File.join(base, Ruhoh.names.plugins)
|
49
|
+
|
50
|
+
paths.theme = File.join(base, Ruhoh.names.themes, config.theme)
|
51
|
+
paths.theme_dashboard_file= File.join(paths.theme, Ruhoh.names.dashboard_file)
|
52
|
+
paths.theme_config_data = File.join(paths.theme, Ruhoh.names.theme_config)
|
53
|
+
paths.theme_layouts = File.join(paths.theme, Ruhoh.names.layouts)
|
54
|
+
paths.theme_stylesheets = File.join(paths.theme, Ruhoh.names.stylesheets)
|
55
|
+
paths.theme_javascripts = File.join(paths.theme, Ruhoh.names.javascripts)
|
56
|
+
paths.theme_media = File.join(paths.theme, Ruhoh.names.media)
|
57
|
+
paths.theme_widgets = File.join(paths.theme, Ruhoh.names.widgets)
|
58
|
+
paths.theme_partials = File.join(paths.theme, Ruhoh.names.partials)
|
59
|
+
|
60
|
+
return false unless self.theme_is_valid?(paths)
|
61
|
+
|
62
|
+
paths.system_dashboard_file = File.join(Ruhoh::Root, Ruhoh.names.dashboard_file)
|
63
|
+
paths.system_widgets = File.join(Ruhoh::Root, Ruhoh.names.widgets)
|
64
|
+
|
65
|
+
paths
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.theme_is_valid?(paths)
|
69
|
+
return true if FileTest.directory?(paths.theme)
|
70
|
+
Ruhoh.log.error("Theme directory does not exist: #{paths.theme}")
|
71
|
+
return false
|
72
|
+
end
|
73
|
+
|
74
|
+
end #Paths
|
75
|
+
end #Ruhoh
|
data/lib/ruhoh/previewer.rb
CHANGED
@@ -14,8 +14,7 @@ class Ruhoh
|
|
14
14
|
|
15
15
|
def call(env)
|
16
16
|
return favicon if env['PATH_INFO'] == '/favicon.ico'
|
17
|
-
|
18
|
-
return admin if ["/#{dash}", "/#{dash}/"].include?(env['PATH_INFO'])
|
17
|
+
return admin if [Ruhoh.urls.dashboard, "#{Ruhoh.urls.dashboard}/"].include?(env['PATH_INFO'])
|
19
18
|
|
20
19
|
id = Ruhoh::DB.routes[env['PATH_INFO']]
|
21
20
|
raise "Page id not found for url: #{env['PATH_INFO']}" unless id
|
@@ -29,9 +28,16 @@ class Ruhoh
|
|
29
28
|
end
|
30
29
|
|
31
30
|
def admin
|
32
|
-
|
33
|
-
|
34
|
-
|
31
|
+
template = nil
|
32
|
+
[
|
33
|
+
Ruhoh.paths.theme_dashboard_file,
|
34
|
+
Ruhoh.paths.dashboard_file,
|
35
|
+
Ruhoh.paths.system_dashboard_file
|
36
|
+
].each do |path|
|
37
|
+
template = path and break if File.exist?(path)
|
38
|
+
end
|
39
|
+
template = File.open(template, 'r:UTF-8') {|f| f.read }
|
40
|
+
output = @page.templater.render(template, Ruhoh::DB.payload)
|
35
41
|
|
36
42
|
[200, {'Content-Type' => 'text/html'}, [output]]
|
37
43
|
end
|
data/lib/ruhoh/program.rb
CHANGED
@@ -12,17 +12,48 @@ class Ruhoh
|
|
12
12
|
# run Ruhoh::Program.preview
|
13
13
|
#
|
14
14
|
# Returns: A new Rack builder object which should work inside config.ru
|
15
|
-
def self.preview(
|
15
|
+
def self.preview(opts={})
|
16
|
+
opts[:watch] ||= true
|
17
|
+
opts[:env] ||= 'development'
|
18
|
+
|
16
19
|
Ruhoh.setup
|
20
|
+
Ruhoh.config.env = opts[:env]
|
17
21
|
Ruhoh::DB.update_all
|
18
|
-
Ruhoh::Watch.start if watch
|
22
|
+
Ruhoh::Watch.start if opts[:watch]
|
19
23
|
Rack::Builder.new {
|
20
24
|
use Rack::Lint
|
21
25
|
use Rack::ShowExceptions
|
22
|
-
|
23
|
-
|
26
|
+
|
27
|
+
# Serve base media
|
28
|
+
map Ruhoh.urls.media do
|
29
|
+
run Rack::File.new(Ruhoh.paths.media)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Serve theme assets
|
33
|
+
map Ruhoh.urls.theme do
|
34
|
+
run Rack::File.new(Ruhoh.paths.theme)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Serve widget javascripts
|
38
|
+
map Ruhoh.urls.widgets do
|
39
|
+
run Rack::File.new(Ruhoh.paths.widgets)
|
40
|
+
end
|
41
|
+
|
42
|
+
map '/' do
|
43
|
+
run Ruhoh::Previewer.new(Ruhoh::Page.new)
|
44
|
+
end
|
24
45
|
}
|
25
46
|
end
|
26
47
|
|
48
|
+
# Public: A program for compiling to a static website.
|
49
|
+
# The compile environment should always be 'production' in order
|
50
|
+
# to properly omit drafts and other development-only settings.
|
51
|
+
def self.compile(target)
|
52
|
+
Ruhoh.setup
|
53
|
+
Ruhoh.config.env = 'production'
|
54
|
+
Ruhoh::DB.update_all
|
55
|
+
Ruhoh::Compiler.compile(target)
|
56
|
+
end
|
57
|
+
|
27
58
|
end #Program
|
28
59
|
end #Ruhoh
|
@@ -0,0 +1,66 @@
|
|
1
|
+
class Ruhoh
|
2
|
+
module Templaters
|
3
|
+
module AssetHelpers
|
4
|
+
|
5
|
+
def assets
|
6
|
+
method = "assets_#{Ruhoh.config.env}"
|
7
|
+
return '' unless self.respond_to?(method)
|
8
|
+
self.__send__(method)
|
9
|
+
end
|
10
|
+
|
11
|
+
def assets_development
|
12
|
+
buffer = ''
|
13
|
+
master_layout = self.context['page']['master_layout']
|
14
|
+
sub_layout = self.context['page']['sub_layout']
|
15
|
+
stylesheets = Ruhoh::DB.stylesheets[master_layout] || []
|
16
|
+
stylesheets += Ruhoh::DB.stylesheets[sub_layout] || []
|
17
|
+
stylesheets += Ruhoh::DB.stylesheets[Ruhoh.names.widgets] || []
|
18
|
+
stylesheets.each do |style|
|
19
|
+
buffer += "<link href=\"#{style['url']}?#{rand()}\" type=\"text/css\" rel=\"stylesheet\" media=\"all\">\n"
|
20
|
+
end
|
21
|
+
buffer += "\n"
|
22
|
+
scripts = Ruhoh::DB.javascripts[master_layout] || []
|
23
|
+
scripts += Ruhoh::DB.javascripts[sub_layout] || []
|
24
|
+
scripts += Ruhoh::DB.javascripts[Ruhoh.names.widgets] || []
|
25
|
+
scripts.each do |script|
|
26
|
+
buffer += "<script src=\"#{script['url']}?#{rand()}\"></script>\n"
|
27
|
+
end
|
28
|
+
|
29
|
+
buffer
|
30
|
+
end
|
31
|
+
|
32
|
+
# TODO: Implement this for real.
|
33
|
+
def assets_production
|
34
|
+
self.assets_development
|
35
|
+
end
|
36
|
+
|
37
|
+
# NOTICE: This is unfinished and not-implemented!
|
38
|
+
def assets_production_not_implemented
|
39
|
+
buffer = ''
|
40
|
+
master_layout = self.context['page']['master_layout']
|
41
|
+
sub_layout = self.context['page']['sub_layout']
|
42
|
+
stylesheets = []
|
43
|
+
stylesheets << master_layout if Ruhoh::DB.stylesheets[master_layout]
|
44
|
+
stylesheets << sub_layout if Ruhoh::DB.stylesheets[sub_layout]
|
45
|
+
|
46
|
+
stylesheets.each do |name|
|
47
|
+
url = [Ruhoh.urls.theme_stylesheets, "#{name}.css"].join('/')
|
48
|
+
buffer += "<link href=\"#{url}\" type=\"text/css\" rel=\"stylesheet\" media=\"all\">\n"
|
49
|
+
end
|
50
|
+
buffer += "\n"
|
51
|
+
|
52
|
+
scripts = []
|
53
|
+
scripts << master_layout if Ruhoh::DB.javascripts[master_layout]
|
54
|
+
scripts << sub_layout if Ruhoh::DB.javascripts[sub_layout]
|
55
|
+
# Missing widgets
|
56
|
+
scripts.each do |name|
|
57
|
+
url = [Ruhoh.urls.theme_javascripts, "#{name}.js"].join('/')
|
58
|
+
buffer += "<script src=\"#{url}\"></script>\n"
|
59
|
+
end
|
60
|
+
|
61
|
+
buffer
|
62
|
+
end
|
63
|
+
|
64
|
+
end #AssetHelpers
|
65
|
+
end #Templaters
|
66
|
+
end #Ruhoh
|
@@ -0,0 +1,143 @@
|
|
1
|
+
class Ruhoh
|
2
|
+
module Templaters
|
3
|
+
module BaseHelpers
|
4
|
+
|
5
|
+
def partial(name)
|
6
|
+
p = Ruhoh::DB.partials[name.to_s]
|
7
|
+
Ruhoh::Friend.say { yellow "partial not found: '#{name}'" } if p.nil?
|
8
|
+
p
|
9
|
+
end
|
10
|
+
|
11
|
+
# Truncate the page content relative to a line_count limit.
|
12
|
+
# This is optimized for markdown files in which content is largely
|
13
|
+
# blocked into chunks and separating by blank lines.
|
14
|
+
# The line_limit truncates content based on # of content-based lines,
|
15
|
+
# so blank lines don't count toward the limit.
|
16
|
+
# Always break the content on a blank line only so result stays formatted nicely.
|
17
|
+
def summary
|
18
|
+
content, id = self.get_page_content
|
19
|
+
line_limit = self.context['site']['config']['posts']['summary_lines'].to_i rescue nil
|
20
|
+
line_limit ||= 20
|
21
|
+
line_count = 0
|
22
|
+
line_breakpoint = content.lines.count
|
23
|
+
|
24
|
+
content.lines.each_with_index do |line, i|
|
25
|
+
if line =~ /^\s*$/ # line with only whitespace
|
26
|
+
if line_count >= line_limit
|
27
|
+
line_breakpoint = i
|
28
|
+
break
|
29
|
+
end
|
30
|
+
else
|
31
|
+
line_count += 1
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
content = content.lines.to_a[0, line_breakpoint].join
|
36
|
+
content = self.render(content)
|
37
|
+
Ruhoh::Converter.convert(content, id)
|
38
|
+
end
|
39
|
+
|
40
|
+
def pages
|
41
|
+
pages = []
|
42
|
+
self.context['db']['pages'].each_value {|page| pages << page }
|
43
|
+
self.mark_active_page(pages)
|
44
|
+
end
|
45
|
+
|
46
|
+
def posts
|
47
|
+
self.to_posts(self.context['db']['posts']['chronological'])
|
48
|
+
end
|
49
|
+
|
50
|
+
def posts_latest
|
51
|
+
latest = self.context['site']['config']['posts']['latest'].to_i rescue nil
|
52
|
+
latest ||= 10
|
53
|
+
(latest.to_i > 0) ? self.posts[0, latest.to_i] : self.posts
|
54
|
+
end
|
55
|
+
|
56
|
+
def categories
|
57
|
+
cats = []
|
58
|
+
self.context['db']['posts']['categories'].each_value { |cat| cats << cat }
|
59
|
+
cats
|
60
|
+
end
|
61
|
+
|
62
|
+
def tags
|
63
|
+
tags = []
|
64
|
+
self.context['db']['posts']['tags'].each_value { |tag| tags << tag }
|
65
|
+
tags
|
66
|
+
end
|
67
|
+
|
68
|
+
def raw_code(sub_context)
|
69
|
+
code = sub_context.gsub('{', '{').gsub('}', '}').gsub('<', '<').gsub('>', '>')
|
70
|
+
"<pre><code>#{code}</code></pre>"
|
71
|
+
end
|
72
|
+
|
73
|
+
def debug(sub_context)
|
74
|
+
Ruhoh::Friend.say {
|
75
|
+
yellow "?debug:"
|
76
|
+
magenta sub_context.class
|
77
|
+
cyan sub_context.inspect
|
78
|
+
}
|
79
|
+
|
80
|
+
"<pre>#{sub_context.class}\n#{sub_context.pretty_inspect}</pre>"
|
81
|
+
end
|
82
|
+
|
83
|
+
def to_posts(sub_context)
|
84
|
+
Array(sub_context).map { |id|
|
85
|
+
self.context['db']['posts']['dictionary'][id]
|
86
|
+
}.compact
|
87
|
+
end
|
88
|
+
|
89
|
+
def to_pages(sub_context)
|
90
|
+
pages = Array(sub_context).map { |id|
|
91
|
+
self.context['db']['pages'][id]
|
92
|
+
}.compact
|
93
|
+
self.mark_active_page(pages)
|
94
|
+
end
|
95
|
+
|
96
|
+
def to_categories(sub_context)
|
97
|
+
Array(sub_context).map { |id|
|
98
|
+
self.context['db']['posts']['categories'][id]
|
99
|
+
}.compact
|
100
|
+
end
|
101
|
+
|
102
|
+
def to_tags(sub_context)
|
103
|
+
Array(sub_context).map { |id|
|
104
|
+
self.context['db']['posts']['tags'][id]
|
105
|
+
}.compact
|
106
|
+
end
|
107
|
+
|
108
|
+
def next(sub_context)
|
109
|
+
return unless sub_context.is_a?(String) || sub_context.is_a?(Hash)
|
110
|
+
id = sub_context.is_a?(Hash) ? sub_context['id'] : sub_context
|
111
|
+
return unless id
|
112
|
+
index = self.context['db']['posts']['chronological'].index(id)
|
113
|
+
return unless index && (index-1 >= 0)
|
114
|
+
next_id = self.context['db']['posts']['chronological'][index-1]
|
115
|
+
return unless next_id
|
116
|
+
self.to_posts(next_id)
|
117
|
+
end
|
118
|
+
|
119
|
+
def previous(sub_context)
|
120
|
+
return unless sub_context.is_a?(String) || sub_context.is_a?(Hash)
|
121
|
+
id = sub_context.is_a?(Hash) ? sub_context['id'] : sub_context
|
122
|
+
return unless id
|
123
|
+
index = self.context['db']['posts']['chronological'].index(id)
|
124
|
+
return unless index && (index+1 >= 0)
|
125
|
+
prev_id = self.context['db']['posts']['chronological'][index+1]
|
126
|
+
return unless prev_id
|
127
|
+
self.to_posts(prev_id)
|
128
|
+
end
|
129
|
+
|
130
|
+
# Marks the active page if exists in the given pages Array
|
131
|
+
def mark_active_page(pages)
|
132
|
+
pages.each_with_index do |page, i|
|
133
|
+
next unless page['id'] == self.context[:page]['id']
|
134
|
+
active_page = page.dup
|
135
|
+
active_page['is_active_page'] = true
|
136
|
+
pages[i] = active_page
|
137
|
+
end
|
138
|
+
pages
|
139
|
+
end
|
140
|
+
|
141
|
+
end #BaseHelpers
|
142
|
+
end #Templaters
|
143
|
+
end #Ruhoh
|
@@ -1,155 +1,8 @@
|
|
1
|
-
require 'pp'
|
2
|
-
|
3
1
|
class Ruhoh
|
4
2
|
module Templaters
|
3
|
+
# Interface for user-defined helper methods
|
5
4
|
module Helpers
|
6
|
-
|
7
|
-
def partial(name)
|
8
|
-
Ruhoh::DB.partials[name.to_s]
|
9
|
-
end
|
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']['tags'].each_value { |tag| tags << tag }
|
30
|
-
tags
|
31
|
-
end
|
32
|
-
|
33
|
-
def raw_code(sub_context)
|
34
|
-
code = sub_context.gsub('{', '{').gsub('}', '}').gsub('<', '<').gsub('>', '>')
|
35
|
-
"<pre><code>#{code}</code></pre>"
|
36
|
-
end
|
37
|
-
|
38
|
-
def debug(sub_context)
|
39
|
-
Ruhoh::Friend.say {
|
40
|
-
yellow "?debug:"
|
41
|
-
magenta sub_context.class
|
42
|
-
cyan sub_context.inspect
|
43
|
-
}
|
44
|
-
|
45
|
-
"<pre>#{sub_context.class}\n#{sub_context.pretty_inspect}</pre>"
|
46
|
-
end
|
47
|
-
|
48
|
-
def to_posts(sub_context)
|
49
|
-
Array(sub_context).map { |id|
|
50
|
-
self.context['db']['posts']['dictionary'][id]
|
51
|
-
}.compact
|
52
|
-
end
|
53
|
-
|
54
|
-
def to_pages(sub_context)
|
55
|
-
pages = Array(sub_context).map { |id|
|
56
|
-
self.context['db']['pages'][id]
|
57
|
-
}.compact
|
58
|
-
self.mark_active_page(pages)
|
59
|
-
end
|
60
|
-
|
61
|
-
def to_categories(sub_context)
|
62
|
-
Array(sub_context).map { |id|
|
63
|
-
self.context['db']['posts']['categories'][id]
|
64
|
-
}.compact
|
65
|
-
end
|
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
|
-
|
73
|
-
def next(sub_context)
|
74
|
-
return unless sub_context.is_a?(String) || sub_context.is_a?(Hash)
|
75
|
-
id = sub_context.is_a?(Hash) ? sub_context['id'] : sub_context
|
76
|
-
return unless id
|
77
|
-
index = self.context['db']['posts']['chronological'].index(id)
|
78
|
-
return unless index && (index-1 >= 0)
|
79
|
-
next_id = self.context['db']['posts']['chronological'][index-1]
|
80
|
-
return unless next_id
|
81
|
-
self.to_posts(next_id)
|
82
|
-
end
|
83
|
-
|
84
|
-
def previous(sub_context)
|
85
|
-
return unless sub_context.is_a?(String) || sub_context.is_a?(Hash)
|
86
|
-
id = sub_context.is_a?(Hash) ? sub_context['id'] : sub_context
|
87
|
-
return unless id
|
88
|
-
index = self.context['db']['posts']['chronological'].index(id)
|
89
|
-
return unless index && (index+1 >= 0)
|
90
|
-
prev_id = self.context['db']['posts']['chronological'][index+1]
|
91
|
-
return unless prev_id
|
92
|
-
self.to_posts(prev_id)
|
93
|
-
end
|
94
|
-
|
95
|
-
def analytics
|
96
|
-
return '' if self.context['page']['analytics'].to_s == 'false'
|
97
|
-
analytics_config = self.context['site']['config']['analytics']
|
98
|
-
return '' unless analytics_config && analytics_config['provider']
|
99
|
-
|
100
|
-
if analytics_config['provider'] == "custom"
|
101
|
-
code = self.partial("custom_analytics")
|
102
|
-
else
|
103
|
-
code = self.partial("analytics/#{analytics_config['provider']}")
|
104
|
-
end
|
105
|
-
|
106
|
-
return "<h2 style='color:red'>!Analytics Provider partial for '#{analytics_config['provider']}' not found </h2>" if code.nil?
|
107
|
-
|
108
|
-
self.render(code)
|
109
|
-
end
|
110
|
-
|
111
|
-
def comments
|
112
|
-
return '' if self.context['page']['comments'].to_s == 'false'
|
113
|
-
comments_config = self.context['site']['config']['comments']
|
114
|
-
return '' unless comments_config && comments_config['provider']
|
115
|
-
|
116
|
-
if comments_config['provider'] == "custom"
|
117
|
-
code = self.partial("custom_comments")
|
118
|
-
else
|
119
|
-
code = self.partial("comments/#{comments_config['provider']}")
|
120
|
-
end
|
121
|
-
|
122
|
-
return "<h2 style='color:red'>!Comments Provider partial for '#{comments_config['provider']}' not found </h2>" if code.nil?
|
123
|
-
|
124
|
-
self.render(code)
|
125
|
-
end
|
126
|
-
|
127
|
-
def syntax
|
128
|
-
syntax_config = self.context['site']['config']['syntax']
|
129
|
-
return '' unless syntax_config && syntax_config['provider']
|
130
|
-
|
131
|
-
if syntax_config['provider'] == "custom"
|
132
|
-
code = self.partial("custom_syntax")
|
133
|
-
else
|
134
|
-
code = self.partial("syntax/#{syntax_config['provider']}")
|
135
|
-
end
|
136
|
-
|
137
|
-
return "<h2 style='color:red'>!Syntax Provider partial for '#{syntax_config['provider']}' not found </h2>" if code.nil?
|
138
5
|
|
139
|
-
self.render(code)
|
140
|
-
end
|
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
|
-
|
153
6
|
end #Helpers
|
154
7
|
end #Templaters
|
155
8
|
end #Ruhoh
|
@@ -1,8 +1,12 @@
|
|
1
|
-
|
1
|
+
require 'ruhoh/templaters/base_helpers'
|
2
|
+
require 'ruhoh/templaters/asset_helpers'
|
3
|
+
require 'ruhoh/templaters/helpers'
|
2
4
|
|
5
|
+
class Ruhoh
|
3
6
|
module Templaters
|
4
|
-
|
5
7
|
class RMustache < Mustache
|
8
|
+
include Ruhoh::Templaters::BaseHelpers
|
9
|
+
include Ruhoh::Templaters::AssetHelpers
|
6
10
|
include Ruhoh::Templaters::Helpers
|
7
11
|
|
8
12
|
class RContext < Context
|
@@ -21,9 +25,46 @@ class Ruhoh
|
|
21
25
|
def context
|
22
26
|
@context ||= RContext.new(self)
|
23
27
|
end
|
28
|
+
|
29
|
+
# Lazy-load the page body.
|
30
|
+
# When in a global scope (layouts, pages), the content is for the current page.
|
31
|
+
# May also be called in sub-contexts such as looping through posts.
|
32
|
+
#
|
33
|
+
# {{# posts }}
|
34
|
+
# {{{ content }}}
|
35
|
+
# {{/ posts }}
|
36
|
+
def content
|
37
|
+
content, id = self.get_page_content
|
38
|
+
content = self.render(content)
|
39
|
+
Ruhoh::Converter.convert(content, id)
|
40
|
+
end
|
41
|
+
|
42
|
+
def get_page_content
|
43
|
+
id = self.context['id']
|
44
|
+
id ||= self.context['page']['id']
|
45
|
+
return '' unless id
|
46
|
+
unless id =~ Regexp.new("^#{Ruhoh.names.posts}")
|
47
|
+
id = "#{Ruhoh.names.pages}/#{id}"
|
48
|
+
end
|
49
|
+
|
50
|
+
[Ruhoh::Utils.parse_page_file(Ruhoh.paths.base, id)['content'], id]
|
51
|
+
end
|
52
|
+
|
53
|
+
def widget(name)
|
54
|
+
return '' if self.context['page'][name.to_s].to_s == 'false'
|
55
|
+
Ruhoh::DB.widgets[name.to_s]['layout']
|
56
|
+
end
|
57
|
+
|
58
|
+
def method_missing(name, *args, &block)
|
59
|
+
return self.widget(name.to_s) if Ruhoh::DB.widgets.has_key?(name.to_s)
|
60
|
+
super
|
61
|
+
end
|
24
62
|
|
63
|
+
def respond_to?(method)
|
64
|
+
return true if Ruhoh::DB.widgets.has_key?(method.to_s)
|
65
|
+
super
|
66
|
+
end
|
67
|
+
|
25
68
|
end #RMustache
|
26
|
-
|
27
69
|
end #Templaters
|
28
|
-
|
29
70
|
end #Ruhoh
|
data/lib/ruhoh/urls.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
class Ruhoh
|
2
|
+
# Structured container for all pre-defined URLs in the system.
|
3
|
+
# These URLs are used primarily for static assets in development mode.
|
4
|
+
# When compiling, all urls are of course mapped literally to the asset filepaths.
|
5
|
+
module Urls
|
6
|
+
Urls = Struct.new(
|
7
|
+
:media,
|
8
|
+
:widgets,
|
9
|
+
:dashboard,
|
10
|
+
:theme,
|
11
|
+
:theme_media,
|
12
|
+
:theme_javascripts,
|
13
|
+
:theme_stylesheets,
|
14
|
+
:theme_widgets
|
15
|
+
)
|
16
|
+
|
17
|
+
def self.generate(config)
|
18
|
+
urls = Urls.new
|
19
|
+
urls.media = self.to_url(Ruhoh.names.assets, Ruhoh.names.media)
|
20
|
+
urls.widgets = self.to_url(Ruhoh.names.assets, Ruhoh.names.widgets)
|
21
|
+
urls.dashboard = self.to_url(Ruhoh.names.dashboard_file.split('.')[0])
|
22
|
+
|
23
|
+
urls.theme = self.to_url(Ruhoh.names.assets, config.theme)
|
24
|
+
urls.theme_media = self.to_url(Ruhoh.names.assets, config.theme, Ruhoh.names.media)
|
25
|
+
urls.theme_javascripts = self.to_url(Ruhoh.names.assets, config.theme, Ruhoh.names.javascripts)
|
26
|
+
urls.theme_stylesheets = self.to_url(Ruhoh.names.assets, config.theme, Ruhoh.names.stylesheets)
|
27
|
+
urls.theme_widgets = self.to_url(Ruhoh.names.assets, config.theme, Ruhoh.names.widgets)
|
28
|
+
urls
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.to_url(*args)
|
32
|
+
args.unshift(nil).join('/')
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.to_url_slug(title)
|
36
|
+
CGI::escape self.to_slug(title)
|
37
|
+
end
|
38
|
+
|
39
|
+
# My Post Title ===> my-post-title
|
40
|
+
def self.to_slug(title)
|
41
|
+
title = title.to_s.downcase.strip.gsub(/[^\p{Word}+]/u, '-')
|
42
|
+
title.gsub(/^\-+/, '').gsub(/\-+$/, '').gsub(/\-+/, '-')
|
43
|
+
end
|
44
|
+
|
45
|
+
end #Urls
|
46
|
+
end #Ruhoh
|