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.
Files changed (71) hide show
  1. data/Gemfile +1 -0
  2. data/README.md +0 -33
  3. data/dash.html +1 -0
  4. data/history.json +29 -0
  5. data/lib/ruhoh/client/client.rb +30 -22
  6. data/lib/ruhoh/client/help.yml +6 -2
  7. data/lib/ruhoh/compiler.rb +8 -20
  8. data/lib/ruhoh/compilers/rss.rb +36 -0
  9. data/lib/ruhoh/compilers/theme.rb +41 -0
  10. data/lib/ruhoh/config.rb +49 -0
  11. data/lib/ruhoh/converters/converter.rb +17 -4
  12. data/lib/ruhoh/converters/markdown.rb +2 -2
  13. data/lib/ruhoh/db.rb +29 -2
  14. data/lib/ruhoh/deployers/s3.rb +1 -1
  15. data/lib/ruhoh/logger.rb +1 -1
  16. data/lib/ruhoh/page.rb +38 -22
  17. data/lib/ruhoh/parsers/javascripts.rb +67 -0
  18. data/lib/ruhoh/parsers/layouts.rb +6 -10
  19. data/lib/ruhoh/parsers/pages.rb +17 -24
  20. data/lib/ruhoh/parsers/partials.rb +6 -14
  21. data/lib/ruhoh/parsers/payload.rb +47 -0
  22. data/lib/ruhoh/parsers/posts.rb +27 -29
  23. data/lib/ruhoh/parsers/site.rb +2 -2
  24. data/lib/ruhoh/parsers/stylesheets.rb +75 -0
  25. data/lib/ruhoh/parsers/widgets.rb +104 -0
  26. data/lib/ruhoh/paths.rb +75 -0
  27. data/lib/ruhoh/previewer.rb +11 -5
  28. data/lib/ruhoh/program.rb +35 -4
  29. data/lib/ruhoh/templaters/asset_helpers.rb +66 -0
  30. data/lib/ruhoh/templaters/base_helpers.rb +143 -0
  31. data/lib/ruhoh/templaters/helpers.rb +1 -148
  32. data/lib/ruhoh/templaters/rmustache.rb +45 -4
  33. data/lib/ruhoh/urls.rb +46 -0
  34. data/lib/ruhoh/utils.rb +59 -17
  35. data/lib/ruhoh/version.rb +2 -2
  36. data/lib/ruhoh/watch.rb +26 -14
  37. data/lib/ruhoh.rb +38 -96
  38. data/ruhoh.gemspec +29 -10
  39. data/scaffolds/draft.html +9 -0
  40. data/scaffolds/page.html +0 -2
  41. data/scaffolds/post.html +0 -4
  42. data/scaffolds/theme/{images → javascripts}/.gitkeep +0 -0
  43. data/scaffolds/theme/layouts/default.html +2 -4
  44. data/scaffolds/theme/layouts/page.html +1 -1
  45. data/scaffolds/theme/layouts/post.html +1 -1
  46. data/scaffolds/theme/{css/style.css → media/.gitkeep} +0 -0
  47. data/scaffolds/theme/stylesheets/style.css +0 -0
  48. data/scaffolds/theme/theme.yml +27 -0
  49. data/scaffolds/theme/widgets/.gitkeep +0 -0
  50. data/spec/config_spec.rb +50 -0
  51. data/spec/db_spec.rb +28 -14
  52. data/spec/page_spec.rb +24 -35
  53. data/spec/parsers/layouts_spec.rb +5 -13
  54. data/spec/parsers/pages_spec.rb +13 -11
  55. data/spec/parsers/posts_spec.rb +34 -29
  56. data/spec/parsers/routes_spec.rb +2 -1
  57. data/spec/parsers/site_spec.rb +6 -5
  58. data/spec/setup_spec.rb +3 -47
  59. data/widgets/analytics/config.yml +5 -0
  60. data/{system_partials/analytics/getclicky → widgets/analytics/layouts/getclicky.html} +2 -2
  61. data/{system_partials/analytics/google → widgets/analytics/layouts/google.html} +1 -1
  62. data/widgets/comments/config.yml +12 -0
  63. data/{system_partials/comments/disqus → widgets/comments/layouts/disqus.html} +2 -2
  64. data/{system_partials/comments/facebook → widgets/comments/layouts/facebook.html} +1 -1
  65. data/{system_partials/comments/intensedebate → widgets/comments/layouts/intensedebate.html} +1 -1
  66. data/{system_partials/comments/livefyre → widgets/comments/layouts/livefyre.html} +1 -1
  67. data/widgets/google_prettify/config.yml +1 -0
  68. data/widgets/google_prettify/layouts/google_prettify.html +10 -0
  69. metadata +54 -31
  70. data/lib/ruhoh/templaters/base.rb +0 -57
  71. data/system_partials/syntax/google_prettify +0 -11
@@ -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
@@ -14,8 +14,7 @@ class Ruhoh
14
14
 
15
15
  def call(env)
16
16
  return favicon if env['PATH_INFO'] == '/favicon.ico'
17
- dash = File.basename(Ruhoh.files.dashboard, File.extname(Ruhoh.files.dashboard))
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
- system_dash = File.join(Ruhoh::Root, Ruhoh.files.dashboard)
33
- template = File.open(File.exist?(Ruhoh.paths.dashboard) ? Ruhoh.paths.dashboard : system_dash) {|f| f.read }
34
- output = Ruhoh::Templaters::Base.parse(template, nil)
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(watch=true)
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
- use Rack::Static, {:urls => ["/#{Ruhoh.folders.media}", "/#{Ruhoh.folders.templates}"]}
23
- run Ruhoh::Previewer.new(Ruhoh::Page.new)
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('{', '&#123;').gsub('}', '&#125;').gsub('<', '&lt;').gsub('>', '&gt;')
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('{', '&#123;').gsub('}', '&#125;').gsub('<', '&lt;').gsub('>', '&gt;')
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
- class Ruhoh
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