Skip to content

Commit

Permalink
Merge pull request #2 from teppokoivula/dev
Browse files Browse the repository at this point in the history
0.10.0
  • Loading branch information
teppokoivula authored Sep 5, 2021
2 parents 76373aa + b7d10b7 commit 67cbc53
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 74 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.9.0] - 2021-06-09
## [0.10.0] - 2021-09-02

### Added
- Include level by default in the 'item' template.

## [0.9.0] - 2021-06-09

### Added
- New hookable method getSelector().

## [0.8.2] - 2020-11-30
Expand Down
2 changes: 1 addition & 1 deletion MarkupMenu.info.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"title": "MarkupMenu",
"summary": "MarkupMenu is a module for generating menu markup.",
"version": "0.9.0",
"version": "0.10.0",
"author": "Teppo Koivula",
"href": "https://github.com/teppokoivula/MarkupMenu",
"requires": [
Expand Down
49 changes: 21 additions & 28 deletions MarkupMenu.module.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* MarkupMenu is a module for generating menu markup. See README.md for more details.
* Some ideas and code in this module are based on the Markup Simple Navigation module.
*
* @version 0.9.0
* @version 0.10.0
* @author Teppo Koivula <[email protected]>
* @license Mozilla Public License v2.0 http://mozilla.org/MPL/2.0/
*/
Expand All @@ -27,8 +27,8 @@ class MarkupMenu extends WireData implements Module {
'nav' => '<nav class="{classes}">%s</nav>',
'list' => '<ul class="{classes} {class}--level-{level}">%s</ul>',
'list_item' => '<li class="{classes} {class}--level-{level}">%s</li>',
'item' => '<a href="{item.url}" class="{classes}">{item.title}</a>',
'item_current' => '<span class="{classes}">{item.title}</span>',
'item' => '<a href="{item.url}" class="{classes} {class}--level-{level}">{item.title}</a>',
'item_current' => '<span class="{classes} {class}--level-{level}">{item.title}</span>',
],
'include' => [
'selector' => null,
Expand Down Expand Up @@ -122,11 +122,11 @@ protected function renderTree(array $options = [], Page $root = null, PageArray
];

// generate list markup
$out = $this->applyTemplate('list', $out, $placeholders, $options);
$out = $this->applyTemplate('list', $placeholders, $options, null, $out);

// generate nav markup
if ($level === 1) {
$out = $this->applyTemplate('nav', $out, $placeholders, $options);
$out = $this->applyTemplate('nav', $placeholders, $options, null, $out);
}

}
Expand Down Expand Up @@ -219,22 +219,15 @@ protected function ___renderTreeItem(array $options = [], Page $item, Page $root

// generate markup for menu item
$item_template_name = 'item' . ($item_is_current ? '_current' : '');
$item_template = $this->getTemplate($item_template_name, $item, $options);
$item_placeholders = $placeholders;
$item_placeholders['classes'] = $this->parseClassesString($item_placeholders, $options, $item_template_name);
$item_markup = wirePopulateStringTags(
$item_template,
new MarkupMenuData($item_placeholders),
$options['placeholder_options']
);
$item_markup = $this->applyTemplate($item_template_name, $placeholders, $options, $item);

// generate markup for menu item children
if ($with_children) {
$item_markup .= $this->renderTree($options, $item, null, $level + 1);
}

// generate markup for current list item
$out .= $this->applyTemplate('list_item', $item_markup, $placeholders, $options, $item);
$out .= $this->applyTemplate('list_item', $placeholders, $options, $item, $item_markup);

return $out;
}
Expand All @@ -259,7 +252,7 @@ protected function ___getSelector(?Page $item = null, string $context, array $op
* @return null|Page Page object or null
*/
protected function getPage($source = null, $default = null): ?Page {

$page = null;

if ($source instanceof Page) {
Expand All @@ -283,39 +276,39 @@ protected function getPage($source = null, $default = null): ?Page {
* @param array $options An array of options
* @return string Template
*/
protected function ___getTemplate($template_name, Page $item = null, array $options = []): string {
protected function ___getTemplate($template_name, ?Page $item = null, array $options = []): string {
return $options['templates'][$template_name];
}

/**
* Apply a template to content string
*
* @param string $template_name Name of the template
* @param string $content Content to be wrapped in template
* @param array $placeholders Array of placeholders for string replacements
* @param array $options An array of options
* @param Page|null $item Item being rendered
* @param string|null $content Content to be wrapped in template
* @return string Content either wrapped in template, or as-is if no template was defined
*/
protected function applyTemplate(string $template_name, string $content, array $placeholders, array $options, Page $item = null): string {
protected function applyTemplate(string $template_name, array $placeholders, array $options, ?Page $item = null, ?string $content = null): string {

$out = '';

$template = $this->getTemplate($template_name, $item, $options);
if (!empty($template)) {
$placeholders['class'] = $placeholders['classes'][$template_name] ?? $options['classes'][$template_name] ?? null;
$placeholders['classes'] = $this->parseClassesString($placeholders, $options, $template_name);
$out = sprintf(
wirePopulateStringTags(
$template,
new MarkupMenuData(array_merge(
$placeholders,
$options['placeholders']
)),
$options['placeholder_options']
),
$content
$out = wirePopulateStringTags(
$template,
new MarkupMenuData(array_merge(
$placeholders,
$options['placeholders']
)),
$options['placeholder_options']
);
if ($content !== null) {
$out = sprintf($out, $content);
}
}

return $out;
Expand Down
94 changes: 50 additions & 44 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
MarkupMenu ProcessWire module
-----------------------------

MarkupMenu is a markup module for generating menu trees. When provided a root page as a starting point,
it generates a navigation tree (by default as a HTML `<ul>` element wrapped by a `<nav>` element) from
that point onwards. If you've also provided it with current (active) page, the menu will be rendered
accordingly.
MarkupMenu is a ProcessWire module for generating markup for navigation menus. When provided a root page as a starting
point and (optional, but recommended) the current (active) page, it generates the markup for a navigation menu as an
unordered list `<ul>` wrapped with a `<nav>` element based on said arguments.

MarkupMenu provides a number of configurable options, including template strings used for various menu items (such as
the list and nav element mentioned above), as well as hookable methods for those who need full control over how their
menus are laid out.

## Usage

As a markup module, MarkupMenu is intended for front-end use, but you can of course use it in a module
as well. Typically you'll only need the render() method, which takes an array of options as its only
argument:
MarkupMenu is intended for front-end use, but you can of course use it in a module as well. Typically you'll only need
the render() method, which takes an array of options as its only argument:

```
echo $modules->get('MarkupMenu')->render([
Expand All @@ -19,20 +21,21 @@ echo $modules->get('MarkupMenu')->render([
]);
```

Note: if you omit root_page, site root page is used by default – unless you've specified the menu_items
option instead, in which case a root page is not necessary. If you omit current_page, the menu will be
rendered, but current (active) page can't be highlighted.
Note: if you omit the root_page option, site root page is used by default – unless you've specified the menu_items
option, in which case a root page is not necessary at all. If you omit current_page, the menu will be rendered, but
current (active) page can't be highlighted etc.

## Options

Below you'll find all the available options and their default values. You can override these defaults
with the array you pass to the render method, or you can specify an array of site-wide custom options
via site config setting `$config->MarkupMenu`.
Below you'll find all the available options and their default values. You can override these defaults with the array
you pass to the render method, or you can specify an array of site-wide custom options via the site config setting
`$config->MarkupMenu`:

```
[
// 'root_page' is the starting point for the menu. This is optional if you specify the 'menu_items'
// option instead, but leaving *both* empty will make MarkupMenu::render() return an empty string.
$config->MarkupMenu = [
// 'root_page' is the starting point for the menu. This is optional if you specify the 'menu_items' option instead,
// but leaving *both* empty will make MarkupMenu::render() return an empty string.
'root_page' => null,
// 'menu_items' is an optional, prepopulated PageArray of first level menu items.
Expand All @@ -41,15 +44,15 @@ via site config setting `$config->MarkupMenu`.
// 'current' page is the current or active menu page.
'current_page' => null,
// 'templates' are used for rendering individual parts of the menu:
// 'templates' define the template strings used for rendering individual parts of the menu:
//
// - the semantic <nav> element that acts as a wrapper for the menu ('nav'),
// - the lists wrapping the menu items and the subtrees within it ('list'),
// - the list items wrapping menu branches ('list_item'),
// - the items (links) in the menu ('item')
// - the active item ('item_current')
//
// special placeholder values populated by default:
// special placeholder values supported by default and populated while rendering the menu:
//
// - {classes}: all default classes applied, including template class, current class, etc.
// - {class}: the template class only, mostly useful for adding a prefix to other classes
Expand All @@ -59,48 +62,48 @@ via site config setting `$config->MarkupMenu`.
'nav' => '<nav class="{classes}">%s</nav>',
'list' => '<ul class="{classes} {class}--level-{level}">%s</ul>',
'list_item' => '<li class="{classes} {class}--level-{level}">%s</li>',
'item' => '<a href="{item.url}" class="{classes}">{item.title}</a>',
'item_current' => '<span class="{classes}">{item.title}</span>',
'item' => '<a href="{item.url}" class="{classes} {class}--level-{level}">{item.title}</a>',
'item_current' => '<span class="{classes} {class}--level-{level}">{item.title}</span>',
],
// 'include' defines the pages included in the menu: you can provide 'selector' string to choose
// suitable pages, and use a boolean toggle ('root_page') to choose whether the root page itself
// should be included in the menu.
// 'include' defines the pages included in the menu: you can provide 'selector' string to choose suitable pages,
// and use a boolean toggle ('root_page') to choose whether the root page itself should be included in the menu.
'include' => [
'selector' => null,
'root_page' => false,
],
// 'exclude' rules are the opposite of the include rules, and allow you to define the pages not
// included in the menu: pages matching a selector string, non-listable pages ('listable' value
// of false means that non-listable pages are excluded), and pages that would exceed a maximum
// level or depth ('level_greater_than').
// 'exclude' rules are the opposite of the include rules, and allow you to define the pages not included in the
// menu: pages matching a selector string, non-listable pages ('listable' value of false means that non-listable
// pages are excluded), and pages that would exceed a maximum level or depth ('level_greater_than').
//
// **NOTE**: exclude rules are applied *after* initial query, which makes them less performant than include rules;
// in particular one should always prefer the selector in the include rules over the one in the exclude rules.
'exclude' => [
'selector' => null,
'listable' => false,
'level_greater_than' => null,
],
// 'collapsed', in the lack of a better name, defines whether your menu should only be rendered
// up current (active) page, or first level if no current page was provided.
// 'collapsed', in the lack of a better name, defines whether your menu should only be rendered up current (active)
// page, or first level if no current page was provided.
'collapsed' => true,
// 'flat_root' is only useful if you've chosen to include the root page in the menu: this option
// puts the root page at the same level as your other first level pages – typically you'd want
// this, so that your home page shows up at the same level as the first level below it.
// 'flat_root' is only useful if you've chosen to include the root page in the menu: this option puts the root page
// at the same level as your other first level pages – typically you'd want this, so that your home page shows up
// at the same level as the first level below it.
'flat_root' => true,
// 'placeholder_options' is an optional array of options that will be passed to WireTextTools or
// the wirePopulateStringTags() function, used for tag replacements in templates defined via the
// 'templates' option.
// 'placeholder_options' is an array of options that will be passed to WireTextTools or wirePopulateStringTags(),
// used for tag replacements in templates defined via the 'templates' option.
'placeholder_options' => [],
// 'placeholders' can be used to provide additional custom values for string replacements used
// within the templates defined via the 'templates' option.
// 'placeholders' can be used to provide additional custom values for string replacements used within the template
// strings defined via the 'templates' option.
'placeholders' => [],
// 'classes' can be used to override default class names added to items when the {classes} tag
// is used in a template defined via the 'templates' option.
// 'classes' can be used to override default class names added to items when the {classes} tag is used in template
// strings defined via the 'templates' option.
'classes' => [
// 'page_id' => '&--page-id-', // note: page_id is disabled by default!
'nav' => 'menu',
Expand All @@ -120,14 +123,17 @@ via site config setting `$config->MarkupMenu`.
- ProcessWire >= 3.0.112
- PHP >= 7.1.0

If you're working on an earlier version of ProcessWire or PHP, I'd highly recommend checking out the
MarkupSimpleNavigation module instead: https://github.com/somatonic/MarkupSimpleNavigation.
If you're working on an earlier version of ProcessWire or PHP, I'd highly recommend checking out MarkupSimpleNavigation
module instead: https://github.com/somatonic/MarkupSimpleNavigation.

## Installing

This module can be installed just like any other ProcessWire module, by downloading or cloning the
MarkupMenu directory into your /site/modules/ directory. Alternatively you can install MarkupMenu
through Composer by executing `composer require teppokoivula/markup-menu` in your site directory.
This module can be installed just like any other ProcessWire module, by downloading or cloning the MarkupMenu directory
into your /site/modules/ directory. Alternatively you can install the module via Composer:

```
composer require teppokoivula/markup-menu
```

## License

Expand Down

0 comments on commit 67cbc53

Please sign in to comment.