[noosfero/noosfero][next] 3 commits: Add HACKING.themes.md

Rodrigo Souto gitlab at gitlab.com
Fri Mar 27 15:23:31 BRT 2015


Rodrigo Souto pushed to next at Noosfero / noosfero


Commits:
ce2d243c by Aurélio A. Heckert at 2015-03-13T19:23:58Z
Add HACKING.themes.md

- - - - -
8a831990 by Aurélio A. Heckert at 2015-03-26T19:10:52Z
Add global theme intervention spaces

When the env theme has `global.css`, `global_header.html.erb`, or `global_footer.html.erb`, that content is added to any customized profile theme.

- - - - -
fe3c0b17 by Rodrigo Souto at 2015-03-27T18:23:26Z
Merge branch 'env-bars' into 'next'

Add global theme intervention spaces

When the env theme has `global.css`, `global_header.html.erb`, or `global_footer.html.erb`, that content is added to any customized profile theme.

See merge request !529

- - - - -


8 changed files:

- + HACKING.themes.md
- app/helpers/application_helper.rb
- app/helpers/layout_helper.rb
- app/views/layouts/application-ng.html.erb
- app/views/layouts/application.html.erb
- public/stylesheets/application.css
- test/unit/application_helper_test.rb
- test/unit/layout_helper_test.rb


Changes:

=====================================
HACKING.themes.md
=====================================
--- /dev/null
+++ b/HACKING.themes.md
@@ -0,0 +1,60 @@
+Noosfero Instructions for Theme Developers
+==========================================
+
+To build Noosfero themes you must to know HTML and CSS. You may also get some advantages with Ruby and Noosfero hacking knowledge because all customizable pieces of the theme's HTML structure are [erb](http://en.wikipedia.org/wiki/ERuby) files.
+
+
+Organization Basics
+-------------------
+
+A theme is a directory and must inside `noosfero/public/designs/themes`, and you will find tis themes in a fresh installation:
+`noosfero`, `aluminium`, `base`, `butter`, `chameleon`, `chocolate`, `orange`, `plum`, `scarletred` and `skyblue`. The `default` is only a link to `noosfero` and you can change this link to any other.
+
+`noosfero` is the default theme with a big header. All other are colored themes with a thin header. That colored ones can be used as additional themes for any environment, as they will search for `/images/thin-logo.png` inside the current environment.theme, to use as top left logo.
+
+Inside a theme we can found:
+* `theme.yml` — Theme description with some nice configuration options.
+* `preview.png` — A 100x100 screenshot of this theme to the theme selection UI.
+* `style.css` — The main file. The magic happens here.
+* `errors.css` — Change the error page look. (only if this theme is linked by `defaut`)
+* `favicon.ico` — The identifier icon for your web site.
+* `images` — Another name can be found by your CSS, but will not allow to reuse the logo.
+  * `thin-logo.png` — The logo to be reused by the colored themes.
+  * *many images...*
+* `site_title.html.erb` — A nice place to put your logo, any code here will be placed inside `h1#site-title`.
+* `header.html.erb` — That goes inside `div#theme-header`.
+* `navigation.html.erb` — That goes inside `div#navigation ul`, so use `<li>`s.
+* `footer.html.erb` — That goes inside `div#theme-footer`.
+
+You can add more files like javascript and modularized CSS, but you must to refer that by the described files above.
+
+To refer one of this files trough the web the path is `<domain>/designs/themes/<thistheme>/<somefile>`.
+
+
+theme.yml
+---------
+
+A simple definition file. See this example:
+```yml
+name: "My Cool Theme"
+layout: "application-ng"
+jquery_theme: "smoothness"
+icon_theme: [default, pidgin]
+gravatar: "retro"
+```
+
+About non obvious:
+* `layout` is about the theme structure to use. The `application-ng` is enough for 99.97358% use cases. If you want to use another structure, you must add a new `*.html.erb` file at `app/views/layouts/`.
+* `icon_theme` point to something inside `public/designs/icons/`.
+* `gravatar` set the default gravatar *(avatar picture)* for people without picture.
+
+
+Theme Intervention from Environment Theme
+-----------------------------------------
+
+Sometimes an environment (as instace http://cirandas.net) wants to allow profiles to set its own theme, but with some environment identification or functions, like a top bar with the social network logo and a top menu (as instace http://cirandas.net/rango-vegan).
+To make the magic happens you can add some files to the environment theme.
+All are optional:
+* `global.css` — this must be used to style all extra html added by your intervention partials. As it is a free form css file you can style anything, but this is a conflict risk.
+* `global_header.html.erb` — Will add content to `#global-header`.
+* `global_footer.html.erb` — Will add content to `#global-footer`.

=====================================
app/helpers/application_helper.rb
=====================================
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -398,19 +398,27 @@ module ApplicationHelper
       end
   end
 
-  def theme_view_file(template)
+  def theme_view_file(template, theme=nil)
     # Since we cannot control what people are doing in external themes, we
     # will keep looking for the deprecated .rhtml extension here.
-    file = Rails.root.join('public', theme_path[1..-1], template + '.html.erb')
+    addr = theme ? "designs/themes/#{theme}" : theme_path[1..-1]
+    file = Rails.root.join('public', addr, template + '.html.erb')
     return file if File.exists?(file)
     nil
   end
 
   def theme_include(template, options = {})
-    file = theme_view_file(template)
-    options.merge!({:file => file, :use_full_path => false})
+    from_theme_include(nil, template, options)
+  end
+
+  def env_theme_include(template, options = {})
+    from_theme_include(environment.theme, template, options)
+  end
+
+  def from_theme_include(theme, template, options = {})
+    file = theme_view_file(template, theme)
     if file
-      render options
+      render options.merge(file: file, use_full_path: false)
     else
       nil
     end
@@ -446,6 +454,14 @@ module ApplicationHelper
     @theme_extra_navigation ||= theme_include 'navigation'
   end
 
+  def global_header
+    @global_header ||= env_theme_include 'global_header'
+  end
+
+  def global_footer
+    @global_footer ||= env_theme_include 'global_footer'
+  end
+
   def is_testing_theme
     !controller.session[:theme].nil?
   end

=====================================
app/helpers/layout_helper.rb
=====================================
--- a/app/helpers/layout_helper.rb
+++ b/app/helpers/layout_helper.rb
@@ -52,22 +52,30 @@ module LayoutHelper
       'selectordie-theme',
       pngfix_stylesheet_path,
     ] + tokeninput_stylesheets
-    plugins_stylesheets = @plugins.select(&:stylesheet?).map { |plugin| plugin.class.public_path('style.css') }
-
-    output = ''
-    output += stylesheet_link_tag standard_stylesheets, :cache => 'cache/application'
-    output += stylesheet_link_tag template_stylesheet_path
-    output += stylesheet_link_tag icon_theme_stylesheet_path
-    output += stylesheet_link_tag jquery_ui_theme_stylesheet_path
+    plugins_stylesheets = @plugins.select(&:stylesheet?).map { |plugin|
+      plugin.class.public_path('style.css')
+    }
+    global_css_pub = "/designs/themes/#{environment.theme}/global.css"
+    global_css_at_fs = Rails.root.join 'public' + global_css_pub
+
+    output = []
+    output << stylesheet_link_tag(standard_stylesheets, :cache => 'cache/application')
+    output << stylesheet_link_tag(template_stylesheet_path)
+    output << stylesheet_link_tag(icon_theme_stylesheet_path)
+    output << stylesheet_link_tag(jquery_ui_theme_stylesheet_path)
     unless plugins_stylesheets.empty?
-      output += stylesheet_link_tag plugins_stylesheets, :cache => "cache/plugins-#{Digest::MD5.hexdigest plugins_stylesheets.to_s}"
+      cacheid = "cache/plugins-#{Digest::MD5.hexdigest plugins_stylesheets.to_s}"
+      output << stylesheet_link_tag(plugins_stylesheets, :cache => cacheid)
     end
-    output += stylesheet_link_tag theme_stylesheet_path
-    output
+    if File.exists? global_css_at_fs
+      output << stylesheet_link_tag(global_css_pub)
+    end
+    output << stylesheet_link_tag(theme_stylesheet_path)
+    output.join "\n"
   end
 
   def pngfix_stylesheet_path
-    'iepngfix/iepngfix.css'
+    'iepngfix/iepngfix.css' #TODO: deprecate it
   end
 
   def tokeninput_stylesheets

=====================================
app/views/layouts/application-ng.html.erb
=====================================
--- a/app/views/layouts/application-ng.html.erb
+++ b/app/views/layouts/application-ng.html.erb
@@ -25,7 +25,7 @@
       end.join("\n")
     %>
 
-    <script type='text/javascript'>
+    <script type="text/javascript">
       DEFAULT_LOADING_MESSAGE = <%="'#{ _('loading...') }'" %>;
     </script>
 
@@ -38,9 +38,12 @@
         if content.respond_to?(:call) then instance_exec(&content).to_s.html_safe else content.to_s.html_safe end
       end.join("\n")
     %>
+    <div id="global-header">
+      <%= global_header %>
+    </div>
 
     <div id="wrap-1">
-      <div id='theme-header'>
+      <div id="theme-header">
         <%= theme_header %>
       </div>
       <div id="wrap-2">
@@ -60,9 +63,14 @@
       </div><!-- end id="wrap-2" -->
     </div><!-- end id="wrap-1" -->
     <%= render_environment_features(:logged_in) if logged_in? %>
-    <div id="theme-footer">
-      <%= theme_footer %>
-    </div><!-- end id="theme-footer" -->
+    <div id="footer">
+      <div id="theme-footer">
+        <%= theme_footer %>
+      </div><!-- end id="theme-footer" -->
+      <div id="global-footer">
+        <%= global_footer %>
+      </div><!-- end id="global-footer" -->
+    </div><!-- end id="footer" -->
     <%= noosfero_layout_features %>
     <%= addthis_javascript %>
     <%=

=====================================
app/views/layouts/application.html.erb
=====================================
--- a/app/views/layouts/application.html.erb
+++ b/app/views/layouts/application.html.erb
@@ -52,6 +52,9 @@
       registerDocumentSize();
       // -->
     </script>
+    <div id="global-header">
+      <%= global_header %>
+    </div>
 
     <div id="accessibility_menu">
       <a href="#content" id="link_go_content"><span><%= _('Go to content') %></span></a>
@@ -112,8 +115,13 @@
     </div><!-- id="wrap" -->
 
     <div id="footer">
-      <%= theme_footer %>
-    </div><!-- id="footer" -->
+      <div id="theme-footer">
+        <%= theme_footer %>
+      </div><!-- end id="theme-footer" -->
+      <div id="global-footer">
+        <%= global_footer %>
+      </div><!-- end id="global-footer" -->
+    </div><!-- end id="footer" -->
 
     <%# if you need to add HTML stuff to the layout, include it in
     app/views/shared/noosfero_layout_features.html.erb! %>

=====================================
public/stylesheets/application.css
=====================================
--- a/public/stylesheets/application.css
+++ b/public/stylesheets/application.css
@@ -77,19 +77,6 @@ div#errorExplanation h2 {
 #footer_content {
   clear: both;
 }
-#footer {
-  text-align: center;
-  clear: both;
-  font-size: 10px;
-  color: #777;
-}
-#footer a {
-  color: #777;
-  text-decoration: none;
-}
-#footer a:hover {
-  color: #555;
-}
 div#profile-disabled {
   border: 2px solid #944;
   text-align: center;

=====================================
test/unit/application_helper_test.rb
=====================================
--- a/test/unit/application_helper_test.rb
+++ b/test/unit/application_helper_test.rb
@@ -961,6 +961,47 @@ class ApplicationHelperTest < ActionView::TestCase
     assert_equal '', manage_communities
   end
 
+  should 'include file from current theme out of a profile page' do
+    def profile; nil; end
+    def environment; e={}; def e.theme; 'env-theme'; end; e; end
+    def render(opt); opt; end
+    File.stubs(:exists?).returns(false)
+    file = Rails.root.join 'public/designs/themes/env-theme/somefile.html.erb'
+    assert_nil theme_include('somefile') # exists? = false
+    File.expects(:exists?).with(file).returns(true).at_least_once
+    assert_equal file, theme_include('somefile')[:file] # exists? = true
+  end
+
+  should 'include file from current theme inside a profile page' do
+    def profile; p={}; def p.theme; 'my-theme'; end; p; end
+    def render(opt); opt; end
+    File.stubs(:exists?).returns(false)
+    file = Rails.root.join 'public/designs/themes/my-theme/otherfile.html.erb'
+    assert_nil theme_include('otherfile') # exists? = false
+    File.expects(:exists?).with(file).returns(true).at_least_once
+    assert_equal file, theme_include('otherfile')[:file] # exists? = true
+  end
+
+  should 'include file from env theme' do
+    def profile; p={}; def p.theme; 'my-theme'; end; p; end
+    def environment; e={}; def e.theme; 'env-theme'; end; e; end
+    def render(opt); opt; end
+    File.stubs(:exists?).returns(false)
+    file = Rails.root.join 'public/designs/themes/env-theme/afile.html.erb'
+    assert_nil env_theme_include('afile') # exists? = false
+    File.expects(:exists?).with(file).returns(true).at_least_once
+    assert_equal file, env_theme_include('afile')[:file] # exists? = true
+  end
+
+  should 'include file from some theme' do
+    def render(opt); opt; end
+    File.stubs(:exists?).returns(false)
+    file = Rails.root.join 'public/designs/themes/atheme/afile.html.erb'
+    assert_nil from_theme_include('atheme', 'afile') # exists? = false
+    File.expects(:exists?).with(file).returns(true).at_least_once
+    assert_equal file, from_theme_include('atheme', 'afile')[:file] # exists? = true
+  end
+
   protected
   include NoosferoTestHelper
 

=====================================
test/unit/layout_helper_test.rb
=====================================
--- a/test/unit/layout_helper_test.rb
+++ b/test/unit/layout_helper_test.rb
@@ -1,6 +1,7 @@
 require_relative "../test_helper"
 
 class LayoutHelperTest < ActionView::TestCase
+  include ApplicationHelper
 
   should 'append logged-in class in body when user is logged-in' do
     expects(:logged_in?).returns(true)
@@ -14,4 +15,19 @@ class LayoutHelperTest < ActionView::TestCase
     assert_not_includes body_classes.split, 'logged-in'
   end
 
+  should 'add global.css to noosfero_stylesheets if env theme has it' do
+    env = fast_create Environment
+    env.theme = 'my-theme'
+    @plugins = []
+    expects(:profile).returns(nil).at_least_once
+    expects(:environment).returns(env).at_least_once
+    expects(:theme_option).with(:icon_theme).returns(['my-icons']).at_least_once
+    expects(:jquery_theme).returns('jquery-nice').at_least_once
+    global_css = Rails.root.join "public/designs/themes/#{env.theme}/global.css"
+    File.stubs(:exists?).returns(false)
+    File.expects(:exists?).with(global_css).returns(true).at_least_once
+    css = noosfero_stylesheets
+    assert_match /<link [^<]*href="\/designs\/themes\/my-theme\/global.css"/, css
+  end
+
 end


View it on GitLab: https://gitlab.com/noosfero/noosfero/compare/fa17646bfe9fc2dc837edef3150b921170c170c8...fe3c0b17eb9366bd157e8c85ee9fec00a62cbed5
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listas.softwarelivre.org/pipermail/noosfero-dev/attachments/20150327/7e75496b/attachment-0001.html>


More information about the Noosfero-dev mailing list