Compare commits

...

48 Commits

Author SHA1 Message Date
Jeff See
288acfacfa
Merge pull request #23 from forestryio/fix/ruby-3.0
fix: Ruby 3.0 Argument Error
2021-10-14 13:08:21 -07:00
Frank Taillandier
21607b627b
Merge pull request #20 from felnne/master
Fixing use double-splats for hash parameters error
2021-07-13 11:51:42 +02:00
Frank Taillandier
41b23d6568 fix: Ruby 3.0 Argument Error
See https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/
2021-07-13 11:46:26 +02:00
Felix Fennell
6c8b53eeb0
Fixing use double-splats for hash parameters error
Now an error from Ruby 3.0.0
2021-03-17 08:40:16 +00:00
Frank Taillandier
2ba953f41f
Minor bump 2019-08-22 17:59:40 +02:00
Frank Taillandier
ebafa6207a
Allow for Jekyll 4.0 2019-08-22 17:38:22 +02:00
Jordon Bedwell
4eeffa3021 Remove extra either. 2017-09-28 03:17:51 -05:00
Jordon Bedwell
34fd696fd6 Further clarifications on 1f020335bfe1e80e418042c1cf7912e8d2bc323f 2017-09-28 03:17:11 -05:00
Jordon Bedwell
1f020335bf Adjust the language of the installation instructions.
This updates the installation instructions to push users towards using Bundler of RubyGems, because it isolates gems, it's the industry standard in Ruby, and it will allow them to use many of the surface tools Jekyll has (like Jekyll Docker, and others.)  It also adjust the different types of installation to using headers to guide so that users can skim to win.
2017-09-28 03:09:22 -05:00
Jordon Bedwell
e6f021a666 Code blocks should be using lang identifiers. 2017-09-28 02:50:37 -05:00
chrisdmacrae
4bfea59378 Update README.md
Bundle add doesn't work because it doesn't add it to the jekyll plugins group.
2017-09-07 12:58:31 -03:00
chrisdmacrae
c157ba39a4 Merge pull request #9 from forestryio/documentation
Documentation
2017-08-31 15:26:28 -03:00
chrisdmacrae
3e8eb755e0 Update README.md 2017-08-30 12:58:39 -03:00
chrisdmacrae
f69126e4bb Update README.md 2017-08-29 16:28:21 -03:00
Christopher Macrae
f33b6afd7c Update README 2017-08-29 16:26:19 -03:00
Christopher Macrae
51ec3d866c Update README 2017-08-29 16:17:20 -03:00
Jordon Bedwell
fbcc9b9a48
📦 v0.6.0 2017-06-26 06:24:33 -05:00
Jordon Bedwell
94286c3317
Fix #8: Make sure we support Liquid 4. 2017-06-26 06:23:54 -05:00
Scott Gallant
4979b35fc4 Added setup instructions 2017-04-08 10:15:57 -03:00
Jordon Bedwell
d170b60841
Release v0.5.0. 2017-03-14 21:22:47 -05:00
Jordon Bedwell
c94954c525
Fix #4: Make sure we don't lead with _ 2017-03-14 15:47:04 -05:00
Jordon Bedwell
f4f7649ccf
💎 Release v0.4.0. 2017-02-13 09:46:35 -06:00
Jordon Bedwell
6145dc74e6
Use before_method instead of method_missing, drops don't like method_missing. 2017-02-13 09:45:25 -06:00
Jordon Bedwell
adaffc454b
Fix #5: Check for Class#data["ext"] before hitting Class#ext. 2017-02-13 09:45:09 -06:00
Jordon Bedwell
b699363013
💎 Release 0.3.0. 2017-01-24 20:39:50 -06:00
Jordon Bedwell
739ba03295
Fix #3: Use pages.docs.select instead of pages.select. 2016-12-17 22:31:15 -06:00
Jordon Bedwell
3e7d01c447
💎 Release v0.2.1 2016-11-23 12:45:08 -06:00
Jordon Bedwell
63977db5c1 Merge pull request #2 from forestryio/hash-not-object
fixed issue with trying to access hash as object
2016-11-22 18:50:14 -06:00
Jordan Patterson
40f0652f39
fixed issue with trying to access hash as object 2016-11-22 20:24:25 -04:00
Jordon Bedwell
6009087b44
💎 Release v0.2.0 2016-11-22 14:36:23 -06:00
Jordon Bedwell
05fcf28891
Guard against invalid menus and no _menus 2016-11-22 14:35:09 -06:00
Jordon Bedwell
02205eeb4a
💎 Release v0.1.0 2016-10-05 19:25:19 -05:00
volgorean
8ad3c3fe07 added collection menus and fixed data menu frontmatter = false 2016-10-05 15:23:09 -07:00
Jordon Bedwell
22d873d95e
Removing my Pry. 2016-10-05 15:03:26 -05:00
Jordon Bedwell
9af8cc15e2
Make sure the path is part of the identifier. 2016-10-05 15:00:53 -05:00
volgorean
0db6d7112c _frontmatter now set to relative path and fixed spelling error 2016-10-05 12:04:32 -07:00
Jordon Bedwell
0f08a5e7ca
💎 Release v0.0.5 2016-10-03 11:50:32 -05:00
Jordon Bedwell
c81b75c62b Merge pull request #1 from volgorean/patch-1
Fixed NameError, Util should be Utils
2016-10-03 11:49:20 -05:00
volgorean
4cf7b543fd Fixed NameError, Util should be Utils 2016-10-03 09:47:27 -07:00
Jordon Bedwell
54c6c337b4
💎 Release v0.0.4 2016-09-30 14:57:34 -05:00
Jordon Bedwell
ae18d0e77b
Add the ability to extract the raw menus. 2016-09-30 14:56:56 -05:00
Jordon Bedwell
a737321189
💎 Release v0.0.3 2016-09-24 09:13:47 -05:00
Jordon Bedwell
a1f3d1d5ec
Remove last reference. 2016-09-24 09:11:46 -05:00
Jordon Bedwell
d4cd98d253
Update the documentation. 2016-09-24 09:10:46 -05:00
Jordon Bedwell
4d9ea00fd8
Remove _data/menu.yml and add _frontmatter. 2016-09-24 09:08:36 -05:00
Jordon Bedwell
13a7d18f69
Explain identifiers. 2016-09-22 10:04:12 -05:00
Jordon Bedwell
7a0147163a
Add more examples. 2016-09-22 09:45:40 -05:00
Jordon Bedwell
adf2d56f4a
Cleanup the readme so it's easier to follow. 2016-09-22 09:35:08 -05:00
6 changed files with 310 additions and 127 deletions

View File

@ -12,14 +12,14 @@ Gem::Specification.new do |spec|
spec.description = "Menus (site navigation) for your Jekyll website"
spec.summary = "Menus (navigation) for your very own Jekyll website."
spec.files = %W(Gemfile) + Dir["lib/**/*"]
spec.required_ruby_version = ">= 2.1.0"
spec.required_ruby_version = ">= 2.4.0"
spec.email = ["jordon@envygeeks.io"]
spec.require_paths = ["lib"]
spec.name = "jekyll-menus"
spec.has_rdoc = false
spec.license = "MIT"
spec.add_runtime_dependency("jekyll", "~> 3.1")
spec.add_runtime_dependency("jekyll", ">= 3.6", "< 5.0" )
spec.add_development_dependency(
"rspec", ">= 3", "< 4"
)

250
README.md
View File

@ -1,92 +1,220 @@
# Jekyll Menus
Complex menus for Jekyll.
A robust, simple-to-use menu plugin for Jekyll that allows for infinitely nested menus.
## Installation
To install and use Jekyll Menus, you should have Ruby, and either [RubyGems](https://jekyllrb.com/docs/installation/#install-with-rubygems), or we recommend using [Bundler](https://bundler.io/#getting-started). Bundler is what Jekyll will prefer you to use by default if you `jekyll new`.
### Using Bundler
You can add our gem to the `jekyll_plugins` group in your `Gemfile`:
```ruby
group :jekyll_plugins do
gem "jekyll-menus"
end
```
And then install from shell.
```sh
bundle install
# --path vendor/bundle
```
***If you are using Jekyll Docker, you do not need to perform this step, Jekyll Docker will perform it on your behalf when you launch the image, you only need to perform this step if you are working directly on your system.***
### Using RubyGems
```sh
sudo gem install jekyll-menus
sudo gem update jekyll-menus
```
Once installed, add the Gem to your `_config.yml`:
```yaml
plugins:
- jekyll-menus
```
***Note in earlier versions of Jekyll, `plugins` should instead be `gems`***
## Usage
You can create `_data/menu.yml`, `_data/menus.yml`, or both, or add menu items
via your front-matter. Both are merged into the same menus so you can even
split off menus between the two, so that you can have menus that have
internal and external links! Just make sure the identifiers match.
Jekyll Menus allows you to create menus by attaching posts and pages to menus through their front matter, or by defining custom menu items via `_data/menus.yml`.
### Front-Matter Examples
#### String Key Menu Item
Jekyll Menus adds a new option to the site variable called `site.menus`, which can be looped over just like pages, posts, and other content:
```yml
```liquid
<ul>
{% for item in site.menus.header %}
<li class="menu-item-{{ loop.index }}">
<a href="{{ item.url }}" title="Go to {{ item.title }}">{{ item.title }}</a>
</li>
{% endfor %}
</ul>
```
## Menus via Front Matter
The easiest way to use Jekyll Menus is to start building menus using your existing posts and pages. This can be done by adding a `menus` variable to your front matter:
```markdown
---
menus: main
title: Homepage
menus: header
---
```
The above configuration will infer all data (url, title, identifier, weight)
from your page data, the default weight is "-1" and the identifier is made from
the pages slug, which Jekyll itself generates. It will also place the page
on the "main" menu on your behalf after inferring said data.
This will create the `header` menu with a single item, the homepage. The `url`, `title`, and `identifier` for the homepage menu item will be automatically generated from the pages title, file path, and permalink.
#### Array of String Key Menu Items
You can optionally set any of the available [menu item variables](#menu-items) yourself to customize the appearance and functionality of your menus. For example, to set a custom title and weight:
```yml
```markdown
---
title: Homepage
menus:
- header
- footer
header:
title: Home
weight: 1
---
```
The above configuration will infer all data (url, title, identifier, weight)
from your page data, the default weight is "-1" and the identifier is made from
the pages slug, which Jekyll itself generates. It will also place the page
on the "header", and "footer" menus after inferring said data.
## Custom Menu Items via `_data/menus.yml`
#### Hash with Key as Identifier
The other option for configuring menus is creating menus using `_data/menus.yml`. In this scenario, you can add custom menu items to external content, or site content that isnt handled by Jekyll.
```yml
In this file, you provide the menu key and an array of custom menu items. Custom menu items in the data file must have `url`, `title`, and `identifier` variable:
```markdown
---
header:
- url: /api
title: API Documentation
identifier: api
---
```
## Sub-menus
Jekyll Menus supports infinitely nested menu items using the `identifier` variable. Any menu item can be used as a parent menu by using its identifier as the menu.
For example, in `_data/menus.yml`:
```yaml
header:
- url: /api
title: API Documentation
identifier: api
```
In a content file called `/api-support.html`:
```markdown
---
title: Get API Support
menus: api
---
```
Which can then be used in your templates by looping over the menu items `children` variable:
```liquid
<ul>
{% for item in site.menus.header %}
<li class="menu-item-{{ loop.index }}">
<a href="{{ item.url }}" title="Go to {{ item.title }}">{{ item.title }}</a>
{% if item.children %}
<ul class="sub-menu">
{% for item in item.children %}
<li class="menu-item-{{ loop.index }}">
<a href="{{ item.url }}" title="Go to {{ item.title }}">{{ item.title }}</a>
</li>
{% endfor %}
</ul>
{% endif %}
</li>
{% endfor %}
</ul>
```
You can also do this [recursively using a re-usable include](#recursive-menus), allowing for easily managed infinitely nested menus.
## Variables
Jekyll Menus has the following variables:
### Menus
| Variable | Description |
|---|---|
| menu.menu | Returns a JSON object with all of the menus items. |
| menu.identifier | The unique identifier for the current menu, generated from the menu key. Allows for nested menu items. |
| menu.parent | The parent menu. Resolves to the site.menus object for top-level menus. |
### Menu Items
| Variable | Description |
|---|---|
| item.title | The display title of the menu item. Automatically set as the post or page title if no value is provided in front matter. |
| item.url | The URL the menu item links to. Automatically set to the post or page URL if no value is provided in front matter. |
| item.weight | Handles the order of menu items through a weighted system, starting with 1 being first. |
| item.identifier | The unique identifier for the current menu item. Allows for nested menu items. Automatically resolved to the pages file path and filename if not provided in front matter. |
| item.parent | The parent menu. |
| item.children | An array of any child menu items. Used to create sub-menus. |
## Custom Variables
Menu items also support custom variables, which you add to each menu item in the front matter or data file.
For example, adding a `pre` or `post` variable to add text or HTML to your menu items:
```markdown
---
title: Homepage
menus:
main:
url: "/custom-url"
header:
pre: <i class="icon-home"></i>
post: " · "
---
```
The above will place a menu on "main" and override the URL for you inferring
the rest of the data on your behalf. You can add multiple keys with hashes
if you wish to place the item on multiple menus, and you can override as much
as you wish at that time. ***Data is not inferred between items, so if you
override in one you must override in all, or the default values will be
used.***
## Recursive Menus
### `_data/menu.yml`, `_data/menus.yml`
If youre looking to build an infinitely nested menu (or a menu that is nested more than once up to a limit) then you should set up a reusable menu include that will handle this for you.
***All data within menu(s).yml must provide url, title, identifier, and
weight (actually weight is optional)***
In `_includes/menu.html` :
Menu items within data files must follow a key array format, or a key hash
format, we do not accept string formats because we do not infer data, it's
impossible to infer such data efficiently and the data files are mostly built
for you to add external links or links to other parts of your site that are
considered sub-domains. Examples:
```yml
main:
- title: Title
identifier: title
url: url
```liquid
{% if menu %}
<ul>
{% for item in menu %}
<li class="menu-item-{{ loop.index }}">
<a href="{{ item.url }}" title="Go to {{ item.title }}">{{ item.title }}</a>
{% if item.children %}
{% assign menu = item.children %}
{% include menu.html %}
{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
```
```yml
main:
title: Title
identifier: title
url: url
In `_layouts/default.html` (or any layout file):
```liquid
<html>
<body>
<header>
<nav>
{% assign menu = site.menus.header %}
{% include menus.html %}
</nav>
</header>
{{ content }}
</body>
</html>
```
***It should be noted that _data/menu.yml and _data/menus.yml are both read
and merged, so you can have one, or both... we won't judge you if you happen
to use both of these files at once, it's your choice!***
### Custom Menu Data
You can add any amount of custom data you wish to an item, we do not remove
data, and we do not block it, we will pass any data you wish to put into the
into the menu item. It is up to you what data you put there, we only check
that our own keys exist, and if they don't then we fail in certain scenarios.

View File

@ -13,23 +13,34 @@ module Jekyll
#
def to_liquid_drop
Drops::All.new(Utils.deep_merge(
_config_menus, _page_menus
def menus
Utils.deep_merge(_data_menus, Utils.deep_merge(
_page_menus, _collection_menus
))
end
#
def _config_menus
mns = [@site.data["menu"], @site.data["menus"]]
out = {}; mns.compact.each do |menus|
menus.each do |key, menu|
def to_liquid_drop
Drops::All.new(
menus
)
end
#
def _data_menus
out = {}
if @site.data["menus"] && @site.data["menus"].is_a?(Hash)
then @site.data["menus"].each do |key, menu|
if menu.is_a?(Hash) || menu.is_a?(Array)
(menu = [menu].flatten).each do |item|
_validate_config_menu_item(
item
)
item["_frontmatter"] = false
end
else
@ -38,9 +49,10 @@ module Jekyll
)
end
out = Utils.deep_merge(out, {
key => menu
})
merge = { key => menu }
out = Utils.deep_merge(
out, merge
)
end
end
@ -54,70 +66,93 @@ module Jekyll
@site.pages.select { |p| p.data.keys.grep(/menus?/).size > 0 }.each_with_object({}) do |page|
[page.data["menus"], page.data["menu"]].flatten.compact.map do |menu|
out = _front_matter_menu(menu, page, out)
end
end
out
end
#
def _collection_menus
out = {}
@site.collections.each do |collection, pages|
pages.docs.select { |p| p.data.keys.grep(/menus?/).size > 0 }.each_with_object({}) do |page|
[page.data["menus"], page.data["menu"]].flatten.compact.map do |menu|
out = _front_matter_menu(menu, page, out)
end
end
end
out
end
#
def _front_matter_menu(menu, page, out={})
# --
# menu: key
# menu:
# - key1
# - key2
# --
if menu.is_a?(Array) || menu.is_a?(String)
_simple_front_matter_menu(menu, **{
:mergeable => out, :page => page
})
#
elsif menu.is_a?(Hash)
menu.each do |key, item|
out[key] ||= []
# --
# menu: key
# menu:
# - key1
# - key2
# key: identifier
# --
if menu.is_a?(Array) || menu.is_a?(String)
_simple_front_matter_menu(menu, {
:mergeable => out, :page => page
if item.is_a?(String)
out[key] << _fill_front_matter_menu({ "identifier" => item }, **{
:page => page
})
#
# --
# menu:
# key:
# url: /url
# --
elsif menu.is_a?(Hash)
menu.each do |key, item|
out[key] ||= []
# --
# menu:
# key: identifier
# --
if item.is_a?(String)
out[key] << _fill_front_matter_menu({ "identifier" => item }, {
:page => page
})
# --
# menu:
# key:
# url: /url
# --
elsif item.is_a?(Hash)
out[key] << _fill_front_matter_menu(item, {
:page => page
})
# --
# menu:
# key:
# - url: /url
# --
else
_throw_invalid_menu_entry(
item
)
end
end
elsif item.is_a?(Hash)
out[key] << _fill_front_matter_menu(item, **{
:page => page
})
# --
# menu:
# key: 3
# key:
# - url: /url
# --
else
_throw_invalid_menu_entry(
menu
item
)
end
end
# --
# menu:
# key: 3
# --
else
_throw_invalid_menu_entry(
menu
)
end
out
@ -143,7 +178,7 @@ module Jekyll
else
mergeable[menu] ||= []
mergeable[menu] << _fill_front_matter_menu(nil, {
mergeable[menu] << _fill_front_matter_menu(nil, **{
:page => page
})
end
@ -157,14 +192,26 @@ module Jekyll
val ||= {}
val["url"] ||= page.url
val["identifier"] ||= slug(page)
val["_frontmatter"] = page.relative_path # `page.url` can be changed with permalink frontmatter
val["title"] ||= page.data["title"]
val["identifier"] ||= File.basename(page.name, page.ext)
val["weight"] ||= -1
val
end
#
private
def slug(page)
ext = page.data["ext"] || page.ext
out = File.join(File.dirname(page.path), File.basename(page.path, ext))
out.tr("^a-z0-9-_\\/", "").gsub(/\/|\-+/, "_").gsub(
/^_+/, ""
)
end
#
private
def _validate_config_menu_item(item)
if !item.is_a?(Hash) || !item.values_at("url", "title", "identifier").compact.size == 3

View File

@ -56,16 +56,15 @@ module Jekyll
#
def method_missing(method, *args)
if args.size == 0 && @item.has_key?(method.to_s)
def before_method(method)
if @item.has_key?(method.to_s)
return @item[
method.to_s
]
else
super
end
end
alias_method :liquid_method_missing, :before_method
end
end
end

View File

@ -4,6 +4,6 @@
module Jekyll
class Menus
VERSION = "0.0.2"
VERSION = "0.6.1"
end
end

View File

@ -0,0 +1,9 @@
---
title: Array of Strings
layout: default
menu:
- header
- footer
---
A Page