はじまりの大地
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
namespace dokuwiki\Menu;
|
||||
|
||||
use dokuwiki\Menu\Item\AbstractItem;
|
||||
|
||||
/**
|
||||
* Class AbstractMenu
|
||||
*
|
||||
* Basic menu functionality. A menu defines a list of AbstractItem that shall be shown.
|
||||
* It contains convenience functions to display the menu in HTML, but template authors can also
|
||||
* just accesst the items via getItems() and create the HTML as however they see fit.
|
||||
*/
|
||||
abstract class AbstractMenu implements MenuInterface {
|
||||
|
||||
/** @var string[] list of Item classes to load */
|
||||
protected $types = array();
|
||||
|
||||
/** @var int the context this menu is used in */
|
||||
protected $context = AbstractItem::CTX_DESKTOP;
|
||||
|
||||
/** @var string view identifier to be set in the event */
|
||||
protected $view = '';
|
||||
|
||||
/**
|
||||
* AbstractMenu constructor.
|
||||
*
|
||||
* @param int $context the context this menu is used in
|
||||
*/
|
||||
public function __construct($context = AbstractItem::CTX_DESKTOP) {
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of action items in this menu
|
||||
*
|
||||
* @return AbstractItem[]
|
||||
* @triggers MENU_ITEMS_ASSEMBLY
|
||||
*/
|
||||
public function getItems() {
|
||||
$data = array(
|
||||
'view' => $this->view,
|
||||
'items' => array(),
|
||||
);
|
||||
trigger_event('MENU_ITEMS_ASSEMBLY', $data, array($this, 'loadItems'));
|
||||
return $data['items'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Default action for the MENU_ITEMS_ASSEMBLY event
|
||||
*
|
||||
* @see getItems()
|
||||
* @param array $data The plugin data
|
||||
*/
|
||||
public function loadItems(&$data) {
|
||||
foreach($this->types as $class) {
|
||||
try {
|
||||
$class = "\\dokuwiki\\Menu\\Item\\$class";
|
||||
/** @var AbstractItem $item */
|
||||
$item = new $class();
|
||||
if(!$item->visibleInContext($this->context)) continue;
|
||||
$data['items'][] = $item;
|
||||
} catch(\RuntimeException $ignored) {
|
||||
// item not available
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate HTML list items for this menu
|
||||
*
|
||||
* This is a convenience method for template authors. If you need more fine control over the
|
||||
* output, use getItems() and build the HTML yourself
|
||||
*
|
||||
* @param string|false $classprefix create a class from type with this prefix, false for no class
|
||||
* @param bool $svg add the SVG link
|
||||
* @return string
|
||||
*/
|
||||
public function getListItems($classprefix = '', $svg = true) {
|
||||
$html = '';
|
||||
foreach($this->getItems() as $item) {
|
||||
if($classprefix !== false) {
|
||||
$class = ' class="' . $classprefix . $item->getType() . '"';
|
||||
} else {
|
||||
$class = '';
|
||||
}
|
||||
|
||||
$html .= "<li$class>";
|
||||
$html .= $item->asHtmlLink(false, $svg);
|
||||
$html .= '</li>';
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace dokuwiki\Menu;
|
||||
|
||||
/**
|
||||
* Class DetailMenu
|
||||
*
|
||||
* This menu offers options on an image detail view. It usually displayed similar to
|
||||
* the PageMenu.
|
||||
*/
|
||||
class DetailMenu extends AbstractMenu {
|
||||
|
||||
protected $view = 'detail';
|
||||
|
||||
protected $types = array(
|
||||
'MediaManager',
|
||||
'ImgBackto',
|
||||
'Top',
|
||||
);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
<?php
|
||||
|
||||
namespace dokuwiki\Menu\Item;
|
||||
|
||||
/**
|
||||
* Class AbstractItem
|
||||
*
|
||||
* This class defines a single Item to be displayed in one of DokuWiki's menus. Plugins
|
||||
* can extend those menus through action plugins and add their own instances of this class,
|
||||
* overwriting some of its properties.
|
||||
*
|
||||
* Items may be shown multiple times in different contexts. Eg. for the default template
|
||||
* all menus are shown in a Dropdown list on mobile, but are split into several places on
|
||||
* desktop. The item's $context property can be used to hide the item depending on the current
|
||||
* context.
|
||||
*
|
||||
* Children usually just need to overwrite the different properties, but for complex things
|
||||
* the accessors may be overwritten instead.
|
||||
*/
|
||||
abstract class AbstractItem {
|
||||
|
||||
/** menu item is to be shown on desktop screens only */
|
||||
const CTX_DESKTOP = 1;
|
||||
/** menu item is to be shown on mobile screens only */
|
||||
const CTX_MOBILE = 2;
|
||||
/** menu item is to be shown in all contexts */
|
||||
const CTX_ALL = 3;
|
||||
|
||||
/** @var string name of the action, usually the lowercase class name */
|
||||
protected $type = '';
|
||||
/** @var string optional keyboard shortcut */
|
||||
protected $accesskey = '';
|
||||
/** @var string the page id this action links to */
|
||||
protected $id = '';
|
||||
/** @var string the method to be used when this action is used in a form */
|
||||
protected $method = 'get';
|
||||
/** @var array parameters for the action (should contain the do parameter) */
|
||||
protected $params = array();
|
||||
/** @var bool when true, a rel=nofollow should be used */
|
||||
protected $nofollow = true;
|
||||
/** @var string this item's label may contain a placeholder, which is replaced with this */
|
||||
protected $replacement = '';
|
||||
/** @var string the full path to the SVG icon of this menu item */
|
||||
protected $svg = DOKU_INC_COMPAT . 'lib/images/menu/00-default_checkbox-blank-circle-outline.svg';
|
||||
/** @var string can be set to overwrite the default lookup in $lang.btn_* */
|
||||
protected $label = '';
|
||||
/** @var string the tooltip title, defaults to $label */
|
||||
protected $title = '';
|
||||
/** @var int the context this titme is shown in */
|
||||
protected $context = self::CTX_ALL;
|
||||
|
||||
/**
|
||||
* AbstractItem constructor.
|
||||
*
|
||||
* Sets the dynamic properties
|
||||
*
|
||||
* Children should always call the parent constructor!
|
||||
*
|
||||
* @throws \RuntimeException when the action is disabled
|
||||
*/
|
||||
public function __construct() {
|
||||
global $ID;
|
||||
$this->id = $ID;
|
||||
$this->type = $this->getType();
|
||||
$this->params['do'] = $this->type;
|
||||
|
||||
if(!actionOK($this->type)) throw new \RuntimeException("action disabled: {$this->type}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return this item's label
|
||||
*
|
||||
* When the label property was set, it is simply returned. Otherwise, the action's type
|
||||
* is used to look up the translation in the main language file and, if used, the replacement
|
||||
* is applied.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLabel() {
|
||||
if($this->label !== '') return $this->label;
|
||||
|
||||
/** @var array $lang */
|
||||
global $lang;
|
||||
$label = $lang['btn_' . $this->type];
|
||||
if(strpos($label, '%s')) {
|
||||
$label = sprintf($label, $this->replacement);
|
||||
}
|
||||
if($label === '') $label = '[' . $this->type . ']';
|
||||
return $label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return this item's title
|
||||
*
|
||||
* This title should be used to display a tooltip (using the HTML title attribute). If
|
||||
* a title property was not explicitly set, the label will be returned.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTitle() {
|
||||
if($this->title === '') return $this->getLabel();
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the link this item links to
|
||||
*
|
||||
* Basically runs wl() on $id and $params. However if the ID is a hash it is used directly
|
||||
* as the link
|
||||
*
|
||||
* Please note that the generated URL is *not* XML escaped.
|
||||
*
|
||||
* @see wl()
|
||||
* @return string
|
||||
*/
|
||||
public function getLink() {
|
||||
if($this->id && $this->id[0] == '#') {
|
||||
return $this->id;
|
||||
} else {
|
||||
return wl($this->id, $this->params, false, '&');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to get the attributes for constructing an <a> element
|
||||
*
|
||||
* @see buildAttributes()
|
||||
* @param string|false $classprefix create a class from type with this prefix, false for no class
|
||||
* @return array
|
||||
*/
|
||||
public function getLinkAttributes($classprefix = 'menuitem ') {
|
||||
$attr = array(
|
||||
'href' => $this->getLink(),
|
||||
'title' => $this->getTitle(),
|
||||
);
|
||||
if($this->isNofollow()) $attr['rel'] = 'nofollow';
|
||||
if($this->getAccesskey()) {
|
||||
$attr['accesskey'] = $this->getAccesskey();
|
||||
$attr['title'] .= ' [' . $this->getAccesskey() . ']';
|
||||
}
|
||||
if($classprefix !== false) $attr['class'] = $classprefix . $this->getType();
|
||||
|
||||
return $attr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to create a full <a> element
|
||||
*
|
||||
* Wraps around the label and SVG image
|
||||
*
|
||||
* @param string|false $classprefix create a class from type with this prefix, false for no class
|
||||
* @param bool $svg add SVG icon to the link
|
||||
* @return string
|
||||
*/
|
||||
public function asHtmlLink($classprefix = 'menuitem ', $svg = true) {
|
||||
$attr = buildAttributes($this->getLinkAttributes($classprefix));
|
||||
$html = "<a $attr>";
|
||||
if($svg) {
|
||||
$html .= '<span>' . hsc($this->getLabel()) . '</span>';
|
||||
$html .= inlineSVG($this->getSvg());
|
||||
} else {
|
||||
$html .= hsc($this->getLabel());
|
||||
}
|
||||
$html .= "</a>";
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to create a <button> element inside it's own form element
|
||||
*
|
||||
* Uses html_btn()
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function asHtmlButton() {
|
||||
return html_btn(
|
||||
$this->getType(),
|
||||
$this->id,
|
||||
$this->getAccesskey(),
|
||||
$this->getParams(),
|
||||
$this->method,
|
||||
$this->getTitle(),
|
||||
$this->getLabel(),
|
||||
$this->getSvg()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Should this item be shown in the given context
|
||||
*
|
||||
* @param int $ctx the current context
|
||||
* @return bool
|
||||
*/
|
||||
public function visibleInContext($ctx) {
|
||||
return (bool) ($ctx & $this->context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the name of this item
|
||||
*/
|
||||
public function getType() {
|
||||
if($this->type === '') {
|
||||
$this->type = strtolower(substr(strrchr(get_class($this), '\\'), 1));
|
||||
}
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAccesskey() {
|
||||
return $this->accesskey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getParams() {
|
||||
return $this->params;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isNofollow() {
|
||||
return $this->nofollow;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getSvg() {
|
||||
return $this->svg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return this Item's settings as an array as used in tpl_get_action()
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getLegacyData() {
|
||||
return array(
|
||||
'accesskey' => $this->accesskey ?: null,
|
||||
'type' => $this->type,
|
||||
'id' => $this->id,
|
||||
'method' => $this->method,
|
||||
'params' => $this->params,
|
||||
'nofollow' => $this->nofollow,
|
||||
'replacement' => $this->replacement
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace dokuwiki\Menu\Item;
|
||||
|
||||
/**
|
||||
* Class Admin
|
||||
*
|
||||
* Opens the Admin screen. Only shown to managers or above
|
||||
*/
|
||||
class Admin extends AbstractItem {
|
||||
|
||||
/** @inheritdoc */
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
|
||||
$this->svg = DOKU_INC_COMPAT . 'lib/images/menu/settings.svg';
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
public function visibleInContext($ctx)
|
||||
{
|
||||
global $INFO;
|
||||
if(!$INFO['ismanager']) return false;
|
||||
|
||||
return parent::visibleInContext($ctx);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace dokuwiki\Menu\Item;
|
||||
|
||||
/**
|
||||
* Class Back
|
||||
*
|
||||
* Navigates back up one namepspace. This is currently not used in any menu. Templates
|
||||
* would need to add this item manually.
|
||||
*/
|
||||
class Back extends AbstractItem {
|
||||
|
||||
/** @inheritdoc */
|
||||
public function __construct() {
|
||||
global $ID;
|
||||
parent::__construct();
|
||||
|
||||
$parent = tpl_getparent($ID);
|
||||
if(!$parent) {
|
||||
throw new \RuntimeException("No parent for back action");
|
||||
}
|
||||
|
||||
$this->id = $parent;
|
||||
$this->params = array('do' => '');
|
||||
$this->accesskey = 'b';
|
||||
$this->svg = DOKU_INC_COMPAT . 'lib/images/menu/12-back_arrow-left.svg';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace dokuwiki\Menu\Item;
|
||||
|
||||
/**
|
||||
* Class Backlink
|
||||
*
|
||||
* Shows the backlinks for the current page
|
||||
*/
|
||||
class Backlink extends AbstractItem {
|
||||
|
||||
/** @inheritdoc */
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->svg = DOKU_INC_COMPAT . 'lib/images/menu/08-backlink_link-variant.svg';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace dokuwiki\Menu\Item;
|
||||
|
||||
/**
|
||||
* Class Edit
|
||||
*
|
||||
* Most complex item. Shows the edit button but mutates to show, draft and create based on
|
||||
* current state.
|
||||
*/
|
||||
class Edit extends AbstractItem {
|
||||
|
||||
/** @inheritdoc */
|
||||
public function __construct() {
|
||||
global $ACT;
|
||||
global $INFO;
|
||||
global $REV;
|
||||
|
||||
parent::__construct();
|
||||
|
||||
if($ACT === 'show') {
|
||||
$this->method = 'post';
|
||||
if($INFO['writable']) {
|
||||
$this->accesskey = 'e';
|
||||
if(!empty($INFO['draft'])) {
|
||||
$this->type = 'draft';
|
||||
$this->params['do'] = 'draft';
|
||||
} else {
|
||||
$this->params['rev'] = $REV;
|
||||
if(!$INFO['exists']) {
|
||||
$this->type = 'create';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(!actionOK("source")) throw new \RuntimeException("action disabled: source");
|
||||
$params['rev'] = $REV;
|
||||
$this->type = 'source';
|
||||
$this->accesskey = 'v';
|
||||
}
|
||||
} else {
|
||||
$this->params = array('do' => '');
|
||||
$this->type = 'show';
|
||||
$this->accesskey = 'v';
|
||||
}
|
||||
|
||||
$this->setIcon();
|
||||
}
|
||||
|
||||
/**
|
||||
* change the icon according to what type the edit button has
|
||||
*/
|
||||
protected function setIcon() {
|
||||
$icons = array(
|
||||
'edit' => '01-edit_pencil.svg',
|
||||
'create' => '02-create_pencil.svg',
|
||||
'draft' => '03-draft_android-studio.svg',
|
||||
'show' => '04-show_file-document.svg',
|
||||
'source' => '05-source_file-xml.svg',
|
||||
);
|
||||
if(isset($icons[$this->type])) {
|
||||
$this->svg = DOKU_INC_COMPAT . 'lib/images/menu/' . $icons[$this->type];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace dokuwiki\Menu\Item;
|
||||
|
||||
/**
|
||||
* Class ImgBackto
|
||||
*
|
||||
* Links back to the originating page from a detail image view
|
||||
*/
|
||||
class ImgBackto extends AbstractItem {
|
||||
|
||||
/** @inheritdoc */
|
||||
public function __construct() {
|
||||
global $ID;
|
||||
parent::__construct();
|
||||
|
||||
$this->svg = DOKU_INC_COMPAT . 'lib/images/menu/12-back_arrow-left.svg';
|
||||
$this->type = 'img_backto';
|
||||
$this->params = array();
|
||||
$this->accesskey = 'b';
|
||||
$this->replacement = $ID;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace dokuwiki\Menu\Item;
|
||||
|
||||
/**
|
||||
* Class Index
|
||||
*
|
||||
* Shows the sitemap
|
||||
*/
|
||||
class Index extends AbstractItem {
|
||||
|
||||
/** @inheritdoc */
|
||||
public function __construct() {
|
||||
global $conf;
|
||||
global $ID;
|
||||
parent::__construct();
|
||||
|
||||
$this->accesskey = 'x';
|
||||
$this->svg = DOKU_INC_COMPAT . 'lib/images/menu/file-tree.svg';
|
||||
|
||||
// allow searchbots to get to the sitemap from the homepage (when dokuwiki isn't providing a sitemap.xml)
|
||||
if($conf['start'] == $ID && !$conf['sitemap']) {
|
||||
$this->nofollow = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace dokuwiki\Menu\Item;
|
||||
|
||||
/**
|
||||
* Class Login
|
||||
*
|
||||
* Show a login or logout item, based on the current state
|
||||
*/
|
||||
class Login extends AbstractItem {
|
||||
|
||||
/** @inheritdoc */
|
||||
public function __construct() {
|
||||
global $INPUT;
|
||||
parent::__construct();
|
||||
|
||||
$this->svg = DOKU_INC_COMPAT . 'lib/images/menu/login.svg';
|
||||
$this->params['sectok'] = getSecurityToken();
|
||||
if($INPUT->server->has('REMOTE_USER')) {
|
||||
if(!actionOK('logout')) {
|
||||
throw new \RuntimeException("logout disabled");
|
||||
}
|
||||
$this->params['do'] = 'logout';
|
||||
$this->type = 'logout';
|
||||
$this->svg = DOKU_INC_COMPAT . 'lib/images/menu/logout.svg';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace dokuwiki\Menu\Item;
|
||||
|
||||
/**
|
||||
* Class Media
|
||||
*
|
||||
* Opens the media manager
|
||||
*/
|
||||
class Media extends AbstractItem {
|
||||
|
||||
/** @inheritdoc */
|
||||
public function __construct() {
|
||||
global $ID;
|
||||
parent::__construct();
|
||||
|
||||
$this->svg = DOKU_INC_COMPAT . 'lib/images/menu/folder-multiple-image.svg';
|
||||
$this->params['ns'] = getNS($ID);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace dokuwiki\Menu\Item;
|
||||
|
||||
/**
|
||||
* Class MediaManager
|
||||
*
|
||||
* Opens the current image in the media manager. Used on image detail view.
|
||||
*/
|
||||
class MediaManager extends AbstractItem {
|
||||
|
||||
/** @inheritdoc */
|
||||
public function __construct() {
|
||||
global $IMG;
|
||||
parent::__construct();
|
||||
|
||||
$imgNS = getNS($IMG);
|
||||
$authNS = auth_quickaclcheck("$imgNS:*");
|
||||
if($authNS < AUTH_UPLOAD) {
|
||||
throw new \RuntimeException("media manager link only with upload permissions");
|
||||
}
|
||||
|
||||
$this->svg = DOKU_INC_COMPAT . 'lib/images/menu/11-mediamanager_folder-image.svg';
|
||||
$this->type = 'mediaManager';
|
||||
$this->params = array(
|
||||
'ns' => $imgNS,
|
||||
'image' => $IMG,
|
||||
'do' => 'media'
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace dokuwiki\Menu\Item;
|
||||
|
||||
/**
|
||||
* Class Profile
|
||||
*
|
||||
* Open the user's profile
|
||||
*/
|
||||
class Profile extends AbstractItem {
|
||||
|
||||
/** @inheritdoc */
|
||||
public function __construct() {
|
||||
global $INPUT;
|
||||
parent::__construct();
|
||||
|
||||
if(!$INPUT->server->str('REMOTE_USER')) {
|
||||
throw new \RuntimeException("profile is only for logged in users");
|
||||
}
|
||||
|
||||
$this->svg = DOKU_INC_COMPAT . 'lib/images/menu/account-card-details.svg';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace dokuwiki\Menu\Item;
|
||||
|
||||
/**
|
||||
* Class Recent
|
||||
*
|
||||
* Show the site wide recent changes
|
||||
*/
|
||||
class Recent extends AbstractItem {
|
||||
|
||||
/** @inheritdoc */
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
|
||||
$this->accesskey = 'r';
|
||||
$this->svg = DOKU_INC_COMPAT . 'lib/images/menu/calendar-clock.svg';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace dokuwiki\Menu\Item;
|
||||
|
||||
/**
|
||||
* Class Register
|
||||
*
|
||||
* Open the view to register a new account
|
||||
*/
|
||||
class Register extends AbstractItem {
|
||||
|
||||
/** @inheritdoc */
|
||||
public function __construct() {
|
||||
global $INPUT;
|
||||
parent::__construct();
|
||||
|
||||
if($INPUT->server->str('REMOTE_USER')) {
|
||||
throw new \RuntimeException("no register when already logged in");
|
||||
}
|
||||
|
||||
$this->svg = DOKU_INC_COMPAT . 'lib/images/menu/account-plus.svg';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace dokuwiki\Menu\Item;
|
||||
|
||||
/**
|
||||
* Class Resendpwd
|
||||
*
|
||||
* Access the "forgot password" dialog
|
||||
*/
|
||||
class Resendpwd extends AbstractItem {
|
||||
|
||||
/** @inheritdoc */
|
||||
public function __construct() {
|
||||
global $INPUT;
|
||||
parent::__construct();
|
||||
|
||||
if($INPUT->server->str('REMOTE_USER')) {
|
||||
throw new \RuntimeException("no resendpwd when already logged in");
|
||||
}
|
||||
|
||||
$this->svg = DOKU_INC_COMPAT . 'lib/images/menu/lock-reset.svg';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace dokuwiki\Menu\Item;
|
||||
|
||||
/**
|
||||
* Class Revert
|
||||
*
|
||||
* Quick revert to the currently shown page revision
|
||||
*/
|
||||
class Revert extends AbstractItem {
|
||||
|
||||
/** @inheritdoc */
|
||||
public function __construct() {
|
||||
global $REV;
|
||||
global $INFO;
|
||||
parent::__construct();
|
||||
|
||||
if(!$REV || !$INFO['writable']) {
|
||||
throw new \RuntimeException('revert not available');
|
||||
}
|
||||
$this->params['rev'] = $REV;
|
||||
$this->params['sectok'] = getSecurityToken();
|
||||
$this->svg = DOKU_INC_COMPAT . 'lib/images/menu/06-revert_replay.svg';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace dokuwiki\Menu\Item;
|
||||
|
||||
/**
|
||||
* Class Revisions
|
||||
*
|
||||
* Access the old revisions of the current page
|
||||
*/
|
||||
class Revisions extends AbstractItem {
|
||||
|
||||
/** @inheritdoc */
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
|
||||
$this->accesskey = 'o';
|
||||
$this->type = 'revs';
|
||||
$this->svg = DOKU_INC_COMPAT . 'lib/images/menu/07-revisions_history.svg';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace dokuwiki\Menu\Item;
|
||||
|
||||
/**
|
||||
* Class Subscribe
|
||||
*
|
||||
* Access the subscription management view
|
||||
*/
|
||||
class Subscribe extends AbstractItem {
|
||||
|
||||
/** @inheritdoc */
|
||||
public function __construct() {
|
||||
global $INPUT;
|
||||
parent::__construct();
|
||||
|
||||
if(!$INPUT->server->str('REMOTE_USER')) {
|
||||
throw new \RuntimeException("subscribe is only for logged in users");
|
||||
}
|
||||
|
||||
$this->svg = DOKU_INC_COMPAT . 'lib/images/menu/09-subscribe_email-outline.svg';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace dokuwiki\Menu\Item;
|
||||
|
||||
/**
|
||||
* Class Top
|
||||
*
|
||||
* Scroll back to the top. Uses a hash as $id which is handled special in getLink().
|
||||
* Not shown in mobile context
|
||||
*/
|
||||
class Top extends AbstractItem {
|
||||
|
||||
/** @inheritdoc */
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
|
||||
$this->svg = DOKU_INC_COMPAT . 'lib/images/menu/10-top_arrow-up.svg';
|
||||
$this->accesskey = 't';
|
||||
$this->params = array('do' => '');
|
||||
$this->id = '#dokuwiki__top';
|
||||
$this->context = self::CTX_DESKTOP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to create a <button> element
|
||||
*
|
||||
* Uses html_topbtn()
|
||||
*
|
||||
* @todo this does currently not support the SVG icon
|
||||
* @return string
|
||||
*/
|
||||
public function asHtmlButton() {
|
||||
return html_topbtn();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace dokuwiki\Menu;
|
||||
|
||||
use dokuwiki\Menu\Item\AbstractItem;
|
||||
|
||||
/**
|
||||
* Interface MenuInterface
|
||||
*
|
||||
* Defines what a Menu provides
|
||||
*/
|
||||
Interface MenuInterface {
|
||||
|
||||
/**
|
||||
* Get the list of action items in this menu
|
||||
*
|
||||
* @return AbstractItem[]
|
||||
*/
|
||||
public function getItems();
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace dokuwiki\Menu;
|
||||
|
||||
use dokuwiki\Menu\Item\AbstractItem;
|
||||
|
||||
/**
|
||||
* Class MobileMenu
|
||||
*
|
||||
* Note: this does not inherit from AbstractMenu because it is not working like the other
|
||||
* menus. This is a meta menu, aggregating the items from the other menus and offering a combined
|
||||
* view. The idea is to use this on mobile devices, thus the context is fixed to CTX_MOBILE
|
||||
*/
|
||||
class MobileMenu implements MenuInterface {
|
||||
|
||||
/**
|
||||
* Returns all items grouped by view
|
||||
*
|
||||
* @return AbstractItem[][]
|
||||
*/
|
||||
public function getGroupedItems() {
|
||||
$pagemenu = new PageMenu(AbstractItem::CTX_MOBILE);
|
||||
$sitemenu = new SiteMenu(AbstractItem::CTX_MOBILE);
|
||||
$usermenu = new UserMenu(AbstractItem::CTX_MOBILE);
|
||||
|
||||
return array(
|
||||
'page' => $pagemenu->getItems(),
|
||||
'site' => $sitemenu->getItems(),
|
||||
'user' => $usermenu->getItems()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all items in a flat array
|
||||
*
|
||||
* This returns the same format as AbstractMenu::getItems()
|
||||
*
|
||||
* @return AbstractItem[]
|
||||
*/
|
||||
public function getItems() {
|
||||
$menu = $this->getGroupedItems();
|
||||
return call_user_func_array('array_merge', array_values($menu));
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a dropdown menu with all DokuWiki actions
|
||||
*
|
||||
* Note: this will not use any pretty URLs
|
||||
*
|
||||
* @param string $empty empty option label
|
||||
* @param string $button submit button label
|
||||
* @return string
|
||||
*/
|
||||
public function getDropdown($empty = '', $button = '>') {
|
||||
global $ID;
|
||||
global $REV;
|
||||
/** @var string[] $lang */
|
||||
global $lang;
|
||||
global $INPUT;
|
||||
|
||||
$html = '<form action="' . script() . '" method="get" accept-charset="utf-8">';
|
||||
$html .= '<div class="no">';
|
||||
$html .= '<input type="hidden" name="id" value="' . $ID . '" />';
|
||||
if($REV) $html .= '<input type="hidden" name="rev" value="' . $REV . '" />';
|
||||
if($INPUT->server->str('REMOTE_USER')) {
|
||||
$html .= '<input type="hidden" name="sectok" value="' . getSecurityToken() . '" />';
|
||||
}
|
||||
|
||||
$html .= '<select name="do" class="edit quickselect" title="' . $lang['tools'] . '">';
|
||||
$html .= '<option value="">' . $empty . '</option>';
|
||||
|
||||
foreach($this->getGroupedItems() as $tools => $items) {
|
||||
if (count($items)) {
|
||||
$html .= '<optgroup label="' . $lang[$tools . '_tools'] . '">';
|
||||
foreach($items as $item) {
|
||||
$params = $item->getParams();
|
||||
$html .= '<option value="' . $params['do'] . '">';
|
||||
$html .= hsc($item->getLabel());
|
||||
$html .= '</option>';
|
||||
}
|
||||
$html .= '</optgroup>';
|
||||
}
|
||||
}
|
||||
|
||||
$html .= '</select>';
|
||||
$html .= '<button type="submit">' . $button . '</button>';
|
||||
$html .= '</div>';
|
||||
$html .= '</form>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace dokuwiki\Menu;
|
||||
|
||||
/**
|
||||
* Class PageMenu
|
||||
*
|
||||
* Actions manipulating the current page. Shown as a floating menu in the dokuwiki template
|
||||
*/
|
||||
class PageMenu extends AbstractMenu {
|
||||
|
||||
protected $view = 'page';
|
||||
|
||||
protected $types = array(
|
||||
'Edit',
|
||||
'Revert',
|
||||
'Revisions',
|
||||
'Backlink',
|
||||
'Subscribe',
|
||||
'Top',
|
||||
);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace dokuwiki\Menu;
|
||||
|
||||
/**
|
||||
* Class SiteMenu
|
||||
*
|
||||
* Actions that are not bound to an individual page but provide toolsfor the whole wiki.
|
||||
*/
|
||||
class SiteMenu extends AbstractMenu {
|
||||
|
||||
protected $view = 'site';
|
||||
|
||||
protected $types = array(
|
||||
'Recent',
|
||||
'Media',
|
||||
'Index'
|
||||
);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace dokuwiki\Menu;
|
||||
|
||||
/**
|
||||
* Class UserMenu
|
||||
*
|
||||
* Actions related to the current user
|
||||
*/
|
||||
class UserMenu extends AbstractMenu {
|
||||
|
||||
protected $view = 'user';
|
||||
|
||||
protected $types = array(
|
||||
'Profile',
|
||||
'Admin',
|
||||
'Register',
|
||||
'Login',
|
||||
);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* DokuWiki Bootstrap3 Template: Compatibility functions
|
||||
*
|
||||
* @link http://dokuwiki.org/template:bootstrap3
|
||||
* @author Giuseppe Di Terlizzi <giuseppe.diterlizzi@gmail.com>
|
||||
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
|
||||
*/
|
||||
|
||||
global $updateVersion;
|
||||
$dokuwiki_version = floatval($updateVersion);
|
||||
|
||||
define('DOKU_VERSION', $dokuwiki_version);
|
||||
define('DOKU_VERSION_HOGFATHER', 51); // 2020-07-29
|
||||
define('DOKU_VERSION_GREEBO', 50); // 2018-04-22 (PHP >= 5.6)
|
||||
define('DOKU_VERSION_FRUSTERICK_MANNERS', 49); // 2017-02-19 (PHP >= 5.4 ???)
|
||||
define('DOKU_VERSION_ELENOR_OF_TSORT', 48); // 2016-06-26
|
||||
define('DOKU_VERSION_DETRITUS', 47); // 2015-08-10 (PHP >= 5.3.3)
|
||||
|
||||
|
||||
// Load compatibility Menu classes for pre-Greebo releases
|
||||
if (DOKU_VERSION > 0 && DOKU_VERSION < DOKU_VERSION_GREEBO) {
|
||||
|
||||
define('DOKU_INC_COMPAT', realpath(dirname(__FILE__) . '/../') . '/');
|
||||
|
||||
require DOKU_INC_COMPAT . "inc/Menu/MenuInterface.php";
|
||||
require DOKU_INC_COMPAT . "inc/Menu/AbstractMenu.php";
|
||||
require DOKU_INC_COMPAT . "inc/Menu/Item/AbstractItem.php";
|
||||
|
||||
require DOKU_INC_COMPAT . "inc/Menu/UserMenu.php";
|
||||
require DOKU_INC_COMPAT . "inc/Menu/MobileMenu.php";
|
||||
require DOKU_INC_COMPAT . "inc/Menu/PageMenu.php";
|
||||
require DOKU_INC_COMPAT . "inc/Menu/SiteMenu.php";
|
||||
require DOKU_INC_COMPAT . "inc/Menu/DetailMenu.php";
|
||||
|
||||
require DOKU_INC_COMPAT . "inc/Menu/Item/ImgBackto.php";
|
||||
require DOKU_INC_COMPAT . "inc/Menu/Item/Top.php";
|
||||
require DOKU_INC_COMPAT . "inc/Menu/Item/Edit.php";
|
||||
require DOKU_INC_COMPAT . "inc/Menu/Item/Profile.php";
|
||||
require DOKU_INC_COMPAT . "inc/Menu/Item/Revisions.php";
|
||||
require DOKU_INC_COMPAT . "inc/Menu/Item/Backlink.php";
|
||||
require DOKU_INC_COMPAT . "inc/Menu/Item/Back.php";
|
||||
require DOKU_INC_COMPAT . "inc/Menu/Item/Login.php";
|
||||
require DOKU_INC_COMPAT . "inc/Menu/Item/Index.php";
|
||||
require DOKU_INC_COMPAT . "inc/Menu/Item/Register.php";
|
||||
require DOKU_INC_COMPAT . "inc/Menu/Item/MediaManager.php";
|
||||
require DOKU_INC_COMPAT . "inc/Menu/Item/Subscribe.php";
|
||||
require DOKU_INC_COMPAT . "inc/Menu/Item/Recent.php";
|
||||
require DOKU_INC_COMPAT . "inc/Menu/Item/Media.php";
|
||||
require DOKU_INC_COMPAT . "inc/Menu/Item/Resendpwd.php";
|
||||
require DOKU_INC_COMPAT . "inc/Menu/Item/Admin.php";
|
||||
require DOKU_INC_COMPAT . "inc/Menu/Item/Revert.php";
|
||||
|
||||
}
|
||||
|
||||
// Load template class for previous "Frusterick Manners" (2017-02-19) releases
|
||||
if (DOKU_VERSION < DOKU_VERSION_FRUSTERICK_MANNERS) {
|
||||
|
||||
$tpl_incdir = tpl_incdir();
|
||||
|
||||
require $tpl_incdir . 'Template.php';
|
||||
require $tpl_incdir . 'SVG.php';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* copied from core (available since Greebo)
|
||||
*/
|
||||
if (!function_exists('inlineSVG')) {
|
||||
|
||||
function inlineSVG($file, $maxsize = 2048)
|
||||
{
|
||||
$file = trim($file);
|
||||
if ($file === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!file_exists($file)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (filesize($file) > $maxsize) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_readable($file)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$content = file_get_contents($file);
|
||||
$content = preg_replace('/<!--.*?(-->)/s', '', $content); // comments
|
||||
$content = preg_replace('/<\?xml .*?\?>/i', '', $content); // xml header
|
||||
$content = preg_replace('/<!DOCTYPE .*?>/i', '', $content); // doc type
|
||||
$content = preg_replace('/>\s+</s', '><', $content); // newlines between tags
|
||||
$content = trim($content);
|
||||
if (substr($content, 0, 5) !== '<svg ') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* copied from core (available since Detritus)
|
||||
*/
|
||||
if (!function_exists('tpl_toolsevent')) {
|
||||
|
||||
function tpl_toolsevent($toolsname, $items, $view = 'main')
|
||||
{
|
||||
$data = array(
|
||||
'view' => $view,
|
||||
'items' => $items,
|
||||
);
|
||||
|
||||
$hook = 'TEMPLATE_' . strtoupper($toolsname) . '_DISPLAY';
|
||||
$evt = new Doku_Event($hook, $data);
|
||||
|
||||
if ($evt->advise_before()) {
|
||||
foreach ($evt->data['items'] as $k => $html) {
|
||||
echo $html;
|
||||
}
|
||||
}
|
||||
$evt->advise_after();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* copied from core (available since Binky)
|
||||
*/
|
||||
if (!function_exists('tpl_classes')) {
|
||||
|
||||
function tpl_classes()
|
||||
{
|
||||
global $ACT, $conf, $ID, $INFO;
|
||||
|
||||
$classes = array(
|
||||
'dokuwiki',
|
||||
'mode_' . $ACT,
|
||||
'tpl_' . $conf['template'],
|
||||
!empty($_SERVER['REMOTE_USER']) ? 'loggedIn' : '',
|
||||
$INFO['exists'] ? '' : 'notFound',
|
||||
($ID == $conf['start']) ? 'home' : '',
|
||||
);
|
||||
|
||||
return join(' ', $classes);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* copied from core (available since Detritus)
|
||||
*/
|
||||
if (!function_exists('plugin_getRequestAdminPlugin')) {
|
||||
|
||||
function plugin_getRequestAdminPlugin()
|
||||
{
|
||||
static $admin_plugin = false;
|
||||
global $ACT, $INPUT, $INFO;
|
||||
|
||||
if ($admin_plugin === false) {
|
||||
if (($ACT == 'admin') && ($page = $INPUT->str('page', '', true)) != '') {
|
||||
$pluginlist = plugin_list('admin');
|
||||
if (in_array($page, $pluginlist)) {
|
||||
// attempt to load the plugin
|
||||
/** @var $admin_plugin DokuWiki_Admin_Plugin */
|
||||
$admin_plugin = plugin_load('admin', $page);
|
||||
// verify
|
||||
if ($admin_plugin && $admin_plugin->forAdminOnly() && !$INFO['isadmin']) {
|
||||
$admin_plugin = null;
|
||||
$INPUT->remove('page');
|
||||
msg('For admins only', -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $admin_plugin;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M12 20a8 8 0 0 1-8-8 8 8 0 0 1 8-8 8 8 0 0 1 8 8 8 8 0 0 1-8 8m0-18A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10A10 10 0 0 0 12 2z"/></svg>
|
||||
|
After Width: | Height: | Size: 239 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M20.71 7.04c.39-.39.39-1.04 0-1.41l-2.34-2.34c-.37-.39-1.02-.39-1.41 0l-1.84 1.83 3.75 3.75M3 17.25V21h3.75L17.81 9.93l-3.75-3.75L3 17.25z"/></svg>
|
||||
|
After Width: | Height: | Size: 239 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" height="24" width="24"><path d="M13.118 16.118h3v-3h2v3h3v2h-3v3h-2v-3h-3zM20.71 7.04c.39-.39.39-1.04 0-1.41l-2.34-2.34c-.37-.39-1.02-.39-1.41 0l-1.84 1.83 3.75 3.75M3 17.25V21h3.75L17.81 9.93l-3.75-3.75z"/></svg>
|
||||
|
After Width: | Height: | Size: 273 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M11 2h2v2h.5A1.5 1.5 0 0 1 15 5.5V9l-.44.44 1.64 2.84C17.31 11.19 18 9.68 18 8h2c0 2.42-1.07 4.59-2.77 6.06l3.14 5.44.13 2.22-1.87-1.22-3.07-5.33c-1.06.53-2.28.83-3.56.83-1.28 0-2.5-.3-3.56-.83L5.37 20.5 3.5 21.72l.13-2.22L9.44 9.44 9 9V5.5A1.5 1.5 0 0 1 10.5 4h.5V2M9.44 13.43c.78.37 1.65.57 2.56.57.91 0 1.78-.2 2.56-.57L13.1 10.9h-.01c-.62.6-1.56.6-2.18 0h-.01l-1.46 2.53M12 6a1 1 0 0 0-1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0-1-1z"/></svg>
|
||||
|
After Width: | Height: | Size: 537 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M13 9h5.5L13 3.5V9M6 2h8l6 6v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4c0-1.11.89-2 2-2m9 16v-2H6v2h9m3-4v-2H6v2h12z"/></svg>
|
||||
|
After Width: | Height: | Size: 209 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M13 9h5.5L13 3.5V9M6 2h8l6 6v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4c0-1.11.89-2 2-2m.12 13.5l3.74 3.74 1.42-1.41-2.33-2.33 2.33-2.33-1.42-1.41-3.74 3.74m11.16 0l-3.74-3.74-1.42 1.41 2.33 2.33-2.33 2.33 1.42 1.41 3.74-3.74z"/></svg>
|
||||
|
After Width: | Height: | Size: 319 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M12 5V1L7 6l5 5V7a6 6 0 0 1 6 6 6 6 0 0 1-6 6 6 6 0 0 1-6-6H4a8 8 0 0 0 8 8 8 8 0 0 0 8-8 8 8 0 0 0-8-8z"/></svg>
|
||||
|
After Width: | Height: | Size: 205 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M11 7v5.11l4.71 2.79.79-1.28-4-2.37V7m0-5C8.97 2 5.91 3.92 4.27 6.77L2 4.5V11h6.5L5.75 8.25C6.96 5.73 9.5 4 12.5 4a7.5 7.5 0 0 1 7.5 7.5 7.5 7.5 0 0 1-7.5 7.5c-3.27 0-6.03-2.09-7.06-5h-2.1c1.1 4.03 4.77 7 9.16 7 5.24 0 9.5-4.25 9.5-9.5A9.5 9.5 0 0 0 12.5 2z"/></svg>
|
||||
|
After Width: | Height: | Size: 358 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M10.59 13.41c.41.39.41 1.03 0 1.42-.39.39-1.03.39-1.42 0a5.003 5.003 0 0 1 0-7.07l3.54-3.54a5.003 5.003 0 0 1 7.07 0 5.003 5.003 0 0 1 0 7.07l-1.49 1.49c.01-.82-.12-1.64-.4-2.42l.47-.48a2.982 2.982 0 0 0 0-4.24 2.982 2.982 0 0 0-4.24 0l-3.53 3.53a2.982 2.982 0 0 0 0 4.24m2.82-4.24c.39-.39 1.03-.39 1.42 0a5.003 5.003 0 0 1 0 7.07l-3.54 3.54a5.003 5.003 0 0 1-7.07 0 5.003 5.003 0 0 1 0-7.07l1.49-1.49c-.01.82.12 1.64.4 2.43l-.47.47a2.982 2.982 0 0 0 0 4.24 2.982 2.982 0 0 0 4.24 0l3.53-3.53a2.982 2.982 0 0 0 0-4.24.973.973 0 0 1 0-1.42z"/></svg>
|
||||
|
After Width: | Height: | Size: 640 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M20 4H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2m0 14H4V8l8 5 8-5v10m0-12l-8 5-8-5h16z"/></svg>
|
||||
|
After Width: | Height: | Size: 210 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8v12z"/></svg>
|
||||
|
After Width: | Height: | Size: 168 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M5 17l4.5-6 3.5 4.5 2.5-3L19 17m1-11h-8l-2-2H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2z"/></svg>
|
||||
|
After Width: | Height: | Size: 212 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12z"/></svg>
|
||||
|
After Width: | Height: | Size: 165 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M2 3h20c1.05 0 2 .95 2 2v14c0 1.05-.95 2-2 2H2c-1.05 0-2-.95-2-2V5c0-1.05.95-2 2-2m12 3v1h8V6h-8m0 2v1h8V8h-8m0 2v1h7v-1h-7m-6 3.91C6 13.91 2 15 2 17v1h12v-1c0-2-4-3.09-6-3.09M8 6a3 3 0 0 0-3 3 3 3 0 0 0 3 3 3 3 0 0 0 3-3 3 3 0 0 0-3-3z"/></svg>
|
||||
|
After Width: | Height: | Size: 337 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M15 14c-2.67 0-8 1.33-8 4v2h16v-2c0-2.67-5.33-4-8-4m-9-4V7H4v3H1v2h3v3h2v-3h3v-2m6 2a4 4 0 0 0 4-4 4 4 0 0 0-4-4 4 4 0 0 0-4 4 4 4 0 0 0 4 4z"/></svg>
|
||||
|
After Width: | Height: | Size: 242 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M15 13h1.5v2.82l2.44 1.41-.75 1.3L15 16.69V13m4-5H5v11h4.67c-.43-.91-.67-1.93-.67-3a7 7 0 0 1 7-7c1.07 0 2.09.24 3 .67V8M5 21a2 2 0 0 1-2-2V5c0-1.11.89-2 2-2h1V1h2v2h8V1h2v2h1a2 2 0 0 1 2 2v6.1c1.24 1.26 2 2.99 2 4.9a7 7 0 0 1-7 7c-1.91 0-3.64-.76-4.9-2H5m11-9.85A4.85 4.85 0 0 0 11.15 16c0 2.68 2.17 4.85 4.85 4.85A4.85 4.85 0 0 0 20.85 16c0-2.68-2.17-4.85-4.85-4.85z"/></svg>
|
||||
|
After Width: | Height: | Size: 469 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M3 3h6v4H3V3m12 7h6v4h-6v-4m0 7h6v4h-6v-4m-2-4H7v5h6v2H5V9h2v2h6v2z"/></svg>
|
||||
|
After Width: | Height: | Size: 168 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M7 15l4.5-6 3.5 4.5 2.5-3L21 15m1-11h-8l-2-2H6a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2M2 6H0v14a2 2 0 0 0 2 2h18v-2H2V6z"/></svg>
|
||||
|
After Width: | Height: | Size: 245 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M12.63 2c5.53 0 10.01 4.5 10.01 10s-4.48 10-10.01 10c-3.51 0-6.58-1.82-8.37-4.57l1.58-1.25C7.25 18.47 9.76 20 12.64 20a8 8 0 0 0 8-8 8 8 0 0 0-8-8C8.56 4 5.2 7.06 4.71 11h2.76l-3.74 3.73L0 11h2.69c.5-5.05 4.76-9 9.94-9m2.96 8.24c.5.01.91.41.91.92v4.61c0 .5-.41.92-.92.92h-5.53c-.51 0-.92-.42-.92-.92v-4.61c0-.51.41-.91.91-.92V9.23c0-1.53 1.25-2.77 2.77-2.77 1.53 0 2.78 1.24 2.78 2.77v1.01m-2.78-2.38c-.75 0-1.37.61-1.37 1.37v1.01h2.75V9.23c0-.76-.62-1.37-1.38-1.37z"/></svg>
|
||||
|
After Width: | Height: | Size: 567 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M10 17.25V14H3v-4h7V6.75L15.25 12 10 17.25M8 2h9a2 2 0 0 1 2 2v16a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2v-4h2v4h9V4H8v4H6V4a2 2 0 0 1 2-2z"/></svg>
|
||||
|
After Width: | Height: | Size: 230 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M17 17.25V14h-7v-4h7V6.75L22.25 12 17 17.25M13 2a2 2 0 0 1 2 2v4h-2V4H4v16h9v-4h2v4a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9z"/></svg>
|
||||
|
After Width: | Height: | Size: 233 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M12 15.5A3.5 3.5 0 0 1 8.5 12 3.5 3.5 0 0 1 12 8.5a3.5 3.5 0 0 1 3.5 3.5 3.5 3.5 0 0 1-3.5 3.5m7.43-2.53c.04-.32.07-.64.07-.97 0-.33-.03-.66-.07-1l2.11-1.63c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.31-.61-.22l-2.49 1c-.52-.39-1.06-.73-1.69-.98l-.37-2.65A.506.506 0 0 0 14 2h-4c-.25 0-.46.18-.5.42l-.37 2.65c-.63.25-1.17.59-1.69.98l-2.49-1c-.22-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64L4.57 11c-.04.34-.07.67-.07 1 0 .33.03.65.07.97l-2.11 1.66c-.19.15-.25.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1.01c.52.4 1.06.74 1.69.99l.37 2.65c.04.24.25.42.5.42h4c.25 0 .46-.18.5-.42l.37-2.65c.63-.26 1.17-.59 1.69-.99l2.49 1.01c.22.08.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.66z"/></svg>
|
||||
|
After Width: | Height: | Size: 786 B |