coolstrap-generator 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -34,7 +34,7 @@ module Coolstrap::Generator
34
34
  end
35
35
 
36
36
  map %w(s) => 'scaffold'
37
- desc "scaffold <list/complexlist/tabbar/toolbar> <domain> <name>", "generate a scaffold for Coolstrap elements."
37
+ desc "scaffold <list/complexlist/tabbar/toolbar/dialog> <domain> <name>", "generate a scaffold for Coolstrap elements."
38
38
  def scaffold(cs_type, domain, name)
39
39
  ::Coolstrap::Generator::Generate::View.create(name, {
40
40
  :domain => domain,
@@ -60,12 +60,17 @@ module Coolstrap::Generator
60
60
  end
61
61
 
62
62
  map %w(b) => 'build'
63
- system "pwd"
64
63
  desc "build ", "builds middleman app"
65
64
  def build
66
65
  system "echo ::== COOLSTRAP BUILD =="
67
66
  system "middleman build"
68
67
  end
69
68
 
69
+ #map %w(d) => 'doc'
70
+ #desc "doc", "Shows readme file"
71
+ #def doc
72
+ # system "echo see repo"
73
+ # #system "cat ./readme.md"
74
+ #end
70
75
  end
71
76
  end
@@ -16,21 +16,25 @@ module Coolstrap::Generator
16
16
  #log "#{context.inspect}"
17
17
  case context[:cs_type]
18
18
  when 'list'
19
- log("HINT! to use lists you should call them with href '##{name}' & data-target = 'section', and add the partial in index.html.haml ")
19
+ log("HINT: to use lists call them with href '##{name}' & data-target = 'section', and add the partial in index.html.haml ")
20
20
  template = templates("app/components/listview/_simplelist.html.haml.erb")
21
21
  when 'complexlist'
22
- log("HINT! to use lists you should call them with href '##{name}' & data-target = 'section', and add the partial in index.html.haml ")
22
+ log("HINT: to use lists call them with href '##{name}' & data-target = 'section', and add the partial in index.html.haml ")
23
23
  template = templates("app/components/listview/_complexlistavatar.html.haml.erb")
24
24
  when 'tabbar'
25
25
  view_directory = "source/views/tabbars"
26
- log("HINT! tabbar partial generated, you could put partial in some header or footer element' ")
26
+ log("HINT: put partial in some header or footer element' ")
27
27
  template = templates("app/components/tabbar.html.haml.erb")
28
28
  when 'toolbar'
29
29
  view_directory = "source/views/toolbars"
30
- log("HINT! toolbar partial generated!, you could put partial in some header or footer element' ")
30
+ log("HINT: put partial in some header or footer element' ")
31
31
  template = templates("app/components/toolbar.html.haml.erb")
32
+ when 'dialog'
33
+ view_directory = "source/views/dialogs"
34
+ log("HINT: put partial in index.html.haml, see comments' ")
35
+ template = templates("app/components/dialog.html.haml.erb")
32
36
  else
33
- log("HINT! to use lists you should call them with href '##{name}' & data-target = 'section', and add the partial in index.html.haml ")
37
+ log("HINT: to use lists call them with href '##{name}' & data-target = 'section', and add the partial in index.html.haml ")
34
38
  template = templates("app/components/listview/_complexlistavatar.html.haml.erb")
35
39
  end
36
40
 
@@ -129,10 +129,25 @@ module Middleman::Features::Helpers
129
129
  end
130
130
  end
131
131
 
132
+ def dialog(opts, &block)
133
+ options = {:role => "dialog", :data=>{:type=>opts[:type] || "modal", :transition=>opts[:transition] || "slideup"}}
134
+ opts = opts.merge(options)
135
+ if block_given?
136
+ content_tag(:div, opts) do
137
+ capture(&block)
138
+ end
139
+ else
140
+ end
141
+ end
142
+
132
143
  def render_tabbar(tabbar)
133
144
  partial("views/tabbars/#{tabbar}")
134
145
  end
135
146
 
147
+ def render_dialog(dialog)
148
+ partial("views/dialogs/#{tabbar}")
149
+ end
150
+
136
151
  def render_toolbar(tabbar)
137
152
  partial("views/toolbars/#{tabbar}")
138
153
  end
@@ -0,0 +1,34 @@
1
+ -# more on dialogs soon:
2
+
3
+ --# more on dialogs at http://...
4
+ -# usage partial = partial "views/dialogs/<%= name %>"
5
+
6
+ -# modal example
7
+ = dialog(:id=>"mymodal") do
8
+ = link_to "#mymodal", "data-target" => "close" do
9
+ = icon :"remove-circle"
10
+ %h1 Cras mattis consectetur purus sit amet fermentumm agnis dis parturient mo.
11
+
12
+
13
+ -# alert example
14
+ = dialog(:id=>"myalert", :type=>"alert" ) do
15
+ %h1 Cras mattis consectetur purus agnis dis parturient mo.
16
+ %p Donec id elit non mi porta gravida at eget metus estibulum id ligula porta felis euismod semper.
17
+ .button-group
18
+ %a Ullamcorper
19
+ = link_to "Close", "#myalert", {"data-target" => "close"}, :class=>"close"
20
+
21
+ -# action example
22
+ = dialog(:id=>"myaction", :type=>"action" ) do
23
+ %h1 Cras mattis consectetur purus sit amet fermentumm agnis dis parturient mo.
24
+ .button-group
25
+ %a Ullamcorper
26
+ %a Tristique
27
+ %p Cras mattis consectetur purus sit amet fermentumm agnis dis parturient mo.
28
+ .button-group.alignVertical
29
+ %a Ullamcorper Ridiculus
30
+ %a Tristique Lorem
31
+ = link_to ""
32
+ = link_to "Close", "#myaction", {"data-target" => "close"}, :class=>"close"
33
+
34
+
@@ -10,12 +10,15 @@
10
10
 
11
11
  = partial "views/home"
12
12
  -# put collection partials here
13
- -# = partial "views/users/repos"
13
+ -# = partial "views/users/collection"
14
14
 
15
15
  = partial "views/shared/aside_onleft"
16
16
  = partial "views/shared/aside_onright"
17
17
  = partial "views/shared/aside_ontop"
18
18
  = partial "views/shared/aside_onbottom"
19
19
 
20
+ -# put dialogs here
21
+ -# = render_dialog("/users/alert")
22
+
20
23
  = content_for :application_js do
21
24
  = javascript_include_tag "app.js"
@@ -22,8 +22,8 @@
22
22
  %i.icon-edit
23
23
 
24
24
  = article( { :id => 'first-page', :class => 'scrollable' }) do
25
- %ul#mail{"data-type" => "listview"}
26
- %li
25
+ = list_view(:id=>"someid") do
26
+ = list_item do
27
27
  = link_to "#collection" , "data-target" => "section" do
28
28
  .content
29
29
  .title Example Link - run "coolstrap s list [Domain] [collection]"
@@ -11,7 +11,8 @@
11
11
  .content
12
12
  %h1 Don Francisco
13
13
 
14
- %li.list-divider Favorites
14
+ = divider do
15
+ Favorites
15
16
 
16
17
  %li
17
18
  .aside
@@ -1,66 +1,10 @@
1
1
  %aside.onRight#aside-right
2
2
  %header
3
- %h1 Dialogs
3
+ %h1 On Right
4
4
 
5
- %section{ :class => 'scrollable' }
6
- %ul{"data-type" => "listview"}
5
+ = section(:class=>'scrollable') do
6
+ = list_view do
7
7
  %li
8
8
  %a{"href" => "#mymodal", "data-target" => "dialog"}
9
9
  .content Open dialog type [modal]
10
- %i.icon-play-circle
11
- %li
12
- %a{"href" => "#myalert", "data-target" => "dialog"}
13
- .content Open dialog type [alert]
14
- %i.icon-play-circle
15
- %li
16
- %a{"href" => "#myaction", "data-target" => "dialog"}
17
- .content Open dialog type [action]
18
- %i.icon-play-circle
19
- %li
20
- %a{"href" => "#myaction2", "data-target" => "dialog"}
21
- .content Open another dialog type [action]
22
- %i.icon-play-circle
23
- %li
24
- %a{"href" => "#myaction3", "data-target" => "dialog"}
25
- .content even more, open dialog type [action]
26
- %i.icon-play-circle
27
-
28
-
29
- %div#mymodal{:role => "dialog", "data-type" => "modal", "data-transition" => "slideup"}
30
- %a.close{"href" => "#mymodal", "data-target" => "close"}
31
- %i.icon-remove-circle
32
- %h1 Cras mattis consectetur purus sit amet fermentumm agnis dis parturient mo.
33
-
34
- %div#myalert{:role => "dialog", "data-type" => "alert"}
35
- %h1 Cras mattis consectetur purus agnis dis parturient mo.
36
- %p Donec id elit non mi porta gravida at eget metus estibulum id ligula porta felis euismod semper.
37
- .button-group
38
- %a Ullamcorper
39
- %a.close{"href" => "#myalert", "data-target" => "close"}
40
- Close
41
-
42
- %div#myaction{:role => "dialog", "data-type" => "action"}
43
- %h1 Cras mattis consectetur purus sit amet fermentumm agnis dis parturient mo.
44
- .button-group
45
- %a Ullamcorper Ridiculus
46
- %a.close{"href" => "#myaction", "data-target" => "close"}
47
- Close
48
-
49
- %div#myaction2{:role => "dialog", "data-type" => "action"}
50
- %h1 Cras mattis consectetur purus sit amet fermentumm agnis dis parturient mo.
51
- %a Ullamcorper Ridiculus
52
- %a.close{"href" => "#myaction2", "data-target" => "close"}
53
- Close
54
-
55
- %div#myaction3{:role => "dialog", "data-type" => "action"}
56
- %h1 Cras mattis consectetur purus sit amet fermentumm agnis dis parturient mo.
57
- .button-group
58
- %a Ullamcorper
59
- %a Tristique
60
- %p Cras mattis consectetur purus sit amet fermentumm agnis dis parturient mo.
61
- .button-group.alignVertical
62
- %a Ullamcorper Ridiculus
63
- %a Tristique Lorem
64
- %a.close{"href" => "#myaction3", "data-target" => "close"}
65
- Close
66
-
10
+ %i.icon-play-circle
@@ -1,5 +1,5 @@
1
1
  module Coolstrap
2
2
  module Generator
3
- VERSION = "0.1.2"
3
+ VERSION = "0.1.3"
4
4
  end
5
5
  end
data/readme.md CHANGED
@@ -1,10 +1,13 @@
1
1
  # CoolsTrap Generator
2
2
 
3
- ### An app generator for rapid Html5 mobile development with coolstrap framework.
3
+ ### An app generator for rapid HTML5 mobile development with [Coolstrap](https://github.com/rhyboo/coolstrap) framework.
4
4
 
5
5
  ## DISCLAIMER:
6
6
 
7
- Coolstrap is in alpha development phase, so the project should be treated like that until the coolstrap team generates the stable version of the framework.
7
+ [Coolstrap](https://github.com/rhyboo/coolstrap) is in alpha development phase, so the project should be treated like that until coolstrap team generates a stable version of the framework.
8
+
9
+ so... coolstrap-generator is in early development too...
10
+
8
11
 
9
12
  ## Requirements
10
13
 
@@ -56,21 +59,21 @@
56
59
  ## Convenience Helpers
57
60
 
58
61
  Coolstrap Generator comes with some convenience helpers methods for header, footer, sections, list_view and more.
59
- see: coolstrap-generator/templates/.
62
+ see: lib/coolstrap-generator/templates/. to see more examples.
60
63
 
61
- ### some examples
62
-
64
+ ### Some examples
65
+ ### Header
63
66
  = header do
64
67
  = toolbar(:control=>true) do
65
68
  %a= icon(:facebook)
66
69
  %a= icon(:facebook)
67
70
  %a= icon(:comments)
68
-
71
+ ### Footer & tabbars
69
72
  = footer do
70
73
  = tabbar do
71
74
  = link_to "#" do
72
75
  = icon(:facebook)
73
-
76
+ ### List views
74
77
  = article(:class=>"scrollable") do
75
78
  = list_view(:class=>"inset") do
76
79
  = list_item(:arrow=>"right")
@@ -82,6 +85,12 @@
82
85
  1. Title and description widht avatar
83
86
  = list_item do
84
87
  ....
88
+ ### Dialogs
89
+ = dialog(:id=>"mymodal") do
90
+ = link_to "#mymodal", "data-target" => "close" do
91
+ = icon :"remove-circle"
92
+ %h1 Cras mattis consectetur purus sit amet fermentumm agnis dis parturient mo.
93
+
85
94
 
86
95
 
87
96
  ### Contributing to Coolstrap-Generator
@@ -94,14 +103,18 @@
94
103
  * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
95
104
  * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
96
105
 
97
- ### acknowledgments
98
- * Coolstrap team for their awesome work on coolstrap framework.
106
+ ### Local installation
107
+
108
+ * Download from the repo
109
+ * cd /to/coolstrap-generator && rake install
110
+ * ruby -Ilib ./bin/coolstrap # test local bin
111
+
112
+ ### Acknowledgments
113
+ * Coolstrap team - Cristian Ferrari, Abraham Barrera, Felipe Funes - for their awesome work on coolstrap framework.
99
114
  * This gem is heavily inspired in Ti gem from Robert Evans, so many of this gorgeous code was taken verbatim from that gem, the main difference is that I adapted the code to work with coolstrap mobile framework and middleman static page generator system.
100
-
101
-
102
115
 
103
116
  ### Copyright
104
117
 
105
- Copyright Miguel Michelson Martinez (c) 2012 , the same licence as coolstrap.
118
+ Coolstrap mobile framework is licensed under Apache 2.0 by [Rhyboo](http://Rhyboo.com) & (http://needmorecaffeine.com | @needmorecaffeine)
106
119
 
107
- ruby -Ilib ./bin/coolstrap
120
+ coolstrap-generator is a project started by Miguel Michelson and mantained by [Continuum](http://continuum.cl) under the same license as coolstrap.
@@ -20,6 +20,56 @@ describe "Creating of a view file" do
20
20
  end
21
21
  end
22
22
 
23
+ context "Creating a scaffold file and its spec" do
24
+ before(:each) do
25
+ system("cd dailyfocus && coolstrap s list User collection")
26
+ end
27
+
28
+ it "should have created the view within the source/views directory" do
29
+ File.exists?("dailyfocus/source/views/user/_collection.haml").should be_true
30
+ end
31
+ end
32
+
33
+ context "Creating a scaffold file and its spec" do
34
+ before(:each) do
35
+ system("cd dailyfocus && coolstrap s complexlist User complexcollection")
36
+ end
37
+
38
+ it "should have created the view within the source/views directory" do
39
+ File.exists?("dailyfocus/source/views/user/_complexcollection.haml").should be_true
40
+ end
41
+ end
42
+
43
+ context "Creating a scaffold tabbar and its spec" do
44
+ before(:each) do
45
+ system("cd dailyfocus && coolstrap s tabbar User menu")
46
+ end
47
+
48
+ it "should have created the view within the source/views/tabbars directory" do
49
+ File.exists?("dailyfocus/source/views/tabbars/user/_menu.haml").should be_true
50
+ end
51
+ end
52
+
53
+ context "Creating a scaffold toolbar and its spec" do
54
+ before(:each) do
55
+ system("cd dailyfocus && coolstrap s toolbar User menu")
56
+ end
57
+
58
+ it "should have created the view within the source/views/toolbars directory" do
59
+ File.exists?("dailyfocus/source/views/toolbars/user/_menu.haml").should be_true
60
+ end
61
+ end
62
+
63
+ context "Creating a scaffold dialog and its spec" do
64
+ before(:each) do
65
+ system("cd dailyfocus && coolstrap s dialog User menu")
66
+ end
67
+
68
+ it "should have created the view within the source/views/dialogs directory" do
69
+ File.exists?("dailyfocus/source/views/dialogs/user/_menu.haml").should be_true
70
+ end
71
+ end
72
+
23
73
  after(:all) do
24
74
  remove_directories('dailyfocus', 'app', 'spec/views')
25
75
  end
@@ -1,4 +1,4 @@
1
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib', 'ti'))
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib', 'coolstrap-generator'))
2
2
  $LOAD_PATH.unshift(File.dirname(__FILE__))
3
3
  require 'rspec'
4
4
  require 'coolstrap-generator'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: coolstrap-generator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-07-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: coffee-script
16
- requirement: &70098236859260 !ruby/object:Gem::Requirement
16
+ requirement: &70104167605060 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 2.2.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70098236859260
24
+ version_requirements: *70104167605060
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: colored
27
- requirement: &70098236858620 !ruby/object:Gem::Requirement
27
+ requirement: &70104167604420 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '1.2'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70098236858620
35
+ version_requirements: *70104167604420
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rake
38
- requirement: &70098236857960 !ruby/object:Gem::Requirement
38
+ requirement: &70104167603760 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 0.9.2
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70098236857960
46
+ version_requirements: *70104167603760
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: nokogiri
49
- requirement: &70098236857300 !ruby/object:Gem::Requirement
49
+ requirement: &70104167603040 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 1.4.4
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70098236857300
57
+ version_requirements: *70104167603040
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: erubis
60
- requirement: &70098236855800 !ruby/object:Gem::Requirement
60
+ requirement: &70104167601580 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: 2.7.0
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *70098236855800
68
+ version_requirements: *70104167601580
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rocco
71
- requirement: &70098236852500 !ruby/object:Gem::Requirement
71
+ requirement: &70104167598180 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ~>
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0.7'
77
77
  type: :runtime
78
78
  prerelease: false
79
- version_requirements: *70098236852500
79
+ version_requirements: *70104167598180
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: thor
82
- requirement: &70098236865580 !ruby/object:Gem::Requirement
82
+ requirement: &70104167611300 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ~>
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: 0.14.6
88
88
  type: :runtime
89
89
  prerelease: false
90
- version_requirements: *70098236865580
90
+ version_requirements: *70104167611300
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: compass
93
- requirement: &70098236864560 !ruby/object:Gem::Requirement
93
+ requirement: &70104167610340 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ~>
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: '0.7'
99
99
  type: :runtime
100
100
  prerelease: false
101
- version_requirements: *70098236864560
101
+ version_requirements: *70104167610340
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: session
104
- requirement: &70098236863540 !ruby/object:Gem::Requirement
104
+ requirement: &70104167609300 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ~>
@@ -109,10 +109,10 @@ dependencies:
109
109
  version: '3.1'
110
110
  type: :runtime
111
111
  prerelease: false
112
- version_requirements: *70098236863540
112
+ version_requirements: *70104167609300
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: middleman
115
- requirement: &70098236862840 !ruby/object:Gem::Requirement
115
+ requirement: &70104167608420 !ruby/object:Gem::Requirement
116
116
  none: false
117
117
  requirements:
118
118
  - - ~>
@@ -120,10 +120,10 @@ dependencies:
120
120
  version: '2.0'
121
121
  type: :runtime
122
122
  prerelease: false
123
- version_requirements: *70098236862840
123
+ version_requirements: *70104167608420
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: actionpack
126
- requirement: &70098236862020 !ruby/object:Gem::Requirement
126
+ requirement: &70104167607740 !ruby/object:Gem::Requirement
127
127
  none: false
128
128
  requirements:
129
129
  - - ! '>='
@@ -131,10 +131,10 @@ dependencies:
131
131
  version: '0'
132
132
  type: :runtime
133
133
  prerelease: false
134
- version_requirements: *70098236862020
134
+ version_requirements: *70104167607740
135
135
  - !ruby/object:Gem::Dependency
136
136
  name: bundler
137
- requirement: &70098236860940 !ruby/object:Gem::Requirement
137
+ requirement: &70104167606660 !ruby/object:Gem::Requirement
138
138
  none: false
139
139
  requirements:
140
140
  - - ~>
@@ -142,10 +142,10 @@ dependencies:
142
142
  version: 1.1.pre.10
143
143
  type: :development
144
144
  prerelease: false
145
- version_requirements: *70098236860940
145
+ version_requirements: *70104167606660
146
146
  - !ruby/object:Gem::Dependency
147
147
  name: rspec
148
- requirement: &70098236860080 !ruby/object:Gem::Requirement
148
+ requirement: &70104167605840 !ruby/object:Gem::Requirement
149
149
  none: false
150
150
  requirements:
151
151
  - - ~>
@@ -153,7 +153,7 @@ dependencies:
153
153
  version: 2.6.0
154
154
  type: :development
155
155
  prerelease: false
156
- version_requirements: *70098236860080
156
+ version_requirements: *70104167605840
157
157
  description: App Generator for coolstrap mobile framework
158
158
  email:
159
159
  - miguelmichelson@gmail.com
@@ -257,6 +257,7 @@ files:
257
257
  - lib/coolstrap-generator/templates/app/components/_formelements.html.haml
258
258
  - lib/coolstrap-generator/templates/app/components/_tabbar.html.haml
259
259
  - lib/coolstrap-generator/templates/app/components/_toolbar.html.haml
260
+ - lib/coolstrap-generator/templates/app/components/dialog.html.haml.erb
260
261
  - lib/coolstrap-generator/templates/app/components/formelements.html.haml
261
262
  - lib/coolstrap-generator/templates/app/components/listview/_complexlistavatar.html.haml.erb
262
263
  - lib/coolstrap-generator/templates/app/components/listview/_simplelist.html.haml.erb