bootstrap_builders 0.0.3 → 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.
- checksums.yaml +4 -4
- data/{LICENSE.txt → MIT-LICENSE} +1 -1
- data/README.md +52 -8
- data/Rakefile +17 -44
- data/app/assets/javascripts/bootstrap_builders/application.js +13 -0
- data/app/assets/stylesheets/bootstrap_builders/application.css +15 -0
- data/app/controllers/bootstrap_builders/application_controller.rb +2 -0
- data/app/helpers/bootstrap_builders/application_helper.rb +104 -0
- data/app/views/layouts/bootstrap_builders/application.html.erb +14 -0
- data/config/routes.rb +2 -0
- data/config/spring.rb +1 -0
- data/lib/bootstrap_builders.rb +15 -5
- data/lib/bootstrap_builders/attribute_rows.rb +95 -0
- data/lib/bootstrap_builders/button.rb +90 -22
- data/lib/bootstrap_builders/class_attribute_handler.rb +20 -0
- data/lib/bootstrap_builders/configuration.rb +7 -0
- data/lib/bootstrap_builders/engine.rb +3 -0
- data/lib/bootstrap_builders/is_a_checker.rb +14 -0
- data/lib/bootstrap_builders/panel.rb +88 -0
- data/lib/bootstrap_builders/table.rb +44 -0
- data/lib/bootstrap_builders/version.rb +3 -0
- data/lib/tasks/bootstrap_builders_tasks.rake +4 -0
- metadata +158 -44
- data/.document +0 -5
- data/.rspec +0 -1
- data/.rubocop.yml +0 -60
- data/Gemfile +0 -14
- data/Gemfile.lock +0 -99
- data/VERSION +0 -1
- data/bootstrap_builders.gemspec +0 -76
- data/lib/bootstrap_builders/application_helpers.rb +0 -55
- data/lib/bootstrap_builders/box.rb +0 -66
- data/spec/bootstrap_helpers/box_spec.rb +0 -17
- data/spec/bootstrap_helpers/button_spec.rb +0 -12
- data/spec/spec_helper.rb +0 -12
- data/spec/support/working_helpers.rb +0 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c2e43bdc56f44def9fdde24067ba74e9496dd833
|
4
|
+
data.tar.gz: fec8d583324e41c4728d2ceb50f36e9567fd0076
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0f19384fe95607c4d333ae2cf2fab73f4b2db0adf4a698b3bb1c7e792bc7130a8c3b8a1b69f27b474b90009d4df8954f7f5fe4ecf865d309e0ce0661c8b95eec
|
7
|
+
data.tar.gz: bc903302b6ca80d51f885dd512a8a08a738bc6c7e52aad5c217a544ce7d865b61a80ed95c36e58b535453c6a038f5ba3aaad8103eca77e77fae64ec09ac43203
|
data/{LICENSE.txt → MIT-LICENSE}
RENAMED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# BootstrapBuilders
|
2
2
|
|
3
3
|
## Install
|
4
4
|
|
@@ -10,24 +10,69 @@ gem "bootstrap_builders"
|
|
10
10
|
Then add to your `ApplicationHelper` module:
|
11
11
|
```ruby
|
12
12
|
module ApplicationHelper
|
13
|
-
include BootstrapBuilders::
|
13
|
+
include BootstrapBuilders::ApplicationHelper
|
14
14
|
end
|
15
15
|
```
|
16
16
|
|
17
17
|
## Usage
|
18
18
|
|
19
|
-
###
|
19
|
+
### Panel
|
20
|
+
|
21
|
+
1. Panel in all its glory with elements and classes
|
22
|
+
2. Controls if `:right` argument is given
|
23
|
+
3. Table if `:table` argument is given
|
24
|
+
|
20
25
|
```haml
|
21
|
-
=
|
22
|
-
Content of
|
26
|
+
= bb_panel "Title of panel", right: button_content do
|
27
|
+
Content of panel
|
23
28
|
```
|
24
29
|
|
25
|
-
###
|
30
|
+
### Panel with a table
|
31
|
+
|
26
32
|
```haml
|
27
|
-
=
|
33
|
+
= bb_panel "Title of panel", table: true do
|
28
34
|
%tbody
|
29
35
|
%tr
|
30
36
|
%td= "Test"
|
37
|
+
```
|
38
|
+
|
39
|
+
You can add custom classes like this:
|
40
|
+
```haml
|
41
|
+
= bb_panel "Title of panel", table: {bs_classes: [:striped]} do
|
42
|
+
%tbody
|
43
|
+
%tr
|
44
|
+
%td Test
|
45
|
+
```
|
46
|
+
|
47
|
+
### Table
|
48
|
+
|
49
|
+
1. Adds Bootstrap classes: "table", "table-hover", "table-striped"
|
50
|
+
|
51
|
+
```haml
|
52
|
+
= bb_table do
|
53
|
+
%tbody
|
54
|
+
%tr
|
55
|
+
%td= "Test"
|
56
|
+
```
|
57
|
+
|
58
|
+
You can change the default classes like this:
|
59
|
+
```ruby
|
60
|
+
BootstrapBuilders.configuration.default_table_classes = [:striped, :hover]
|
61
|
+
```
|
62
|
+
|
63
|
+
The classes "bb-table" and "table" are always added.
|
64
|
+
|
65
|
+
### Buttons
|
66
|
+
|
67
|
+
1. Adds icons automatically
|
68
|
+
2. Adds labels automatically
|
69
|
+
3. Doesn't show button if CanCan doesn't allow it
|
70
|
+
|
71
|
+
```haml
|
72
|
+
= bb_new_btn url: [:admin, User]
|
73
|
+
= bb_edit_btn url: [:admin, user], mini: true
|
74
|
+
= bb_destroy_btn url: [:admin, user], label: false
|
75
|
+
```
|
31
76
|
|
32
77
|
## Contributing to bootstrap_builders
|
33
78
|
|
@@ -43,4 +88,3 @@ end
|
|
43
88
|
|
44
89
|
Copyright (c) 2016 kaspernj. See LICENSE.txt for
|
45
90
|
further details.
|
46
|
-
|
data/Rakefile
CHANGED
@@ -1,53 +1,26 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require "rubygems"
|
4
|
-
require "bundler"
|
5
1
|
begin
|
6
|
-
|
7
|
-
rescue
|
8
|
-
|
9
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
-
exit e.status_code
|
11
|
-
end
|
12
|
-
require "rake"
|
13
|
-
|
14
|
-
require "jeweler"
|
15
|
-
Jeweler::Tasks.new do |gem|
|
16
|
-
# gem is a Gem::Specification... see http://guides.rubygems.org/specification-reference/ for more options
|
17
|
-
gem.name = "bootstrap_builders"
|
18
|
-
gem.homepage = "http://github.com/kaspernj/bootstrap_builders"
|
19
|
-
gem.license = "MIT"
|
20
|
-
gem.summary = %(A library to generate Bootstrap HTML for Rails.)
|
21
|
-
gem.description = %(A library to generate Bootstrap HTML for Rails.)
|
22
|
-
gem.email = "k@spernj.org"
|
23
|
-
gem.authors = ["kaspernj"]
|
24
|
-
# dependencies defined in Gemfile
|
2
|
+
require "bundler/setup"
|
3
|
+
rescue LoadError
|
4
|
+
puts "You must `gem install bundler` and `bundle install` to run rake tasks"
|
25
5
|
end
|
26
|
-
Jeweler::RubygemsDotOrgTasks.new
|
27
|
-
|
28
|
-
require "rspec/core"
|
29
|
-
require "rspec/core/rake_task"
|
30
|
-
RSpec::Core::RakeTask.new(:spec) do |spec|
|
31
|
-
spec.pattern = FileList["spec/**/*_spec.rb"]
|
32
|
-
end
|
33
|
-
|
34
|
-
desc "Code coverage detail"
|
35
|
-
task :simplecov do
|
36
|
-
ENV["COVERAGE"] = "true"
|
37
|
-
Rake::Task["spec"].execute
|
38
|
-
end
|
39
|
-
|
40
|
-
task default: :spec
|
41
6
|
|
42
7
|
require "rdoc/task"
|
43
|
-
Rake::RDocTask.new do |rdoc|
|
44
|
-
version = File.exist?("VERSION") ? File.read("VERSION") : ""
|
45
8
|
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
46
10
|
rdoc.rdoc_dir = "rdoc"
|
47
|
-
rdoc.title
|
48
|
-
rdoc.
|
11
|
+
rdoc.title = "BootstrapBuilders"
|
12
|
+
rdoc.options << "--line-numbers"
|
13
|
+
rdoc.rdoc_files.include("README.rdoc")
|
49
14
|
rdoc.rdoc_files.include("lib/**/*.rb")
|
50
15
|
end
|
51
16
|
|
52
|
-
|
53
|
-
|
17
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
18
|
+
load "rails/tasks/engine.rake"
|
19
|
+
load "rails/tasks/statistics.rake"
|
20
|
+
|
21
|
+
Bundler::GemHelper.install_tasks
|
22
|
+
|
23
|
+
if Rails.env.development? || Rails.env.test?
|
24
|
+
require "best_practice_project"
|
25
|
+
BestPracticeProject.load_tasks
|
26
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
+
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// compiled file.
|
9
|
+
//
|
10
|
+
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
|
11
|
+
// about supported directives.
|
12
|
+
//
|
13
|
+
//= require_tree .
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any styles
|
10
|
+
* defined in the other CSS/SCSS files in this directory. It is generally better to create a new
|
11
|
+
* file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module BootstrapBuilders::ApplicationHelper
|
2
|
+
def bb_attribute_rows(model, attributes)
|
3
|
+
BootstrapBuilders::AttributeRows.new(model: model, attributes: attributes, context: self).html
|
4
|
+
end
|
5
|
+
|
6
|
+
def bb_panel(*opts, &blk)
|
7
|
+
title = opts.shift unless opts.first.is_a?(Hash)
|
8
|
+
width = opts.shift unless opts.first.is_a?(Hash)
|
9
|
+
|
10
|
+
if opts.length == 1 && opts.first.is_a?(Hash)
|
11
|
+
args = opts.first
|
12
|
+
title = args.fetch(:title) if args.key?(:title)
|
13
|
+
width = args[:width] if args.key?(:width)
|
14
|
+
right = args[:right] if args.key?(:right)
|
15
|
+
else
|
16
|
+
args = {}
|
17
|
+
end
|
18
|
+
|
19
|
+
BootstrapBuilders::Panel.new(args.merge(title: title, width: width, right: right, block: blk, context: self)).html
|
20
|
+
end
|
21
|
+
|
22
|
+
def bb_btn(*args)
|
23
|
+
args = BootstrapBuilders::Button.parse_url_args(args)
|
24
|
+
args[:context] = self
|
25
|
+
button = BootstrapBuilders::Button.new(args)
|
26
|
+
button.classes.add("bb-btn")
|
27
|
+
button.html
|
28
|
+
end
|
29
|
+
|
30
|
+
def bb_edit_btn(*args)
|
31
|
+
args = BootstrapBuilders::Button.parse_url_args(args)
|
32
|
+
args[:label] = t("edit") unless args.key?(:label)
|
33
|
+
args[:title] ||= t("edit") if args[:mini]
|
34
|
+
args[:url] = [:edit, args.fetch(:url)] if args[:url] && !args[:url].is_a?(Array) && BootstrapBuilders::IsAChecker.is_a?(args[:url], "ActiveRecord::Base")
|
35
|
+
|
36
|
+
button = BootstrapBuilders::Button.new(args.merge(icon: "wrench", context: self, can_type: :edit))
|
37
|
+
button.classes.add(["bb-btn", "bb-btn-edit"])
|
38
|
+
button.classes.add("bb-btn-edit-#{button.can_model_class.name.tableize.singularize}") if button.can_model_class
|
39
|
+
button.classes.add("bb-btn-edit-#{button.can_model_class.name.tableize.singularize}-#{button.can_model.id}") if button.can_model
|
40
|
+
button.html
|
41
|
+
end
|
42
|
+
|
43
|
+
def bb_destroy_btn(*args)
|
44
|
+
args = BootstrapBuilders::Button.parse_url_args(args)
|
45
|
+
args[:label] = t("delete") unless args.key?(:label)
|
46
|
+
args[:title] ||= t("delete") if args[:mini]
|
47
|
+
|
48
|
+
args[:data] ||= {}
|
49
|
+
args[:data][:confirm] ||= t("are_you_sure")
|
50
|
+
|
51
|
+
button = BootstrapBuilders::Button.new(args.merge(icon: "remove", context: self, can_type: :destroy, method: :delete))
|
52
|
+
button.classes.add(["btn-danger", "bb-btn", "bb-btn-destroy"])
|
53
|
+
button.classes.add("bb-btn-destroy-#{button.can_model_class.name.tableize.singularize}") if button.can_model_class
|
54
|
+
button.classes.add("bb-btn-destroy-#{button.can_model_class.name.tableize.singularize}-#{button.can_model.id}") if button.can_model
|
55
|
+
button.html
|
56
|
+
end
|
57
|
+
|
58
|
+
def bb_new_btn(*args)
|
59
|
+
args = BootstrapBuilders::Button.parse_url_args(args)
|
60
|
+
args[:label] = t("add_new") unless args.key?(:label)
|
61
|
+
args[:title] ||= t("new") if args[:mini]
|
62
|
+
|
63
|
+
button = BootstrapBuilders::Button.new(args.merge(icon: "pencil", context: self, can_type: :new))
|
64
|
+
button.classes.add(["bb-btn", "bb-btn-new"])
|
65
|
+
button.classes.add("bb-btn-new-#{button.can_model_class.name.tableize.singularize}") if button.can_model_class
|
66
|
+
button.html
|
67
|
+
end
|
68
|
+
|
69
|
+
def bb_index_btn(*args)
|
70
|
+
args = BootstrapBuilders::Button.parse_url_args(args)
|
71
|
+
args[:title] ||= t("index") if args[:mini]
|
72
|
+
|
73
|
+
button = BootstrapBuilders::Button.new(args.merge(icon: "table", context: self, can_type: :index))
|
74
|
+
|
75
|
+
if button.label.to_s.strip.empty?
|
76
|
+
if button.can_model_class
|
77
|
+
button.label = button.can_model_class.model_name.human(count: 2)
|
78
|
+
else
|
79
|
+
button.label = t("index")
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
button.classes.add(["bb-btn", "bb-btn-index"])
|
84
|
+
button.classes.add("bb-btn-index-#{button.can_model_class.name.tableize}") if button.can_model_class
|
85
|
+
button.html
|
86
|
+
end
|
87
|
+
|
88
|
+
def bb_show_btn(*args)
|
89
|
+
args = BootstrapBuilders::Button.parse_url_args(args)
|
90
|
+
args[:label] = t("show") unless args.key?(:label)
|
91
|
+
args[:title] ||= t("show") if args[:mini]
|
92
|
+
|
93
|
+
button = BootstrapBuilders::Button.new(args.merge(icon: "square-o", context: self, can_type: :show))
|
94
|
+
button.classes.add(["bb-btn", "bb-btn-show"])
|
95
|
+
button.classes.add("bb-btn-show-#{button.can_model_class.name.tableize.singularize}") if button.can_model_class
|
96
|
+
button.classes.add("bb-btn-show-#{button.can_model_class.name.tableize.singularize}-#{button.can_model.id}") if button.can_model
|
97
|
+
button.html
|
98
|
+
end
|
99
|
+
|
100
|
+
def bb_table(args = {}, &blk)
|
101
|
+
table = BootstrapBuilders::Table.new(args.merge(context: self, blk: blk))
|
102
|
+
table.html
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>BootstrapBuilders</title>
|
5
|
+
<%= stylesheet_link_tag "bootstrap_builders/application", media: "all" %>
|
6
|
+
<%= javascript_include_tag "bootstrap_builders/application" %>
|
7
|
+
<%= csrf_meta_tags %>
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
|
11
|
+
<%= yield %>
|
12
|
+
|
13
|
+
</body>
|
14
|
+
</html>
|
data/config/routes.rb
ADDED
data/config/spring.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Spring.application_root = "./spec/dummy"
|
data/lib/bootstrap_builders.rb
CHANGED
@@ -1,9 +1,19 @@
|
|
1
|
+
require "bootstrap_builders/engine"
|
2
|
+
require "haml"
|
1
3
|
require "html_gen"
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
+
module BootstrapBuilders
|
6
|
+
extend ActiveSupport::Autoload
|
5
7
|
|
6
|
-
autoload :
|
7
|
-
autoload :
|
8
|
-
autoload :
|
8
|
+
autoload :AttributeRows
|
9
|
+
autoload :Button
|
10
|
+
autoload :ClassAttributeHandler
|
11
|
+
autoload :Configuration
|
12
|
+
autoload :IsAChecker
|
13
|
+
autoload :Panel
|
14
|
+
autoload :Table
|
15
|
+
|
16
|
+
def self.configuration
|
17
|
+
@configuration ||= BootstrapBuilders::Configuration.new
|
18
|
+
end
|
9
19
|
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
class BootstrapBuilders::AttributeRows
|
2
|
+
def initialize(args)
|
3
|
+
@model = args.fetch(:model)
|
4
|
+
@attributes = args.fetch(:attributes)
|
5
|
+
@context = args.fetch(:context)
|
6
|
+
end
|
7
|
+
|
8
|
+
def html
|
9
|
+
elements = []
|
10
|
+
|
11
|
+
@attributes.each do |attribute|
|
12
|
+
tr = HtmlGen::Element.new(:tr, inden: " ", classes: ["bb-attributes-row", "bb-attributes-row-#{attribute}"])
|
13
|
+
tr.add_ele(:th, classes: ["bb-attributes-row-title"], str: @model.class.human_attribute_name(attribute))
|
14
|
+
|
15
|
+
if column_type(attribute) == :boolean
|
16
|
+
str = @model.__send__("#{attribute}?") ? @context.t("yes") : @context.t("no")
|
17
|
+
elsif column_type(attribute) == :model
|
18
|
+
model_value = column_value(attribute)
|
19
|
+
|
20
|
+
unless model_value.nil?
|
21
|
+
link_method_name = "link_to_#{StringCases.camel_to_snake(model_value.class.name)}"
|
22
|
+
|
23
|
+
if @view.respond_to?(:link_to_model)
|
24
|
+
str = @view.link_to_model(model_value)
|
25
|
+
elsif @context.respond_to?(link_method_name)
|
26
|
+
str_html = @context.__send__(link_method_name, model_value)
|
27
|
+
else
|
28
|
+
str = model_value.name
|
29
|
+
end
|
30
|
+
end
|
31
|
+
elsif column_type(attribute) == :datetime || column_type(attribute) == :date
|
32
|
+
str = @context.l(column_value(attribute), format: :long) if column_value(attribute)
|
33
|
+
elsif column_type(attribute) == :money
|
34
|
+
str = @context.number_to_currency(column_value(attribute), unit: "")
|
35
|
+
else
|
36
|
+
str = column_value(attribute).to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
if str
|
40
|
+
tr.add_ele(:td, classes: ["bb-attributes-row-value"], str: str)
|
41
|
+
else
|
42
|
+
tr.add_ele(:td, classes: ["bb-attributes-row-value"], str_html: str_html)
|
43
|
+
end
|
44
|
+
|
45
|
+
elements << tr.html
|
46
|
+
end
|
47
|
+
|
48
|
+
html = elements.join("\n")
|
49
|
+
html = html.html_safe if html.respond_to?(:html_safe)
|
50
|
+
html
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def column_type(column)
|
56
|
+
return :state if column == :state && @model.class.respond_to?(:state_machine)
|
57
|
+
|
58
|
+
type = @model.class.columns_hash[column.to_s].try(:type)
|
59
|
+
return type if type
|
60
|
+
|
61
|
+
reflection = @model.class.reflections[column]
|
62
|
+
return :model if reflection && reflection.is_a?(ActiveRecord::Reflection::AssociationReflection)
|
63
|
+
|
64
|
+
return :money if @model.class.respond_to?(:monetized_attributes) && @model.class.monetized_attributes.key?(column)
|
65
|
+
|
66
|
+
value = column_value(column)
|
67
|
+
return :model if value.is_a?(ActiveRecord::Base)
|
68
|
+
|
69
|
+
reflection_association = @model.class.reflect_on_association(column)
|
70
|
+
return :model if reflection_association
|
71
|
+
|
72
|
+
return :method if @model.respond_to?(column)
|
73
|
+
|
74
|
+
raise "Couldn't find out type for column '#{column}' on class '#{@model.class.name}'."
|
75
|
+
end
|
76
|
+
|
77
|
+
def column_value(column)
|
78
|
+
translated_column_method = "#{column}_translated"
|
79
|
+
translated_column_method_end = "translated_#{column}"
|
80
|
+
translated_option_helper_method = "#{@model.class.name.underscore}_translated_#{column}"
|
81
|
+
translated_state_method_name = "#{@model.class.name.underscore}_translated_state"
|
82
|
+
|
83
|
+
if column == :state && @model.class.respond_to?(:state_machine) && @view.respond_to?(translated_state_method_name)
|
84
|
+
return @view.__send__(translated_state_method_name, @model)
|
85
|
+
elsif @view.respond_to?(translated_option_helper_method)
|
86
|
+
return @view.__send__(translated_option_helper_method, @model)
|
87
|
+
elsif @model.respond_to?(translated_column_method)
|
88
|
+
return @model.__send__(translated_column_method)
|
89
|
+
elsif @model.respond_to?(translated_column_method_end)
|
90
|
+
return @model.__send__(translated_column_method_end)
|
91
|
+
end
|
92
|
+
|
93
|
+
@model.__send__(column)
|
94
|
+
end
|
95
|
+
end
|