feature_box 0.8.1

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 (86) hide show
  1. data/CHANGELOG.rdoc +1 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +107 -0
  4. data/app/assets/javascripts/feature_box/application.js +39 -0
  5. data/app/assets/stylesheets/feature_box/application.css.scss +133 -0
  6. data/app/assets/stylesheets/feature_box/comments.css.scss +41 -0
  7. data/app/assets/stylesheets/feature_box/mixins.css.scss +37 -0
  8. data/app/assets/stylesheets/feature_box/suggestions.css.scss +110 -0
  9. data/app/controllers/feature_box/application_controller.rb +37 -0
  10. data/app/controllers/feature_box/categories_controller.rb +43 -0
  11. data/app/controllers/feature_box/comments_controller.rb +46 -0
  12. data/app/controllers/feature_box/devise/passwords_controller.rb +4 -0
  13. data/app/controllers/feature_box/devise/redirects.rb +21 -0
  14. data/app/controllers/feature_box/devise/registrations_controller.rb +4 -0
  15. data/app/controllers/feature_box/devise/sessions_controller.rb +4 -0
  16. data/app/controllers/feature_box/home_controller.rb +8 -0
  17. data/app/controllers/feature_box/suggestions_controller.rb +161 -0
  18. data/app/controllers/feature_box/users_controller.rb +32 -0
  19. data/app/helpers/feature_box/application_helper.rb +40 -0
  20. data/app/mailers/feature_box/devise/mailer.rb +3 -0
  21. data/app/models/feature_box/ability.rb +25 -0
  22. data/app/models/feature_box/category.rb +15 -0
  23. data/app/models/feature_box/comment.rb +15 -0
  24. data/app/models/feature_box/suggestion.rb +113 -0
  25. data/app/models/feature_box/user.rb +61 -0
  26. data/app/models/feature_box/vote.rb +6 -0
  27. data/app/views/feature_box/categories/_form.html.haml +14 -0
  28. data/app/views/feature_box/categories/edit.html.haml +3 -0
  29. data/app/views/feature_box/categories/index.html.haml +26 -0
  30. data/app/views/feature_box/categories/new.html.haml +3 -0
  31. data/app/views/feature_box/comments/_comment.html.haml +9 -0
  32. data/app/views/feature_box/comments/_new.html.haml +9 -0
  33. data/app/views/feature_box/comments/edit.html.haml +17 -0
  34. data/app/views/feature_box/comments/index.html.haml +8 -0
  35. data/app/views/feature_box/devise/_links.html.haml +9 -0
  36. data/app/views/feature_box/devise/confirmations/new.html.haml +7 -0
  37. data/app/views/feature_box/devise/mailer/confirmation_instructions.html.haml +4 -0
  38. data/app/views/feature_box/devise/mailer/reset_password_instructions.html.haml +6 -0
  39. data/app/views/feature_box/devise/mailer/unlock_instructions.html.haml +5 -0
  40. data/app/views/feature_box/devise/passwords/edit.html.haml +7 -0
  41. data/app/views/feature_box/devise/passwords/new.html.haml +5 -0
  42. data/app/views/feature_box/devise/registrations/edit.html.haml +16 -0
  43. data/app/views/feature_box/devise/registrations/new.html.haml +8 -0
  44. data/app/views/feature_box/devise/sessions/new.html.haml +8 -0
  45. data/app/views/feature_box/shared/_pages_nav.html.haml +6 -0
  46. data/app/views/feature_box/suggestions/_form.html.haml +30 -0
  47. data/app/views/feature_box/suggestions/_order_nav.html.haml +6 -0
  48. data/app/views/feature_box/suggestions/_search.html.haml +4 -0
  49. data/app/views/feature_box/suggestions/_suggestion.html.haml +31 -0
  50. data/app/views/feature_box/suggestions/edit.html.haml +3 -0
  51. data/app/views/feature_box/suggestions/index.html.haml +27 -0
  52. data/app/views/feature_box/suggestions/new.html.haml +6 -0
  53. data/app/views/feature_box/suggestions/show.html.haml +2 -0
  54. data/app/views/feature_box/users/edit.html.haml +14 -0
  55. data/app/views/feature_box/users/index.html.haml +24 -0
  56. data/app/views/layouts/feature_box/application.html.haml +81 -0
  57. data/config/initializers/devise.rb +3 -0
  58. data/config/routes.rb +35 -0
  59. data/db/seeds.rb +11 -0
  60. data/lib/feature_box.rb +72 -0
  61. data/lib/feature_box/engine.rb +5 -0
  62. data/lib/feature_box/helpers.rb +49 -0
  63. data/lib/feature_box/version.rb +3 -0
  64. data/lib/generators/feature_box/existing_generator.rb +26 -0
  65. data/lib/generators/feature_box/generator_base.rb +47 -0
  66. data/lib/generators/feature_box/initializer_generator.rb +14 -0
  67. data/lib/generators/feature_box/migrations_generator.rb +25 -0
  68. data/lib/generators/feature_box/standalone_generator.rb +27 -0
  69. data/lib/generators/feature_box/templates/initializers/initializer.rb +32 -0
  70. data/lib/generators/feature_box/templates/initializers/new_devise_initializer.rb +8 -0
  71. data/lib/generators/feature_box/templates/migrations/00_create_feature_box_suggestions.rb +15 -0
  72. data/lib/generators/feature_box/templates/migrations/01_create_feature_box_categories.rb +9 -0
  73. data/lib/generators/feature_box/templates/migrations/02_create_feature_box_comments.rb +13 -0
  74. data/lib/generators/feature_box/templates/migrations/03_create_feature_box_votes.rb +12 -0
  75. data/lib/generators/feature_box/templates/migrations/04_create_feature_box_users.rb +10 -0
  76. data/lib/generators/feature_box/templates/migrations/05_add_devise_to_feature_box_users.rb +50 -0
  77. data/lib/generators/feature_box/templates/migrations/06_add_type_to_{model_name}.rb +5 -0
  78. data/lib/generators/feature_box/views_generator.rb +14 -0
  79. data/lib/tasks/feature_box_tasks.rake +9 -0
  80. data/test/existing-template/application.html.erb +40 -0
  81. data/test/existing-template/application_helper.rb +11 -0
  82. data/test/existing-template/index.html.erb +1 -0
  83. data/test/run-all-tests.sh +7 -0
  84. data/test/template.rb +29 -0
  85. data/vendor/assets/stylesheets/bootstrap.min.css +689 -0
  86. metadata +250 -0
@@ -0,0 +1,6 @@
1
+ %li{:style => "float:right"}
2
+ = link_to_if(@current_page<@last_page, "next", {:page=>@current_page+1}) do
3
+ %a.disabled next
4
+ %li{:style => "float:right"}
5
+ = link_to_if(@current_page > 1, "previous", {:page=>@current_page-1}) do
6
+ %a.disabled previous
@@ -0,0 +1,4 @@
1
+ %form{:action => search_suggestions_path, :method=> "get", :class=>"well"}
2
+ %h3 What do you want to see in our product?
3
+ %div.input-append#search-field
4
+ = text_field_tag(:q,'', :placeholder=> "Look for existing suggestions first", :autocomplete=>"off", :value=>params[:q])+raw('<input class="btn" type="submit" value="Search"/>')
@@ -0,0 +1,31 @@
1
+ - partial = @suggestion==nil
2
+ .suggestion
3
+ .vote-box.down-append
4
+ .vote-frame
5
+ - votes = suggestion.votes.size
6
+ .vote-number{:class=>if(votes>9999)then "long" end }= votes
7
+ %span.votes-label
8
+ = pluralize(votes, 'vote')[votes.to_s.length+1,20]
9
+ - if user_signed_in?
10
+ - votes = suggestion.user_votes(current_user)
11
+ %div{:class=>"user-votes "+(if votes == 0 then "hidden" else '' end)}="+"+votes.to_s
12
+ = link_to 'Vote', vote_suggestion_path(suggestion.id), :class=>'vote-btn btn btn-success2 '+(if !user_signed_in? || !(current_user.votes_left>0 && current_user.can_vote?(suggestion)) then "disabled" else '' end),:remote => true
13
+ .suggestion-info
14
+ - if (!partial) && can?(:update, suggestion)
15
+ .pull-right= link_to 'edit', edit_suggestion_path(:id=>suggestion)
16
+ %h3.title= link_to_if partial, suggestion.title, suggestion
17
+ .description
18
+ - if partial then
19
+ = truncate suggestion.description, :length=>90, :separator => ' '
20
+ - else
21
+ = multiline suggestion.description
22
+ .name-date
23
+ Suggested by
24
+ %strong #{suggestion.user.name}
25
+ #{distance_of_time_in_words_to_now(suggestion.created_at)} ago
26
+ - if partial
27
+ .comments
28
+ = link_to pluralize(suggestion.comments.size, 'comment'),suggestion
29
+ - else
30
+ .status= if suggestion.status != :default then suggestion.status.to_s.humanize else suggestion.category.name end
31
+ .clearfix
@@ -0,0 +1,3 @@
1
+ - content_for :header do
2
+ Editing suggestion
3
+ = render 'form'
@@ -0,0 +1,27 @@
1
+ - if @show_search
2
+ = render 'search'
3
+ - if @show_nav_bar
4
+ - order_types={:newest => "Newest", :most_popular => "Most Popular", :in_progress => "In Progress", :complete => "Complete"}
5
+ %ul.nav.nav-tabs
6
+ - if @active_order_type
7
+ - order_types.each_pair do |key, value|
8
+ - class_str=(key==@active_order_type)? "active":""
9
+ %li{:class => class_str, :id => ""}
10
+ = link_to value, suggestions_listing_path(:order => key, :category => @active_category.name), :remote => false
11
+ = render "feature_box/shared/pages_nav"
12
+ #suggestions
13
+ - @suggestions.each do |suggestion|
14
+ = render :partial=>suggestion
15
+ - if @suggestions.empty?
16
+ .empty Nothing found
17
+ - if user_signed_in?
18
+ - if current_user.votes_left > 0
19
+ .new-btn
20
+ = link_to 'New Suggestion', new_suggestion_path, :class=>"btn btn-large"
21
+ - else
22
+ .center.alert.alert-info
23
+ = distance_of_time_in_words Time.now, current_user.can_vote_date
24
+ until you get another vote
25
+ - else
26
+ .center.alert.alert-info
27
+ = link_to "Sign in to add suggestions", devise_router_name.new_user_session_path
@@ -0,0 +1,6 @@
1
+ - if current_user.votes_left > 0
2
+ - content_for :header do
3
+ New suggestion
4
+ = render 'form'
5
+ - else
6
+ .empty You need at least one vote to add suggestions
@@ -0,0 +1,2 @@
1
+ = render @suggestion
2
+ = render :template=>'feature_box/comments/index'
@@ -0,0 +1,14 @@
1
+ - if @user.errors.any?
2
+ .alert.alert-error
3
+ %h4
4
+ = pluralize(@user.errors.count, "error")
5
+ prohibited this user from being saved:
6
+ %ul
7
+ - @user.errors.full_messages.each do |msg|
8
+ %li= msg
9
+ .well
10
+ = form_for(@user, :html =>{:class=>'form-horizontal '}) do |f|
11
+ %legend Editing user info
12
+ = generate_form_element f, :name, f.text_field(:name)
13
+ = generate_form_element f, :email, f.text_field(:email)
14
+ = generate_form_element f, nil, f.submit(:class=>"btn btn-primary")
@@ -0,0 +1,24 @@
1
+ .dd
2
+ %ul.nav.nav-tabs.table-nav
3
+ = render "feature_box/shared/pages_nav"
4
+ #categories
5
+ - if @users.empty?
6
+ %div.empty Nothing found
7
+ - else
8
+ %table.table.table-striped
9
+ %thead
10
+ %tr
11
+ %th
12
+ %th User name
13
+ %th Number of suggestions
14
+ %th
15
+ %th
16
+ %tbody
17
+ - n = @offset
18
+ - @users.each do |user|
19
+ %tr
20
+ %td= n+=1
21
+ %td= user.name
22
+ %td= user.suggestions.size
23
+ %td= link_to "edit", edit_user_path(user)
24
+ %td= link_to "delete", user, :confirm => 'Are you sure? This will delete ALL suggestions with user '+user.name, :method=>"delete", :class=>"link danger"
@@ -0,0 +1,81 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ %title FeatureBox
5
+ = stylesheet_link_tag "feature_box/application"
6
+ = javascript_include_tag "feature_box/application"
7
+ = csrf_meta_tag
8
+ %body
9
+ /div in the top right corner
10
+ #current-user-wrapper
11
+ #current-user.container
12
+ .row.pull-right
13
+ - if user_signed_in?
14
+ You signed in as
15
+ %strong= link_to current_user.name, devise_router_name.edit_user_registration_path
16
+ |
17
+ = link_to "Sign out", devise_router_name.destroy_user_session_path, {:method=>:delete}
18
+ - else
19
+ = link_to "Sign in", devise_router_name.new_user_session_path
20
+ /Header
21
+ %header.container
22
+ .row
23
+ .span3
24
+ %h1= link_to 'FeatureBox', feature_box.root_path, :class=>"black-link"
25
+ .span9
26
+ %h1
27
+ %small An excellent way to stay in touch with customers
28
+ /Middle part
29
+ .container
30
+ .row
31
+ /Navigations sidebar on the left
32
+ .span3
33
+ .sidebar-nav
34
+ %ul#category-nav.nav.nav-list
35
+ %li.nav-header Suggestions
36
+ - @categories.each do |category|
37
+ - class_str= if ( controller.controller_name == "suggestions" && category==@active_category) then "active" else "" end
38
+ %li{:class => class_str, :id => ""}
39
+ = link_to category.name, feature_box.suggestions_listing_path(:order => @active_order_type, :category => category.name ), :remote => false
40
+ - if user_signed_in?
41
+ %li.nav-header Your Impact
42
+ %li{:class=>if controller.controller_name == "suggestions" && controller.action_name == "my_suggestions" then "active" else "" end}= link_to "Suggestions", feature_box.my_suggestions_path
43
+ %li{:class=>if controller.controller_name == "suggestions" && controller.action_name == "my_votes" then "active" else "" end}= link_to "Votes", feature_box.my_votes_path
44
+ %li{:class=>if controller.controller_name == "suggestions" && controller.action_name == "my_comments" then "active" else "" end}= link_to "Comments", feature_box.my_comments_path
45
+ - if current_user.admin?
46
+ %li.nav-header Manage
47
+ %li{:class=>if controller.controller_name == "categories" then "active" else "" end}= link_to "Categories", feature_box.categories_path
48
+ %li{:class=>if controller.controller_name == "users" then "active" else "" end}= link_to "Users", feature_box.users_path
49
+ - if FeatureBox::Settings.total_limit >= 0 && current_user.votes_left > 0
50
+ .divider
51
+ #votes-left
52
+ You have
53
+ %span
54
+ = pluralize current_user.votes_left, "vote"
55
+ left
56
+ /Main content holder
57
+ .span9
58
+ /All flash messages and errors from devise goes here
59
+ - if flash[:notice] != nil
60
+ .alert.alert-success
61
+ = flash[:notice]
62
+ - if flash[:alert] != nil
63
+ .alert.alert-error
64
+ = flash[:alert]
65
+ - if flash[:error]
66
+ .alert.alert-error
67
+ = flash[:error]
68
+ - if devise_error_messages_any?
69
+ .alert.alert-error
70
+ = devise_error_messages!
71
+ /Yield
72
+ = yield
73
+ /Footer
74
+ %footer.container
75
+ .row
76
+ .span12
77
+ %p.pull-right
78
+ %a{:href => "#"} Back to top
79
+ %p
80
+ © 2012 FeatureBox by
81
+ %a{:href => "http://dfilimonov.com/"} Dmitry Filimonov
@@ -0,0 +1,3 @@
1
+ Devise.setup do |config|
2
+ require 'devise/orm/active_record'
3
+ end
@@ -0,0 +1,35 @@
1
+ FeatureBox::Engine.routes.draw do
2
+
3
+ root :to => "home#index"
4
+
5
+ match "/suggestions/(:category/(:order(/page/:page)))" => "suggestions#index", :as => :suggestions_listing
6
+ match "/suggestions/:id/page/:page" => "suggestions#show"
7
+
8
+ match "/my_suggestions" => "suggestions#my_suggestions", :as => :my_suggestions
9
+ match "/my_votes" => "suggestions#my_votes", :as => :my_votes
10
+ match "/my_comments" => "suggestions#my_comments", :as => :my_comments
11
+
12
+ resources :suggestions, :except => :index, :path=>'/suggestion' do
13
+ get 'vote', :on => :member
14
+ get 'search', :on => :collection, :as => :search
15
+ resources :comments, :only => [:create, :edit, :update, :destroy]
16
+ end
17
+
18
+ scope "/admin" do
19
+ resources :categories, :except => :show
20
+ resources :users, :only => [:index, :edit, :update, :destroy]
21
+ end
22
+
23
+ if FeatureBox::Settings.devise_router_name == :feature_box
24
+ devise_for :users, {
25
+ class_name: 'FeatureBox::User',
26
+ module: 'FeatureBox::Devise',
27
+ constollers: {
28
+ :sessions => 'feature_box/devise/sessions',
29
+ :registrations => 'feature_box/devise/registrations',
30
+ :passwords => 'feature_box/devise/passwords'
31
+ }
32
+ }
33
+ end
34
+
35
+ end
@@ -0,0 +1,11 @@
1
+ # This file should contain all the record creation needed to seed the database with its default values.
2
+ # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
3
+
4
+ u = FeatureBox::User.new
5
+ u.email = "admin@example.com"
6
+ u.name = "admin"
7
+ u.password="admin!"
8
+ u.password_confirmation="admin!"
9
+ u.admin = true
10
+ u.save
11
+
@@ -0,0 +1,72 @@
1
+ require 'feature_box/engine'
2
+ require 'feature_box/helpers'
3
+ require 'devise'
4
+ require 'cancan'
5
+ require 'cancan/ability'
6
+ require 'active_support/core_ext/object'
7
+ require 'haml'
8
+
9
+
10
+
11
+ module FeatureBox
12
+ module Settings
13
+
14
+ # Voting limits
15
+ mattr_accessor :per_suggestion_limit
16
+ @@per_suggestion_limit = 2
17
+
18
+ mattr_accessor :total_limit
19
+ @@total_limit = 8
20
+
21
+ mattr_accessor :time_limit
22
+ @@time_limit = 1.month
23
+
24
+ mattr_accessor :can_vote_own_suggestions
25
+ @@can_vote_own_suggestions = false
26
+
27
+
28
+
29
+ # Listing limits
30
+ mattr_accessor :max_suggestions_on_page
31
+ @@max_suggestions_on_page = 5
32
+
33
+ mattr_accessor :max_comments_on_page
34
+ @@max_comments_on_page = 10
35
+
36
+ # Admin pages listing limits
37
+ mattr_accessor :max_users_on_page
38
+ @@max_users_on_page = 15
39
+
40
+ mattr_accessor :max_categories_on_page
41
+ @@max_categories_on_page = 15
42
+
43
+
44
+
45
+ # Chars limits
46
+ mattr_accessor :max_suggestion_header_chars
47
+ @@max_suggestion_header_chars = 200
48
+
49
+ mattr_accessor :max_suggestion_description_chars
50
+ @@max_suggestion_description_chars = 1000
51
+
52
+ mattr_accessor :max_comment_chars
53
+ @@max_comment_chars = 1000
54
+
55
+ mattr_accessor :max_category_name_chars
56
+ @@max_category_name_chars = 50
57
+
58
+
59
+ mattr_accessor :devise_parent_model
60
+ @@devise_parent_model = "ActiveRecord::Base"
61
+
62
+ mattr_accessor :devise_router_name
63
+ @@devise_router_name = :feature_box
64
+
65
+ mattr_accessor :mailer
66
+ @@mailer = "Devise::Mailer"
67
+
68
+ def self.setup
69
+ yield self
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,5 @@
1
+ module FeatureBox
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace FeatureBox
4
+ end
5
+ end
@@ -0,0 +1,49 @@
1
+ module FeatureBox
2
+ module Helpers
3
+
4
+ def self.define_helpers
5
+
6
+ #We don't need these helpers if application is in standalone mode
7
+ return if FeatureBox::Settings.devise_router_name == :feature_box
8
+
9
+ model_name = FeatureBox::Settings.devise_parent_model.underscore
10
+ devise_router_name = FeatureBox::Settings.devise_router_name.to_s
11
+ #url helpers
12
+ mappings = Devise.mappings.values.map(&:used_helpers).flatten.uniq
13
+ routes = Devise::URL_HELPERS.slice(*mappings)
14
+ routes.each do |module_name, actions|
15
+ [:path, :url].each do |path_or_url|
16
+ actions.each do |action|
17
+ action = action ? "#{action}_" : ""
18
+ helper = "#{action}user_#{module_name}_#{path_or_url}"
19
+ real_helper = "#{action}#{model_name}_#{module_name}_#{path_or_url}"
20
+
21
+ class_eval <<-URL_HELPERS, __FILE__, __LINE__ + 1
22
+ def #{helper}
23
+ #{devise_router_name}.#{real_helper}
24
+ end
25
+ URL_HELPERS
26
+ end
27
+ end
28
+ end
29
+
30
+ #We don't need these helpers if user model's name is "User"
31
+ return if model_name == 'user'
32
+
33
+ helpers=[:current_user, :user_session, :user_signed_in?, :authenticate_user!]
34
+ helpers.each do |helper|
35
+ helper = helper.to_s
36
+ real_helper = helper.gsub(/user/,model_name)
37
+ class_eval <<-URL_HELPERS
38
+ def #{helper} #{if helper == 'authenticate_user!' then '(opts={})' end}
39
+ #{real_helper} #{if helper == 'authenticate_user!' then 'opts' end}
40
+ end
41
+ URL_HELPERS
42
+ end
43
+
44
+ end
45
+ def self.included m
46
+ self.define_helpers
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,3 @@
1
+ module FeatureBox
2
+ VERSION = "0.8.1"
3
+ end
@@ -0,0 +1,26 @@
1
+ require 'generators/feature_box/generator_base'
2
+ module FeatureBox
3
+ module Generators
4
+ class ExistingGenerator < Rails::Generators::NamedBase
5
+ include GeneratorBase
6
+ desc "Installs FeatureBox to existing application"
7
+ def feature_box_install
8
+ #name of the User model
9
+ @model_name = file_name || "User"
10
+ @model_name = @model_name.camelize
11
+ #variable for templates
12
+ @has_devise = true
13
+
14
+ #migrate
15
+ copy_migrations [/00_.*/,/01_.*/,/02_.*/,/03_.*/,/06_.*/]
16
+ rake "db:migrate"
17
+
18
+ #route
19
+ route "mount FeatureBox::Engine => '/feature_box'"
20
+
21
+ #initializer
22
+ template "initializers/initializer.rb", "config/initializers/feature_box.rb"
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,47 @@
1
+ require 'find'
2
+ module FeatureBox
3
+ module Generators
4
+ # Helper methods
5
+ module GeneratorBase
6
+
7
+ include Rails::Generators::Migration
8
+
9
+ module ClassMethods
10
+ def next_migration_number(path)
11
+ unless @prev_migration_nr
12
+ @prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
13
+ else
14
+ @prev_migration_nr += 1
15
+ end
16
+ @prev_migration_nr.to_s
17
+ end
18
+ end
19
+
20
+ def self.included clazz
21
+ clazz.source_root File.expand_path("../templates", __FILE__)
22
+ clazz.extend include Rails::Generators::Migration::ClassMethods
23
+ clazz.extend ClassMethods
24
+ end
25
+
26
+ def copy_migrations patterns
27
+ model_name = @model_name || "User"
28
+ Find.find(File.expand_path("../templates/migrations", __FILE__)) do |path|
29
+ patterns.each do |pattern|
30
+ if pattern.match(path)
31
+ migration_template path, 'db/migrate/'+(File.basename(path,".rb"))[3..-1].gsub(/{model_name}/,model_name.tableize.gsub(/\//,''))
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ def trim str
38
+ (str.gsub /^[\s]*([^\s])/m, '\1')
39
+ end
40
+
41
+ def trim_f str
42
+ (str.gsub /^[\s]*\|/m, '')
43
+ end
44
+
45
+ end
46
+ end
47
+ end