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