hensel 0.0.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.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.travis.yml +20 -0
- data/Gemfile +4 -0
- data/Guardfile +13 -0
- data/LICENSE.txt +22 -0
- data/README.md +337 -0
- data/Rakefile +9 -0
- data/hensel.gemspec +29 -0
- data/lib/hensel/builder/item.rb +43 -0
- data/lib/hensel/builder/node.rb +53 -0
- data/lib/hensel/builder.rb +105 -0
- data/lib/hensel/configuration.rb +37 -0
- data/lib/hensel/filters.rb +47 -0
- data/lib/hensel/helpers/tag_helpers.rb +113 -0
- data/lib/hensel/helpers.rb +9 -0
- data/lib/hensel/version.rb +3 -0
- data/lib/hensel.rb +29 -0
- data/spec/builder_spec.rb +202 -0
- data/spec/configuration_spec.rb +18 -0
- data/spec/helpers_spec.rb +8 -0
- data/spec/item_spec.rb +40 -0
- data/spec/node_spec.rb +75 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/tag_helpers_spec.rb +41 -0
- metadata +188 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 08c2d34b1ceac0afa538c237967ef7ce7fd6e9d8
|
4
|
+
data.tar.gz: 710a9707597f29eddc79e054bf4ce83b91277f9a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d3bc09b7389bdefdc9f524bdd0f790bbde158629d057299f00991c226ea03fb2fc1e1040f4fc7701f22c1e252a4f3aa7ea7204fdf1027e3ebcfa24fe360d688b
|
7
|
+
data.tar.gz: ced520e15fd2121ae7bb279d2cad07bb4970762ea1cc8ddf2171ed4601cdcc393444c6c08ec013d18d8b9eec9fbb19d40b4e2a6f1a90d174d761b43aee1ab365
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/.travis.yml
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
lang: ruby
|
2
|
+
before_install: gem install bundler --pre
|
3
|
+
install:
|
4
|
+
- gem update --system
|
5
|
+
- bundle update
|
6
|
+
rvm:
|
7
|
+
- 2.0.0
|
8
|
+
- 2.1.0
|
9
|
+
- jruby-head
|
10
|
+
- rbx
|
11
|
+
notifications:
|
12
|
+
recipients:
|
13
|
+
- namusyaka@gmail.com
|
14
|
+
branches:
|
15
|
+
only:
|
16
|
+
- master
|
17
|
+
matrix:
|
18
|
+
allow_failures:
|
19
|
+
- rvm: rbx
|
20
|
+
- rvm: jruby-head
|
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
guard 'rspec', version: 2 do
|
2
|
+
watch(%r{^spec/.+_spec\.rb$})
|
3
|
+
watch(%r{^lib/(.+)\.rb$}) {|m| "spec/#{m[1]}_spec.rb" }
|
4
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
5
|
+
watch('spec/spec_helper.rb') { "spec" }
|
6
|
+
end
|
7
|
+
|
8
|
+
# Add files and commands to this file, like the example:
|
9
|
+
# watch(%r{file/path}) { `command(s)` }
|
10
|
+
#
|
11
|
+
guard 'shell' do
|
12
|
+
watch(/(.*).txt/) {|m| `tail #{m[0]}` }
|
13
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 namusyaka
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,337 @@
|
|
1
|
+
# Hensel
|
2
|
+
|
3
|
+
[](https://travis-ci.org/namusyaka/hensel)
|
4
|
+
|
5
|
+
Hensel makes it easy to build the breadcrumbs.
|
6
|
+
|
7
|
+
Especially, want to recommend for use in Sinatra and Padrino.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
gem 'hensel'
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install hensel
|
22
|
+
|
23
|
+
## Requirements
|
24
|
+
|
25
|
+
* MRI 2.0+
|
26
|
+
|
27
|
+
## Overview
|
28
|
+
|
29
|
+
Hensel can be used easily in your web applications, and it has powerful flexibility.
|
30
|
+
You can use it as helper and builder.
|
31
|
+
In the next section, will explain in detail how to use them.
|
32
|
+
|
33
|
+
## Usage
|
34
|
+
|
35
|
+
### Configuration
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
require 'hensel'
|
39
|
+
|
40
|
+
Hensel.configure do |config|
|
41
|
+
# Default values
|
42
|
+
config.bootstrap = false
|
43
|
+
config.escape_html = true
|
44
|
+
config.indentation = true
|
45
|
+
config.last_item_link = false
|
46
|
+
config.richsnippet = :microdata
|
47
|
+
config.attr_wrapper = "'"
|
48
|
+
config.whitespace = " "
|
49
|
+
config.parent_element = :ul
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
53
|
+
**If `bootstrap` is set to `true`, the parent element of breadcrumbs will contain `breadcrumb` as class attrbiute, and the last item will contain `active` as class attrbiute as well.**
|
54
|
+
It will be something like below.
|
55
|
+
|
56
|
+
```html
|
57
|
+
<ul class='breadcrumb'>
|
58
|
+
<li>
|
59
|
+
<a href='/'>
|
60
|
+
index
|
61
|
+
</a>
|
62
|
+
</li>
|
63
|
+
<li class='active'>
|
64
|
+
current
|
65
|
+
</li>
|
66
|
+
</ul>
|
67
|
+
```
|
68
|
+
|
69
|
+
**If `escape_html` is set to `true`, the text of item and all value of attributes will be escaped.**
|
70
|
+
|
71
|
+
**If `indentation` is set to `true`, the breadcrumbs will be indented.**
|
72
|
+
|
73
|
+
**If `richsnippet` is set to correct symbol, the breadcrumbs will follow the rules of the rich snippets that have been specified.**
|
74
|
+
There is a `:microdata` and `:rdfa`, please specify `nil` if not required type.
|
75
|
+
It will be something like below.
|
76
|
+
|
77
|
+
```html
|
78
|
+
<!-- microdata -->
|
79
|
+
<ul>
|
80
|
+
<li itemscope itemtype='http://data-vocabulary.org/Breadcrumb'>
|
81
|
+
<a href='/' itemprop='url'>
|
82
|
+
<span itemprop='title'>
|
83
|
+
index
|
84
|
+
</span>
|
85
|
+
</a>
|
86
|
+
</li>
|
87
|
+
<li itemscope itemtype='http://data-vocabulary.org/Breadcrumb'>
|
88
|
+
<span itemprop='title'>
|
89
|
+
current
|
90
|
+
</span>
|
91
|
+
</li>
|
92
|
+
</ul>
|
93
|
+
|
94
|
+
<!-- RDFa -->
|
95
|
+
<ul xmlns:v='http://rdf.data-vocabulary.org/#'>
|
96
|
+
<li typeof='v:Breadcrumb'>
|
97
|
+
<a href='/' rel='v:url' property="v:title">
|
98
|
+
index
|
99
|
+
</a>
|
100
|
+
</li>
|
101
|
+
<li typeof='v:Breadcrumb'>
|
102
|
+
<span property="v:title">
|
103
|
+
current
|
104
|
+
</span>
|
105
|
+
</li>
|
106
|
+
</ul>
|
107
|
+
```
|
108
|
+
|
109
|
+
*If don't have special reason, you should enable the option.*
|
110
|
+
*Microdata and RDFa are supported by [google](https://support.google.com/webmasters/answer/185417?hl=en).*
|
111
|
+
|
112
|
+
|
113
|
+
**If `last_item_link` is set to `true`, the link of the last item will contain `a` element as with other elements.**
|
114
|
+
It will be something below.
|
115
|
+
|
116
|
+
```html
|
117
|
+
<!-- If `last_item_link` is set to `true` -->
|
118
|
+
<ul class="breadcrumb">
|
119
|
+
<li>
|
120
|
+
<a href="/">
|
121
|
+
index
|
122
|
+
</a>
|
123
|
+
</li>
|
124
|
+
<li>
|
125
|
+
<a href="/foo">
|
126
|
+
foo
|
127
|
+
</a>
|
128
|
+
</li>
|
129
|
+
</ul>
|
130
|
+
<!-- If `last_item_link` is set to `false` -->
|
131
|
+
<ul class="breadcrumb">
|
132
|
+
<li>
|
133
|
+
<a href="/">
|
134
|
+
index
|
135
|
+
</a>
|
136
|
+
</li>
|
137
|
+
<li>
|
138
|
+
<span>
|
139
|
+
foo
|
140
|
+
</span>
|
141
|
+
</li>
|
142
|
+
</ul>
|
143
|
+
```
|
144
|
+
|
145
|
+
|
146
|
+
**If `attr_wrapper` is set to a wrapper string, all attributes will be used it as the attribute wrapper.**
|
147
|
+
It will be somthing below.
|
148
|
+
|
149
|
+
```html
|
150
|
+
<!-- If `attr_wrapper` is set to `'"'` -->
|
151
|
+
<ul class="breadcrumb">
|
152
|
+
<li>
|
153
|
+
<a href="/">
|
154
|
+
index
|
155
|
+
</a>
|
156
|
+
</li>
|
157
|
+
</ul>
|
158
|
+
<!-- If `attr_wrapper` is set to `nil` -->
|
159
|
+
<ul class=breadcrumb>
|
160
|
+
<li>
|
161
|
+
<a href=/>
|
162
|
+
index
|
163
|
+
</a>
|
164
|
+
</li>
|
165
|
+
</ul>
|
166
|
+
```
|
167
|
+
|
168
|
+
**If `whitespace` is set to a whitespace string, all indentation will be used it as the indentation space.**
|
169
|
+
It will be somthing below.
|
170
|
+
|
171
|
+
```html
|
172
|
+
<!-- If `whitespace` is set to `" "` -->
|
173
|
+
<ul>
|
174
|
+
<li>
|
175
|
+
<a href="/">
|
176
|
+
index
|
177
|
+
</a>
|
178
|
+
</li>
|
179
|
+
</ul>
|
180
|
+
<!-- If `attr_wrapper` is set to `" "` -->
|
181
|
+
<ul>
|
182
|
+
<li>
|
183
|
+
<a href="/">
|
184
|
+
index
|
185
|
+
</a>
|
186
|
+
</li>
|
187
|
+
</ul>
|
188
|
+
```
|
189
|
+
|
190
|
+
**If `parent_element` is set to a name string, it will be used as a name of the parent element.**
|
191
|
+
|
192
|
+
### Builder
|
193
|
+
|
194
|
+
#### `add(text, url, **options) -> Hensel::Builder::Item`
|
195
|
+
|
196
|
+
Adds a new item to items, and returns a fresh instance of `Hensel::Builder::Item` built by the builder.
|
197
|
+
|
198
|
+
```ruby
|
199
|
+
builder = Hensel::Builder.new
|
200
|
+
item = builder.add("home", "/")
|
201
|
+
item.text #=> "home"
|
202
|
+
item.url #=> "/"
|
203
|
+
```
|
204
|
+
|
205
|
+
#### `add(**parameters) -> Hensel::Builder::Item`
|
206
|
+
|
207
|
+
```ruby
|
208
|
+
builder = Hensel::Builder.new
|
209
|
+
item = builder.add(text: "home", url: "/")
|
210
|
+
item.text #=> "home"
|
211
|
+
item.url #=> "/"
|
212
|
+
```
|
213
|
+
|
214
|
+
#### `remove(text)`
|
215
|
+
|
216
|
+
Removes the item from items.
|
217
|
+
|
218
|
+
```ruby
|
219
|
+
builder = Hensel::Builder.new
|
220
|
+
builder.add(text: "home", url: "/")
|
221
|
+
|
222
|
+
builder.items.empty? #=> false
|
223
|
+
builder.remove("home")
|
224
|
+
builder.items.empty? #=> true
|
225
|
+
```
|
226
|
+
|
227
|
+
#### `remove{|item| ... }`
|
228
|
+
|
229
|
+
```ruby
|
230
|
+
builder = Hensel::Builder.new
|
231
|
+
builder.add(text: "home", url: "/")
|
232
|
+
|
233
|
+
builder.items.empty? #=> false
|
234
|
+
builder.remove{|item| item.text == "home" }
|
235
|
+
builder.items.empty? #=> true
|
236
|
+
```
|
237
|
+
|
238
|
+
#### `render -> String`
|
239
|
+
|
240
|
+
Renders the breadcrumbs, and returns the html of breadcrumbs rendered by this method.
|
241
|
+
|
242
|
+
```ruby
|
243
|
+
builder = Hensel::Builder.new
|
244
|
+
builder.add(text: "home", url: "/")
|
245
|
+
|
246
|
+
builder.render #=> "<ul> ... </ul>"
|
247
|
+
```
|
248
|
+
|
249
|
+
#### `render{ ... } -> String`
|
250
|
+
|
251
|
+
This method is for customize breadcrumbs.
|
252
|
+
|
253
|
+
If this method has a parameter, it will be an instance of `Hensel::Builder::Item`.
|
254
|
+
|
255
|
+
If this method does not have parameter, the block will be evaluated as an instance of `Hensel::Builder::Item`.
|
256
|
+
|
257
|
+
However, if you use `render` with block, a few configuration(`richsnippets`, `last_item_link`) will be ignored.
|
258
|
+
|
259
|
+
```ruby
|
260
|
+
builder = Hensel::Builder.new
|
261
|
+
builder.add(text: "home", url: "/")
|
262
|
+
|
263
|
+
builder.render {|item| "<li>#{item.text}</li>" } #=> "<ul><li>home</li></ul>"
|
264
|
+
builder.render do
|
265
|
+
if last?
|
266
|
+
node(:li) do
|
267
|
+
node(:span){ item.text }
|
268
|
+
end
|
269
|
+
else
|
270
|
+
node(:li) do
|
271
|
+
node(:a, href: item.url) do
|
272
|
+
node(:span){ item.text }
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
```
|
278
|
+
|
279
|
+
### Helpers
|
280
|
+
|
281
|
+
The helper is prepared for use in Sinatra and Padrino.
|
282
|
+
|
283
|
+
### with Sinatra
|
284
|
+
|
285
|
+
```ruby
|
286
|
+
class Sample < Sinatra::Base
|
287
|
+
helpers Hensel::Helpers
|
288
|
+
|
289
|
+
configure do
|
290
|
+
Hensel.configure do |config|
|
291
|
+
config.attr_wrapper = '"'
|
292
|
+
config.whitespace = ' '
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
get "/" do
|
297
|
+
breadcrumbs.add("home", "/")
|
298
|
+
breadcrumbs.render
|
299
|
+
end
|
300
|
+
end
|
301
|
+
```
|
302
|
+
|
303
|
+
### with Padrino
|
304
|
+
|
305
|
+
```ruby
|
306
|
+
# config/boot.rb
|
307
|
+
Padrino.before_load do
|
308
|
+
Hensel.configure do |config|
|
309
|
+
config.attr_wrapper = '"'
|
310
|
+
config.whitespace = ' '
|
311
|
+
end
|
312
|
+
end
|
313
|
+
```
|
314
|
+
|
315
|
+
```ruby
|
316
|
+
class Sample < Padrino::Application
|
317
|
+
helpers Hensel::Helpers
|
318
|
+
|
319
|
+
get :index do
|
320
|
+
breadcrumbs.add("home", ?/)
|
321
|
+
breadcrumbs.render
|
322
|
+
end
|
323
|
+
end
|
324
|
+
```
|
325
|
+
|
326
|
+
## TODO
|
327
|
+
|
328
|
+
* Support Rails
|
329
|
+
* New syntax for Sinatra and Padrino
|
330
|
+
|
331
|
+
## Contributing
|
332
|
+
|
333
|
+
1. Fork it ( https://github.com/namusyaka/hensel/fork )
|
334
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
335
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
336
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
337
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/hensel.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'hensel/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "hensel"
|
8
|
+
spec.version = Hensel::VERSION
|
9
|
+
spec.authors = ["namusyaka"]
|
10
|
+
spec.email = ["namusyaka@gmail.com"]
|
11
|
+
spec.summary = %q{Hensel makes it easy to build the breadcrumbs.}
|
12
|
+
spec.description = spec.summary
|
13
|
+
spec.homepage = "https://github.com/namusyaka/hensel"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
spec.add_development_dependency "nyan-cat-formatter"
|
25
|
+
spec.add_development_dependency "rspec-html-matchers"
|
26
|
+
spec.add_development_dependency "guard"
|
27
|
+
spec.add_development_dependency "guard-shell"
|
28
|
+
spec.add_development_dependency "guard-rspec"
|
29
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require 'hensel/builder/node'
|
3
|
+
|
4
|
+
module Hensel
|
5
|
+
class Builder
|
6
|
+
class Item < Node
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
attr_accessor :text, :url, :options
|
10
|
+
attr_accessor :_first, :_last, :renderer
|
11
|
+
|
12
|
+
def_delegators :@options, :[], :[]=
|
13
|
+
|
14
|
+
def initialize(text, url, **options)
|
15
|
+
@text = h(text)
|
16
|
+
@url = url
|
17
|
+
@options = options
|
18
|
+
end
|
19
|
+
|
20
|
+
def render
|
21
|
+
if renderer
|
22
|
+
instance_eval(&renderer)
|
23
|
+
else
|
24
|
+
node(:li, **options) do
|
25
|
+
if !Hensel.configuration.last_item_link? && item.last?
|
26
|
+
node(:span){ item.text }
|
27
|
+
else
|
28
|
+
node(:a, href: item.url){ item.text }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def first?
|
35
|
+
!!_first
|
36
|
+
end
|
37
|
+
|
38
|
+
def last?
|
39
|
+
!!_last
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'hensel/helpers/tag_helpers'
|
2
|
+
|
3
|
+
module Hensel
|
4
|
+
class Builder
|
5
|
+
class Node < Struct.new(:name, :attributes, :content, :parent, :indent)
|
6
|
+
include Hensel::Helpers::TagHelpers
|
7
|
+
|
8
|
+
def node(name, content = nil, **attributes, &block)
|
9
|
+
element = Node.new(name, attributes, content, self, child_indent)
|
10
|
+
content =
|
11
|
+
if block_given?
|
12
|
+
result = element.instance_eval(&block)
|
13
|
+
element.children.length.zero? ? result : element.render
|
14
|
+
else
|
15
|
+
content
|
16
|
+
end
|
17
|
+
children << (child = content_tag(name, content, attributes.merge!(indent: child_indent), &block))
|
18
|
+
child
|
19
|
+
end
|
20
|
+
|
21
|
+
def render
|
22
|
+
children.join(Hensel.configuration.indentation? ? "\n" : "")
|
23
|
+
end
|
24
|
+
|
25
|
+
def children
|
26
|
+
@children ||= []
|
27
|
+
end
|
28
|
+
|
29
|
+
def item
|
30
|
+
@item ||=
|
31
|
+
begin
|
32
|
+
return self if self.instance_of?(Hensel::Builder::Item)
|
33
|
+
ancestor = parent
|
34
|
+
while ancestor.instance_of?(Hensel::Builder::Node)
|
35
|
+
ancestor = ancestor.parent
|
36
|
+
end
|
37
|
+
ancestor
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def child_indent
|
44
|
+
@child_indent ||=
|
45
|
+
if Hensel.configuration.indentation?
|
46
|
+
indent ? indent + 1 : 1
|
47
|
+
else
|
48
|
+
0
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'hensel/builder/item'
|
2
|
+
require 'hensel/helpers/tag_helpers'
|
3
|
+
require 'hensel/filters'
|
4
|
+
|
5
|
+
module Hensel
|
6
|
+
class Builder
|
7
|
+
include Helpers::TagHelpers
|
8
|
+
|
9
|
+
attr_reader :items, :options
|
10
|
+
|
11
|
+
def initialize(**options)
|
12
|
+
@items = []
|
13
|
+
@options = options
|
14
|
+
end
|
15
|
+
|
16
|
+
# Adds an item to items
|
17
|
+
def add(*arguments)
|
18
|
+
items << (item = Item.new(*parse_arguments(arguments)))
|
19
|
+
item.parent = self
|
20
|
+
item
|
21
|
+
end
|
22
|
+
|
23
|
+
# Removes the item from items
|
24
|
+
# @example without block
|
25
|
+
# builder = Hensel::Builder.new
|
26
|
+
# builder.add("Index", "/")
|
27
|
+
# builder.remove("Index")
|
28
|
+
#
|
29
|
+
# @example with block
|
30
|
+
# builder = Hensel::Builder.new
|
31
|
+
# builder.add("Index", "/")
|
32
|
+
# builder.remove{|item| item.text == "Index" }
|
33
|
+
def remove(text = nil, &block)
|
34
|
+
block_given? ? items.delete_if(&block) : items.delete_if{|item| text == item.text }
|
35
|
+
end
|
36
|
+
|
37
|
+
# Renders the breadcrumb html
|
38
|
+
def render(&block)
|
39
|
+
process! unless processed?
|
40
|
+
|
41
|
+
concatenated_items = map_items do |item|
|
42
|
+
if block_given?
|
43
|
+
block.arity.zero? ? item.instance_eval(&block) : block.call(item)
|
44
|
+
else
|
45
|
+
item.render
|
46
|
+
end
|
47
|
+
end.join(Hensel.configuration.indentation? ? "\n" : "")
|
48
|
+
|
49
|
+
content_tag(Hensel.configuration.parent_element, concatenated_items, options)
|
50
|
+
end
|
51
|
+
|
52
|
+
def processed?
|
53
|
+
!!@processed
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def map_items
|
59
|
+
items_length = items.length.pred
|
60
|
+
items.map.with_index do |item, index|
|
61
|
+
if index == items_length
|
62
|
+
item._last = true
|
63
|
+
elsif index.zero?
|
64
|
+
item._first = true
|
65
|
+
else
|
66
|
+
item._first = item._last = false
|
67
|
+
end
|
68
|
+
item_filters.each{|filter| item.instance_eval(&filter) } unless item_filters.empty?
|
69
|
+
yield item
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def item_filters
|
74
|
+
@item_filters ||= []
|
75
|
+
end
|
76
|
+
|
77
|
+
# @!visibility private
|
78
|
+
def process!
|
79
|
+
configuration = Hensel.configuration
|
80
|
+
|
81
|
+
Hensel::Filters.filters[:filters].each_pair do |name, block|
|
82
|
+
instance_eval(&block) if configuration.send(:"#{name}?")
|
83
|
+
end
|
84
|
+
richsnippet_filter = Hensel::Filters.filters[:richsnippets][configuration.richsnippet]
|
85
|
+
item_filters << richsnippet_filter if richsnippet_filter
|
86
|
+
@processed = true
|
87
|
+
end
|
88
|
+
|
89
|
+
# @!visibility private
|
90
|
+
def parse_arguments(arguments)
|
91
|
+
case arguments.length
|
92
|
+
when 3
|
93
|
+
arguments
|
94
|
+
when 2
|
95
|
+
arguments << {}
|
96
|
+
when 1
|
97
|
+
if (options = arguments.first) && options.instance_of?(Hash)
|
98
|
+
[ options.delete(:text) || options.delete(:content), options.delete(:path) || options.delete(:url), options ]
|
99
|
+
else
|
100
|
+
raise ArgumentError
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|