1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
|
[](http://badge.fury.io/rb/gretel)
[](https://github.com/kzkn/gretel/actions/workflows/ci.yml)
<img src="http://i.imgur.com/CAKEaBM.png" alt="Handle breadcrumb trails... like a boss :)" />
([TL;DR](http://i.imgur.com/nH25yiH.png)) Gretel is a [Ruby on Rails](http://rubyonrails.org) plugin that makes it easy yet flexible to create breadcrumbs.
It is based around the idea that breadcrumbs are a concern of the view, so you define a set of breadcrumbs in *config/breadcrumbs.rb* (or multiple files; see below) and specify in the view which breadcrumb to use.
Gretel also supports [semantic breadcrumbs](https://developers.google.com/search/docs/data-types/breadcrumb) (those used in Google results).
Have fun!
## Installation
In your *Gemfile*:
```ruby
gem "gretel"
```
And run:
```bash
$ bundle install
```
## Example
Start by generating breadcrumbs configuration file:
```bash
$ rails generate gretel:install
```
Then, in *config/breadcrumbs.rb*:
```ruby
# Root crumb
crumb :root do
link "Home", root_path
end
# Issue list
crumb :issues do
link "All issues", issues_path
end
# Issue
crumb :issue do |issue|
link issue.title, issue
parent :issues
end
```
At the top of *app/views/issues/show.html.erb*, set the current breadcrumb (assuming you have loaded `@issue` with an issue):
```erb
<% breadcrumb :issue, @issue %>
```
Then, in *app/views/layouts/application.html.erb*:
```erb
<%= breadcrumbs pretext: "You are here: ",
separator: " › " %>
```
This will generate the following HTML (indented for readability):
```html
<div class="breadcrumbs">
<span class="pretext">You are here:</span>
<a href="/">Home</a> ›
<a href="/issues">All issues</a> ›
<span class="current">My Issue</span>
</div>
```
## Options
You can pass options to `<%= breadcrumbs %>`, e.g. `<%= breadcrumbs pretext: "You are here: " %>`:
Option | Description | Default
------------------------ | -------------------------------------------------------------------------------------------------------------------------- | -------
:style | How to render the breadcrumbs. Can be `:inline`, `:ol`, `:ul`, `:bootstrap`, `:bootstrap4`, `:bootstrap5`, `:foundation5`, or `:bulma`. See below for more info. | `:inline`
:pretext | Text to be rendered before breadcrumb, e.g. `"You are here: "`. | None
:posttext | Text to be appended after breadcrumb, e.g. `"Text after breacrumb"`, | None
:separator | Separator between links, e.g. `" › "`. | `" › "`
:autoroot | Whether it should automatically link to the `:root` crumb if no parent is given. | True
:display_single_fragment | Whether it should display the breadcrumb if it includes only one link. | False
:link_current | Whether the current crumb should be linked to. | False
:link_current_to_request_path | Whether the current crumb should always link to the current request path. *Note:* This option will have no effect unless `:link_current` is set to `true`. | True
:semantic | Whether it should generate [semantic breadcrumbs](https://developers.google.com/search/docs/data-types/breadcrumb). | False
:id | ID for the breadcrumbs container. | None
:class | CSS class for the breadcrumbs container. Can be set to `nil` for no class. | `"breadcrumbs"`
:fragment_class | CSS class for the fragment link or span. Can be set to `nil` for no class. | None
:current_class | CSS class for the current link or span. Can be set to `nil` for no class. | `"current"`
:pretext_class | CSS class for the pretext, if given. Can be set to `nil` for no class. | `"pretext"`
:posttext_class | CSS class for the posttext, if given. Can be set to `nil` for no class. | `"posttext"`
:link_class | CSS class for the link, if given. Can be set to `nil` for no class. | None
:container_tag | Tag type that contains the breadcrumbs. | `:div`
:fragment_tag | Tag type to contain each breadcrumb fragment/link. | None
:aria_current | Value of `aria-current` attribute. | None
:link_data | Adds data attributes to breadcrumb | `nil`
### Styles
These are the styles you can use with `breadcrumbs style: :xx`.
Style | Description
-------------- | -----------
`:inline` | Default. Renders each link by itself with `›` as the seperator.
`:ol` | Renders the links in `<li>` elements contained in an outer `<ol>`.
`:ul` | Renders the links in `<li>` elements contained in an outer `<ul>`.
`:bootstrap` | Renders the links for use in [Bootstrap v3](https://getbootstrap.com/docs/3.4/).
`:bootstrap4` | Renders the links for use in [Bootstrap v4](https://getbootstrap.com/docs/4.6/getting-started/introduction/).
`:bootstrap5` | Renders the links for use in [Bootstrap v5](https://getbootstrap.com/).
`:foundation5` | Renders the links for use in [Foundation 5](https://get.foundation/).
`:bulma` | Renders the links for use in [Bulma](https://bulma.io/documentation/components/breadcrumb/).
#### Bulma Style
The `:bulma` style renders breadcrumbs compatible with [Bulma CSS](https://bulma.io/documentation/components/breadcrumb/).
**Basic usage:**
```erb
<nav class="breadcrumb" aria-label="breadcrumbs">
<%= breadcrumbs style: :bulma %>
</nav>
```
This generates HTML like:
```html
<nav class="breadcrumb" aria-label="breadcrumbs">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/issues">All issues</a></li>
<li class="is-active"><a href="/issues/123" aria-current="page">My Issue</a></li>
</ul>
</nav>
```
**Customize separators:**
```erb
<nav class="breadcrumb has-arrow-separator" aria-label="breadcrumbs">
<%= breadcrumbs style: :bulma %>
</nav>
```
---
Or you can build the breadcrumbs manually for full customization; see below.
If you add other widely used styles, please submit a [Pull Request](https://github.com/kzkn/gretel/pulls) so others can use them too.
## More examples
In *config/breadcrumbs.rb*:
```ruby
# Root crumb
crumb :root do
link "Home", root_path
end
# Regular crumb
crumb :projects do
link "Projects", projects_path
end
# Parent crumbs
crumb :project_issues do |project|
link "Issues", project_issues_path(project)
parent project # inferred to :project
end
# Child
crumb :issue do |issue|
link issue.name, issue_path(issue)
parent :project_issues, issue.project
end
# Recursive parent categories
crumb :category do |category|
link category.name, category
if category.parent
parent category.parent # inferred to :category
else
parent :categories
end
end
# Product crumb with recursive parent categories (as defined above)
crumb :product do |product|
link product.name, product
parent product.category # inferred to :category
end
# Crumb with multiple links
crumb :test do
link "One", one_path
link "Two", two_path
parent :about
end
# Example of using params to alter the parent, e.g. to
# match the user's actual navigation path
# URL: /products/123?q=my+search
crumb :search do |keyword|
link "Search for #{keyword}", search_path(q: keyword)
end
crumb :product do |product|
if keyword = params[:q].presence
parent :search, keyword
else # default
parent product.category # inferred to :category
end
end
# Multiple arguments
crumb :multiple_test do |a, b, c|
link "Test #{a}, #{b}, #{c}", test_path
parent :other_test, 3, 4, 5
end
# Breadcrumb without link URL; will not generate a link
crumb :without_link do
link "Breadcrumb without link"
end
# Breadcrumb using view helper
module UsersHelper
def user_name_for(user)
user.name
end
end
crumb :user do |user|
link user_name_for(user), user
end
# I18n
crumb :home do
link t("breadcrumbs.home"), root_path
end
```
## Building the breadcrumbs manually
You can use the `breadcrumbs` method directly as an array. It will return an array with the breadcrumb links so you can build the breadcrumbs HTML manually:
```erb
<% breadcrumbs.tap do |links| %>
<% if links.any? %>
You are here:
<% links.each do |link| %>
<%= link_to link.text, link.url, class: (link.current? ? "current" : nil) %> (<%= link.key %>)
<% end %>
<% end %>
<% end %>
```
If you use this approach, you lose the built-in semantic breadcrumb functionality. One way to
add them back is to use JSON-LD structured data:
```erb
<script type="application/ld+json">
<%= raw breadcrumbs.structured_data(url_base: "https://example.com").to_json %>
</script>
```
Or, you can infer `url_base` from `request`:
```erb
<script type="application/ld+json">
<%= raw breadcrumbs.structured_data(url_base: "#{request.protocol}#{request.host_with_port}").to_json %>
</script>
```
## Getting the parent breadcrumb
If you want to add a link to the parent breadcrumb, you can use the `parent_breadcrumb` view helper.
By default it returns a link instance that has the properties `#key`, `#text`, and `#url`.
You can supply options like `autoroot: false` etc.
If you supply a block, it will yield the link if it is present:
```erb
<% parent_breadcrumb do |link| %>
<%= link_to "Back to #{link.text}", link.url %>
<% end %>
```
## Nice to know
### Access to view methods
When configuring breadcrumbs inside a `crumb :xx do ... end` block, you have access to all methods that are normally accessible in the view where the breadcrumbs are inserted. This includes your view helpers, `params`, `request`, etc.
### Using multiple breadcrumb configuration files
If you have a large site and you want to split your breadcrumbs configuration over multiple files, you can create a folder named `config/breadcrumbs` and put your configuration files (e.g. `products.rb` or `frontend.rb`) in there.
The format is the same as `config/breadcrumbs.rb` which is also loaded.
### Loading breadcrumbs from engines
Breadcrumbs are automatically loaded from any engines' `config/breadcrumbs.rb` and `config/breadcrumbs/**/*.rb`.
Breadcrumbs defined in your main app will override breadcrumbs from engines.
### Inferring breadcrumbs
Breadcrumbs can be automatically inferred if you pass an instance of an object that responds to `model_name` (like an ActiveRecord model instance).
For example:
```erb
<% breadcrumb @product %>
```
is short for
```erb
<% breadcrumb :product, @product %>
```
### Passing options to links
You can pass options to links to be used when you render breadcrumbs manually.
In *config/breadcrumbs.rb*:
```ruby
crumb :something do
link "My Link", my_path, title: "My Title", other: "My Other Option"
end
```
Example methods you can then use in the view:
```ruby
breadcrumbs do |links|
links.each do |link|
link.title? # => true
link.title # => "My Title"
link.other? # => true
link.other # => "My Other Option"
link.nonexisting_option? # => false
link.nonexisting_option # => nil
end
end
```
### ARIA support
You can improve the accessibility of your page with the markup that specified in [ARIA](https://www.w3.org/TR/wai-aria-practices/examples/breadcrumb/index.html). Gretel supports generating `aria-current` attribute:
```erb
<% breadcrumb :issue, @issue %>
<%= breadcrumbs aria_current: "page" %>
```
This will generate the following HTML (indented for readability):
```html
<div class="breadcrumbs">
<a href="/">Home</a> ›
<a href="/issues">All issues</a> ›
<span class="current" aria-current="page">My Issue</span>
</div>
```
## Documentation
* [Full documentation](https://rubydoc.info/gems/gretel)
* [Changelog](https://github.com/kzkn/gretel/blob/main/CHANGELOG.md)
* [Tutorial on using Gretel](https://www.sitepoint.com/breadcrumbs-rails-gretel/) (Sitepoint)
## Versioning
Follows [semantic versioning](https://semver.org/).
## Contributing
You are very welcome to help improve Gretel if you have suggestions for features that other people can use.
To contribute:
1. Fork the project
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Make your changes
4. Add/Fix tests
5. Prepare database for testing: `cd spec/dummy; rake db:migrate; rake db:test:prepare; cd ../..`
6. Run `rake` to make sure all tests pass
7. Be sure to check in the changes to `coverage/coverage.txt`
8. Commit your changes (`git commit -am 'Add new feature'`)
9. Push to the branch (`git push origin my-new-feature`)
10. Create new pull request
Thanks.
## History
This repository had been a fork of [lassebunk/gretel](https://github.com/lassebunk/gretel) for a long time. However, due to some reasons, the maintenance of this repository was stopped and the official repository of gretel was transferred to [WilHall/gretel](https://github.com/WilHall/gretel), which is the fork of lassebunk/gretel. WilHall/gretel was then transferred to kzkn/gretel, where it continues to be maintained. During this time, kzkn/gretel was a fork of lassebunk/gretel, so `lassebunk/gretel:master` was selected by default when a pull request was made. This caused unnecessary confusion for contributors to gretel.
As mentioned earlier, lassebunk/gretel is no longer maintained. I have decided to detach the fork for the future of gretel, with all due respect to [@lassebunk](https://github.com/lassebunk) for creating gretel.
## Contributors
Gretel was created by [@lassebunk](https://github.com/lassebunk) and was maintained by [@WilHall](https://github.com/WilHall).
And it is maintained by [@kzkn](https://github.com/kzkn).
[See the list of contributors](https://github.com/kzkn/gretel/graphs/contributors)
## And then
<img src="http://i.imgur.com/u4Wbt4n.png" alt="After using Gretel, you'll be like this" />
Have fun!
Copyright (c) 2010-2020 [Lasse Bunk](http://lassebunk.dk), released under the MIT license
|