cartoonist 0.0.3.5 → 0.0.4

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.
Files changed (43) hide show
  1. data/app/assets/javascripts/application.js.erb +2 -0
  2. data/app/assets/stylesheets/admin.css.scss +16 -0
  3. data/app/controllers/admin_controller.rb +93 -0
  4. data/app/controllers/application_controller.rb +38 -0
  5. data/app/controllers/cache_controller.rb +34 -0
  6. data/app/controllers/settings_controller.rb +35 -0
  7. data/app/controllers/site_controller.rb +49 -0
  8. data/app/controllers/static_cache_controller.rb +19 -0
  9. data/app/helpers/application_helper.rb +74 -0
  10. data/app/helpers/cache_helper.rb +17 -0
  11. data/app/models/backup.rb +11 -0
  12. data/app/models/database_file.rb +2 -0
  13. data/app/models/markdown.rb +17 -0
  14. data/app/models/page_cache.rb +102 -0
  15. data/app/models/setting.rb +258 -0
  16. data/app/models/simple_template.rb +20 -0
  17. data/app/models/sitemap_entry.rb +5 -0
  18. data/app/models/static_cache.rb +47 -0
  19. data/app/models/tweetable.rb +17 -0
  20. data/app/views/admin/main.html.erb +7 -0
  21. data/app/views/admin/sign_in.html.erb +19 -0
  22. data/app/views/cache/index.html.erb +61 -0
  23. data/app/views/layouts/admin.html.erb +43 -0
  24. data/app/views/layouts/application.html.erb +134 -0
  25. data/app/views/layouts/application.rss.erb +16 -0
  26. data/app/views/layouts/application.xml.erb +2 -0
  27. data/app/views/layouts/general_admin.html.erb +10 -0
  28. data/app/views/layouts/sign_in.html.erb +12 -0
  29. data/app/views/settings/initial_setup.html.erb +25 -0
  30. data/app/views/settings/show.html.erb +39 -0
  31. data/app/views/site/robots.text.erb +1 -0
  32. data/app/views/site/sitemap.xml.erb +12 -0
  33. data/app/views/static_cache/index.html.erb +29 -0
  34. data/cartoonist.gemspec +3 -2
  35. data/config/locales/en.yml +99 -0
  36. data/db/migrate/20120320043253_create_database_files.rb +9 -0
  37. data/db/migrate/20120401014029_create_settings.rb +12 -0
  38. data/lib/cartoonist/engine.rb +129 -0
  39. data/lib/cartoonist.rb +236 -0
  40. data/public/errors/404.html +13 -0
  41. data/public/errors/422.html +11 -0
  42. data/public/errors/500.html +13 -0
  43. metadata +41 -2
@@ -0,0 +1,258 @@
1
+ class Setting < ActiveRecord::Base
2
+ class << self
3
+ def [](label)
4
+ raise "Invalid label" unless label.present?
5
+ meta = Meta[label.to_sym]
6
+ raise "Missing setting definition for '#{label}'" unless meta
7
+ record = where(:label => label.to_s).first
8
+
9
+ if record
10
+ meta.convert record.value
11
+ elsif meta.type == :array || meta.type == :hash
12
+ meta.default.dup
13
+ else
14
+ meta.default
15
+ end
16
+ end
17
+
18
+ def []=(label, value)
19
+ raise "Invalid label" unless label.present?
20
+ meta = Meta[label.to_sym]
21
+ raise "Missing setting definition for '#{label}'" unless meta
22
+ old_value = self[label]
23
+ record = where(:label => label.to_s).first
24
+ record = Setting.new :label => label.to_s unless record
25
+ record.value = meta.convert_to_save value
26
+ record.save!
27
+ meta.onchange.call if meta.onchange && old_value != value
28
+ value
29
+ end
30
+
31
+ def define(label, options = {})
32
+ Meta[label.to_sym] = Meta.new label, options
33
+ end
34
+
35
+ def tabs
36
+ Tab.all.sort.map &:label
37
+ end
38
+ end
39
+
40
+ class Meta
41
+ attr_reader :label, :tab, :section, :order, :type, :default, :onchange, :select_from
42
+ @@settings = {}
43
+ @@by_tab_section_and_label = {}
44
+
45
+ def initialize(label, options)
46
+ @label = label.to_sym
47
+ @tab = (options[:tab] || Tab.default)
48
+ @section = (options[:section] || Section.default)
49
+ @order = (options[:order] || 0)
50
+ @type = (options[:type] || :string).to_sym
51
+ @onchange = options[:onchange]
52
+ @select_from = options[:select_from]
53
+ raise "Invalid setting type #{@type}" unless [:string, :symbol, :boolean, :int, :float, :array, :hash].include? @type
54
+
55
+ # Auto create general tab and section if it isn't created
56
+ if @tab == :general && !Tab[@tab]
57
+ Tab.define :general, :order => 0
58
+ end
59
+
60
+ if @section == :general && !Section.by_tab_and_label[@tab][@section]
61
+ Section.define :general, :order => 0, :tab => @tab
62
+ end
63
+
64
+ if options.include? :default
65
+ @default = options[:default]
66
+ elsif @type == :string
67
+ @default = ""
68
+ elsif @type == :symbol
69
+ @default = :""
70
+ elsif @type == :boolean
71
+ @default = false
72
+ elsif @type == :int
73
+ @default = 0
74
+ elsif @type == :float
75
+ @default = 0.0
76
+ elsif @type == :array
77
+ @default = []
78
+ elsif @type == :hash
79
+ @default = {}
80
+ end
81
+ end
82
+
83
+ def select_from_options
84
+ if select_from.respond_to? :call
85
+ select_from.call
86
+ else
87
+ select_from
88
+ end
89
+ end
90
+
91
+ def convert(value)
92
+ if value.nil?
93
+ return default.dup if type == :array || type == :hash
94
+ return default
95
+ end
96
+
97
+ case type
98
+ when :string
99
+ value
100
+ when :symbol
101
+ value.to_sym
102
+ when :boolean
103
+ value == "true"
104
+ when :int
105
+ value.to_i
106
+ when :float
107
+ value.to_f
108
+ when :array
109
+ YAML.load value
110
+ when :hash
111
+ YAML.load value
112
+ end
113
+ end
114
+
115
+ def convert_to_save(value)
116
+ return value if value.nil?
117
+
118
+ if type == :boolean
119
+ (!!value).to_s
120
+ elsif type == :array || type == :hash
121
+ value.to_yaml
122
+ else
123
+ value.to_s
124
+ end
125
+ end
126
+
127
+ def <=>(other)
128
+ result = order <=> other.order
129
+ result = label <=> other.label if result == 0
130
+ result
131
+ end
132
+
133
+ class << self
134
+ def [](label)
135
+ raise "Missing setting '#{label}'" unless @@settings[label.to_sym]
136
+ @@settings[label.to_sym]
137
+ end
138
+
139
+ def []=(label, definition)
140
+ raise "Duplicate setting '#{label}' given!" if @@settings[label.to_sym]
141
+ @@settings[label.to_sym] = definition
142
+ @@by_tab_section_and_label[definition.tab] ||= {}
143
+ @@by_tab_section_and_label[definition.tab][definition.section] ||= {}
144
+ @@by_tab_section_and_label[definition.tab][definition.section][label.to_sym] = definition
145
+ end
146
+
147
+ def by_tab_section_and_label
148
+ @@by_tab_section_and_label
149
+ end
150
+ end
151
+ end
152
+
153
+ class Tab
154
+ attr_reader :label, :order
155
+ @@all = []
156
+ @@by_label = {}
157
+ @@default = :general
158
+
159
+ def initialize(label, options = {})
160
+ @label = label.to_sym
161
+ @order = options[:order] || 1
162
+ Section.by_tab_and_label[@label] ||= {}
163
+ end
164
+
165
+ def sections
166
+ Section.by_tab_and_label[label] ||= {}
167
+ Section.by_tab_and_label[label].values.sort.map &:label
168
+ end
169
+
170
+ def [](section_label)
171
+ Section.by_tab_and_label[label] ||= {}
172
+ Section.by_tab_and_label[label][section_label.to_sym]
173
+ end
174
+
175
+ def <=>(other)
176
+ result = order <=> other.order
177
+ result = label <=> other.label if result == 0
178
+ result
179
+ end
180
+
181
+ class << self
182
+ def [](label)
183
+ @@by_label[label.to_sym]
184
+ end
185
+
186
+ def all
187
+ @@all
188
+ end
189
+
190
+ def default
191
+ @@default
192
+ end
193
+
194
+ def define(label, options = {})
195
+ raise "Duplicate tab '#{label}' being defined" if @@by_label.include? label.to_sym
196
+ tab = Tab.new label, options
197
+ @@all << tab
198
+ @@by_label[label.to_sym] = tab
199
+ begin
200
+ @@default = label.to_sym
201
+ yield if block_given?
202
+ ensure
203
+ @@default = :general
204
+ end
205
+ end
206
+ end
207
+ end
208
+
209
+ class Section
210
+ attr_reader :label, :order, :tab
211
+ @@all = []
212
+ @@by_tab_and_label = {}
213
+ @@default = :general
214
+
215
+ def initialize(label, options = {})
216
+ @label = label.to_sym
217
+ @order = options[:order] || 1
218
+ @tab = (options[:tab] || Tab.default).to_sym
219
+ end
220
+
221
+ def settings
222
+ Meta.by_tab_section_and_label[tab][label].values.sort.map &:label
223
+ end
224
+
225
+ def <=>(other)
226
+ result = order <=> other.order
227
+ result = label <=> other.label if result == 0
228
+ result
229
+ end
230
+
231
+ class << self
232
+ def all
233
+ @@all
234
+ end
235
+
236
+ def default
237
+ @@default
238
+ end
239
+
240
+ def define(label, options = {})
241
+ section = Section.new label, options
242
+ @@all << section
243
+ @@by_tab_and_label[section.tab] ||= {}
244
+ @@by_tab_and_label[section.tab][label.to_sym] = section
245
+ begin
246
+ @@default = label.to_sym
247
+ yield if block_given?
248
+ ensure
249
+ @@default = :general
250
+ end
251
+ end
252
+
253
+ def by_tab_and_label
254
+ @@by_tab_and_label
255
+ end
256
+ end
257
+ end
258
+ end
@@ -0,0 +1,20 @@
1
+ class SimpleTemplate
2
+ class << self
3
+ def [](str, variables = {})
4
+ return "" if str.nil?
5
+ variables ||= {}
6
+
7
+ str.gsub /\{\{([^\}]*)\}\}/ do |matched|
8
+ key = $1.strip.to_sym
9
+
10
+ if variables.include? key
11
+ value = variables[key]
12
+ value = value.call if value.respond_to? :call
13
+ value
14
+ else
15
+ ""
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,5 @@
1
+ class SitemapEntry < Struct.new(:path, :lastmod, :changefreq, :priority)
2
+ def formatted_lastmod
3
+ lastmod.strftime "%Y-%m-%d"
4
+ end
5
+ end
@@ -0,0 +1,47 @@
1
+ class StaticCache
2
+ attr_reader :name
3
+
4
+ CACHE_PATH = File.join Rails.root, "public/cache/static"
5
+
6
+ def initialize(name)
7
+ @name = name
8
+ end
9
+
10
+ def expire!
11
+ gz_name = "#{name}.gz"
12
+ StaticCache.cache_files(:with_gz => true).select do |file|
13
+ file == name || file == gz_name
14
+ end.each do |file|
15
+ File.delete File.join(CACHE_PATH, file)
16
+ end
17
+ end
18
+
19
+ class << self
20
+ def find(name)
21
+ name = "" if name == "INDEX"
22
+ actual = cache_files.select { |x| x == name }.first
23
+ raise ActiveRecord::RecordNotFound.new("No records found!") unless actual
24
+ StaticCache.new actual
25
+ end
26
+
27
+ def all
28
+ cache_files.map do |name|
29
+ StaticCache.new name
30
+ end
31
+ end
32
+
33
+ def cache_files(options = {})
34
+ Dir.glob(File.join(CACHE_PATH, "**/*"), File::FNM_DOTMATCH).map do |file|
35
+ next if file =~ /\.gz$/ unless options[:with_gz]
36
+ next if File.directory? file
37
+ file.sub "#{CACHE_PATH}/", ""
38
+ end.compact.sort.uniq
39
+ end
40
+
41
+ def expire_all!
42
+ files = Dir.glob File.join(CACHE_PATH, "**/*"), File::FNM_DOTMATCH
43
+ files.reject! { |file| File.directory? file }
44
+ File.delete *files unless files.empty?
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,17 @@
1
+ module Tweetable
2
+ def tweet!
3
+ return if tweeted?
4
+ return unless Time.now >= expected_tweet_time
5
+
6
+ if Rails.env.production?
7
+ Twitter.update tweet
8
+ end
9
+
10
+ self.tweeted_at = Time.now
11
+ save!
12
+ end
13
+
14
+ def tweeted?
15
+ tweeted_at.present?
16
+ end
17
+ end
@@ -0,0 +1,7 @@
1
+ <p>
2
+ <a href="/admin/reload"><%= t "admin.general.actions.reload" %></a>
3
+ </p>
4
+
5
+ <p>
6
+ <a href="/admin/backup.json"><%= t "admin.general.actions.backup" %></a>
7
+ </p>
@@ -0,0 +1,19 @@
1
+ <% if flash[:error] %>
2
+ <p style="color: red;">
3
+ <%= flash[:error] %>
4
+ </p>
5
+ <% end %>
6
+
7
+ <%= form_tag "/admin/sign_in", :method => :post do %>
8
+ <p>
9
+ Username: <input type="text" name="username" autofocus="autofocus" />
10
+ </p>
11
+
12
+ <p>
13
+ Password: <input type="password" name="password" />
14
+ </p>
15
+
16
+ <p>
17
+ <input type="submit" value="Sign in" />
18
+ </p>
19
+ <% end %>
@@ -0,0 +1,61 @@
1
+ <p>
2
+ <%= form_tag "/cache/expire_www", :method => :post, :class => "inline" do %>
3
+ <input type="submit" value="<%= t "cache.index.expire_www" %>" />
4
+ <% end %>
5
+
6
+ <%= form_tag "/cache/expire_m", :method => :post, :class => "inline" do %>
7
+ <input type="submit" value="<%= t "cache.index.expire_m" %>" />
8
+ <% end %>
9
+
10
+ <%= form_tag "/cache/expire_tmp", :method => :post, :class => "inline" do %>
11
+ <input type="submit" value="<%= t "cache.index.expire_tmp" %>" />
12
+ <% end %>
13
+
14
+ <%= form_tag "/cache/expire_all", :method => :post, :class => "inline" do %>
15
+ <input type="submit" value="<%= t "cache.index.expire_all" %>" />
16
+ <% end %>
17
+ </p>
18
+
19
+ <p>
20
+ <table class="cache">
21
+ <thead>
22
+ <tr>
23
+ <th><%= t "cache.index.page" %></th>
24
+ <th><%= t "cache.index.www" %></th>
25
+ <th><%= t "cache.index.m" %></th>
26
+ <th><%= t "cache.index.www_tmp" %></th>
27
+ <th><%= t "cache.index.m_tmp" %></th>
28
+ <th></th>
29
+ </tr>
30
+ </thead>
31
+ <tbody>
32
+ <% @caches.each do |cache| %>
33
+ <tr>
34
+ <td><%= cache.display_name %></td>
35
+
36
+ <td class="<%= td_cache_class cache.www? %>">
37
+ <%= td_cache_text cache.www? %>
38
+ </td>
39
+
40
+ <td class="<%= td_cache_class cache.m? %>">
41
+ <%= td_cache_text cache.m? %>
42
+ </td>
43
+
44
+ <td class="<%= td_cache_class cache.www_tmp? %>">
45
+ <%= td_cache_text cache.www_tmp? %>
46
+ </td>
47
+
48
+ <td class="<%= td_cache_class cache.m_tmp? %>">
49
+ <%= td_cache_text cache.m_tmp? %>
50
+ </td>
51
+
52
+ <td>
53
+ <%= form_tag "/cache/#{u cache.delete_name}", :method => :delete do %>
54
+ <input type="submit" value="<%= t "cache.index.expire" %>" />
55
+ <% end %>
56
+ </td>
57
+ </tr>
58
+ <% end %>
59
+ </tbody>
60
+ </table>
61
+ </p>
@@ -0,0 +1,43 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title><%= yield(:title) || Setting[:site_name] %></title>
5
+ <%= stylesheet_link_tag "admin.css" %>
6
+ <%= csrf_meta_tags %>
7
+ <link rel="icon" href="http://<%= Setting[:domain] %><%= asset_path Cartoonist::Theme.favicon %>" type="image/x-icon" />
8
+ <link rel="shortcut icon" href="http://<%= Setting[:domain] %><%= asset_path Cartoonist::Theme.favicon %>" type="image/x-icon" />
9
+ </head>
10
+ <body>
11
+ <p class="tabs">
12
+ <% Cartoonist::Admin::Tab.all.each do |tab| %>
13
+ <a class="tab" href="<%= Cartoonist::Admin::Tab[tab] %>"><%= t tab, :scope => "admin.layout.tab" %></a>
14
+ <% end %>
15
+ | <%= t "admin.layout.user_heading", :user => session[:user] %> <a href="/admin/logout"><%= t "admin.layout.logout" %></a>
16
+ </p>
17
+
18
+ <% if content_for? :subtabs %>
19
+ <p class="subtabs">
20
+ <%= yield :subtabs %>
21
+ </p>
22
+ <% end %>
23
+
24
+ <% if Rails.env.production? %>
25
+ <p style="background-color: red; color: white; font-size: 20px; font-weight: bold; text-align: center;">
26
+ <%= t "admin.layout.production_warning" %>
27
+ </p>
28
+ <% else %>
29
+ <p style="background-color: yellow; color: black; font-size: 20px; text-align: center;">
30
+ <%= t "admin.layout.not_live_warning" %>
31
+ </p>
32
+ <% end %>
33
+
34
+ <% if flash[:message] %>
35
+ <p style="color: red;">
36
+ <%= flash[:message] %>
37
+ </p>
38
+ <% end %>
39
+
40
+ <h1><%= yield :page_title %></h1>
41
+ <%= content_for?(:content) ? yield(:content) : yield %>
42
+ </body>
43
+ </html>
@@ -0,0 +1,134 @@
1
+ <!DOCTYPE html>
2
+ <html class="<%= html_class %>">
3
+ <head>
4
+ <title><%= yield(:title) || Setting[:site_name] %></title>
5
+ <%= stylesheet_link_tag Cartoonist::Theme.css %>
6
+ <% if @output_csrf_meta_tags %>
7
+ <%= csrf_meta_tags %>
8
+ <% end %>
9
+ <link rel="icon" href="http://<%= Setting[:domain] %><%= asset_path Cartoonist::Theme.favicon %>" type="image/x-icon" />
10
+ <link rel="shortcut icon" href="http://<%= Setting[:domain] %><%= asset_path Cartoonist::Theme.favicon %>" type="image/x-icon" />
11
+ <% if rss? %>
12
+ <link href="<%= rss_path %>" rel="alternate" title="<%= rss_title %>" type="application/rss+xml" />
13
+ <% end %>
14
+ <% if !preview? && Rails.env.production? %>
15
+ <script type="text/javascript">
16
+ var _gaq = _gaq || [];
17
+ _gaq.push(['_setAccount', '<%= j Setting[:google_analytics_account] %>']);
18
+ _gaq.push(['_trackPageview']);
19
+
20
+ (function() {
21
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
22
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
23
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
24
+ })();
25
+ </script>
26
+ <% elsif !preview? %>
27
+ <!-- Google analytics goes here on live -->
28
+ <% end %>
29
+ </head>
30
+ <body>
31
+ <div class="site-wrapper">
32
+ <div class="header">
33
+ <div class="main-header">
34
+ <div class="logo"><%= t "application.layout.logo" %></div>
35
+ <h1 class="site-name"><%= Setting[:site_name] %></h1>
36
+ <h2 class="heading"><%= Setting[:site_heading] %></h2>
37
+ <h2 class="site-updates"><%= Setting[:site_update_description] %></h2>
38
+
39
+ <div class="small-buttons">
40
+ <%= yield :small_buttons %>
41
+ </div>
42
+ </div>
43
+
44
+ <div class="navigation">
45
+ <div class="long-buttons">
46
+ <% Cartoonist::Navigation::Link.all.each do |link| %>
47
+ <a class="<%= link.class %>" href="<%= link.url preview? %>" title="<%= t link.title if link.title %>"><%= t link.label %></a>
48
+ <% end %>
49
+ </div>
50
+ </div>
51
+ </div>
52
+
53
+ <div class="content-container">
54
+ <div class="content-header"></div>
55
+ <div class="content <%= yield(:content_class) || "default-content" %>">
56
+ <%= content_for?(:content) ? yield(:content) : yield %>
57
+ </div>
58
+ <div class="content-footer"></div>
59
+ </div>
60
+
61
+ <% if @disqus_enabled %>
62
+ <div class="comments-container">
63
+ <div id="disqus_thread">
64
+ <% if @disqus_options[:count_link] %>
65
+ <a id="disqus_comments" href="#disqus_thread" data-disqus-identifier="/<%= @disqus_options[:path] %>"></a>
66
+ <% end %>
67
+ </div>
68
+ <noscript>
69
+ <%= t "application.layout.disqus.noscript_pre_link" %><a href="http://disqus.com/?ref_noscript"><%= t "application.layout.disqus.noscript_link" %></a><%= t "application.layout.disqus.noscript_post_link" %>
70
+ </noscript>
71
+ </div>
72
+ <% end %>
73
+
74
+ <div class="footer">
75
+ <%= yield :post_date_content %>
76
+ <p class="copyright"><%= copyright_message %></p>
77
+ <%= yield :admin_content %>
78
+ <% if licensed? %>
79
+ <div class="license">
80
+ <p>
81
+ This work is licensed under a
82
+ <a href="<%= content_license_url %>">Creative Commons
83
+ Attribution-Noncommercial 3.0 Unported License</a>.
84
+ <a href="/license">See details</a>.
85
+ </p>
86
+
87
+ <div class="license-buttons-container">
88
+ <div class="license-buttons">
89
+ <a href="<%= content_license_url %>" class="cc-logo">Creative Commons</a>
90
+ <a href="<%= content_license_url %>" class="cc-attribute">Attribution</a>
91
+ <a href="<%= content_license_url %>" class="cc-non-commercial">Noncommercial</a>
92
+ </div>
93
+ </div>
94
+ </div>
95
+ <% end %>
96
+ </div>
97
+ </div>
98
+ <% if @disqus_enabled && Rails.env.production? %>
99
+ <script type="text/javascript">
100
+ var disqus_shortname = "<%= j Setting[:disqus_shortname] %>";
101
+ var disqus_title = "<%= j @disqus_options[:title] %>";
102
+ var disqus_category_id = "<%= j @disqus_options[:category].to_s %>";
103
+ var disqus_identifier = "/<%= j @disqus_options[:path] %>";
104
+ var disqus_url = "http://<%= j Setting[:domain] %>/<%= j @disqus_options[:path] %>";
105
+ <% if @disqus_options[:count_link] %>
106
+ (function () {
107
+ var s = document.createElement('script'); s.async = true;
108
+ s.type = 'text/javascript';
109
+ s.src = 'http://' + disqus_shortname + '.disqus.com/count.js';
110
+ (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(s);
111
+ }());
112
+
113
+ var comments = document.getElementById("disqus_comments");
114
+ comments.onclick = function() {
115
+ document.getElementById("disqus_thread").removeChild(comments);
116
+ var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
117
+ dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
118
+ (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
119
+ return false;
120
+ };
121
+ <% else %>
122
+ (function() {
123
+ var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
124
+ dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
125
+ (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
126
+ })();
127
+ <% end %>
128
+ </script>
129
+ <% end %>
130
+ <% if Cartoonist::Asset.included_js? %>
131
+ <%= javascript_include_tag "application" %>
132
+ <% end %>
133
+ </body>
134
+ </html>
@@ -0,0 +1,16 @@
1
+ <?xml version="1.0" encoding="UTF-8" ?>
2
+ <rss version="2.0">
3
+ <channel>
4
+ <title><%= yield :rss_title %></title>
5
+ <description><%= Setting[:site_heading] %></description>
6
+ <link>http://<%= Setting[:domain] %>/</link>
7
+ <pubDate><%= yield :pub_date %></pubDate>
8
+ <lastBuildDate><%= yield :pub_date %></lastBuildDate>
9
+ <image>
10
+ <url>http://<%= Setting[:domain] %><%= asset_path Cartoonist::Theme.rss_logo %></url>
11
+ <title><%= Setting[:site_name] %></title>
12
+ <link>http://<%= Setting[:domain] %></link>
13
+ </image>
14
+ <%= yield %>
15
+ </channel>
16
+ </rss>
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0" encoding="UTF-8" ?>
2
+ <%= yield %>
@@ -0,0 +1,10 @@
1
+ <% content_for :subtabs do %>
2
+ <a class="subtab" href="/admin"><%= t "admin.general.layout.actions" %></a>
3
+ <a class="subtab" href="/settings"><%= t "admin.general.layout.settings" %></a>
4
+ <a class="subtab" href="/cache"><%= t "admin.general.layout.cache" %></a>
5
+ <a class="subtab" href="/static_cache"><%= t "admin.general.layout.static_cache" %></a>
6
+ <% end %>
7
+
8
+ <% content_for :page_title, t("admin.general.layout.section") %>
9
+ <% content_for(:content) { yield } %>
10
+ <%= render :template => "layouts/admin" %>
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Sign In</title>
5
+ <%= csrf_meta_tags %>
6
+ <link rel="icon" href="http://<%= Setting[:domain] %><%= asset_path Cartoonist::Theme.favicon %>" type="image/x-icon" />
7
+ <link rel="shortcut icon" href="http://<%= Setting[:domain] %><%= asset_path Cartoonist::Theme.favicon %>" type="image/x-icon" />
8
+ </head>
9
+ <body>
10
+ <%= yield %>
11
+ </body>
12
+ </html>