Refactor: Portal is also a Menu
To complete the refactor, the Portal is also refactored as a Menu using the getMenu function. An old code path supporting portals outputted by hooks with strings is marked as deprecated to simplify this code in future. array-portals-first -> data-portals-first (the value is not an array) Changes: * $this->getLanguages and $this->getToolbox() always returns an array (see BaseTemplate) but we previously supported portals made using raw HTML. Let's move away from that behaviour and deprecate it. * Hooks are moved into buildSidebarProps and marked as deprecated where possible (SkinTemplateToolboxEnd). SidebarBeforeOutput can be used instead. Bug: T249372 Change-Id: I2549af3e24e5d51c09e9a88ca50a0d9b2e154c3f
This commit is contained in:
parent
e4a4050b81
commit
9f2ca0d072
|
@ -32,7 +32,9 @@ class VectorTemplate extends BaseTemplate {
|
||||||
/** @var array of alternate message keys for menu labels */
|
/** @var array of alternate message keys for menu labels */
|
||||||
private const MENU_LABEL_KEYS = [
|
private const MENU_LABEL_KEYS = [
|
||||||
'cactions' => 'vector-more-actions',
|
'cactions' => 'vector-more-actions',
|
||||||
|
'tb' => 'toolbox',
|
||||||
'personal' => 'personaltools',
|
'personal' => 'personaltools',
|
||||||
|
'lang' => 'otherlanguages',
|
||||||
];
|
];
|
||||||
/** @var int */
|
/** @var int */
|
||||||
private const MENU_TYPE_DEFAULT = 0;
|
private const MENU_TYPE_DEFAULT = 0;
|
||||||
|
@ -40,6 +42,7 @@ class VectorTemplate extends BaseTemplate {
|
||||||
private const MENU_TYPE_TABS = 1;
|
private const MENU_TYPE_TABS = 1;
|
||||||
/** @var int */
|
/** @var int */
|
||||||
private const MENU_TYPE_DROPDOWN = 2;
|
private const MENU_TYPE_DROPDOWN = 2;
|
||||||
|
private const MENU_TYPE_PORTAL = 3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* T243281: Code used to track clicks to opt-out link.
|
* T243281: Code used to track clicks to opt-out link.
|
||||||
|
@ -324,8 +327,16 @@ class VectorTemplate extends BaseTemplate {
|
||||||
case 'SEARCH':
|
case 'SEARCH':
|
||||||
break;
|
break;
|
||||||
case 'TOOLBOX':
|
case 'TOOLBOX':
|
||||||
$portal = $this->buildPortalProps( 'tb', $this->getToolbox(), 'toolbox',
|
$portal = $this->getMenuData(
|
||||||
'SkinTemplateToolboxEnd' );
|
'tb', $this->getToolbox(), self::MENU_TYPE_PORTAL
|
||||||
|
);
|
||||||
|
// Run deprecated hooks.
|
||||||
|
$vectorTemplate = $this;
|
||||||
|
ob_start();
|
||||||
|
// Use SidebarBeforeOutput instead.
|
||||||
|
Hooks::run( 'SkinTemplateToolboxEnd', [ &$vectorTemplate, true ], '1.35' );
|
||||||
|
$htmlhookitems = ob_get_clean();
|
||||||
|
$portal['html-items'] .= $htmlhookitems;
|
||||||
ob_start();
|
ob_start();
|
||||||
Hooks::run( 'VectorAfterToolbox', [], '1.35' );
|
Hooks::run( 'VectorAfterToolbox', [], '1.35' );
|
||||||
$props[] = $portal + [
|
$props[] = $portal + [
|
||||||
|
@ -336,15 +347,34 @@ class VectorTemplate extends BaseTemplate {
|
||||||
// @phan-suppress-next-line PhanUndeclaredMethod
|
// @phan-suppress-next-line PhanUndeclaredMethod
|
||||||
$languages = $skin->getLanguages();
|
$languages = $skin->getLanguages();
|
||||||
if ( count( $languages ) ) {
|
if ( count( $languages ) ) {
|
||||||
$props[] = $this->buildPortalProps(
|
$props[] = $this->getMenuData(
|
||||||
'lang',
|
'lang',
|
||||||
$languages,
|
$languages,
|
||||||
'otherlanguages'
|
self::MENU_TYPE_PORTAL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
$props[] = $this->buildPortalProps( $name, $content );
|
// Historically some portals have been defined using HTML rather than arrays.
|
||||||
|
// Let's move away from that to a uniform definition.
|
||||||
|
if ( !is_array( $content ) ) {
|
||||||
|
$html = $content;
|
||||||
|
$content = [];
|
||||||
|
wfDeprecated(
|
||||||
|
"`content` field in portal $name must be array."
|
||||||
|
. "Previously it could be a string but this is no longer supported.",
|
||||||
|
'1.35.0'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$html = false;
|
||||||
|
}
|
||||||
|
$portal = $this->getMenuData(
|
||||||
|
$name, $content, self::MENU_TYPE_PORTAL
|
||||||
|
);
|
||||||
|
if ( $html ) {
|
||||||
|
$portal['html-items'] .= $html;
|
||||||
|
}
|
||||||
|
$props[] = $portal;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -363,57 +393,10 @@ class VectorTemplate extends BaseTemplate {
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
'array-portals-rest' => array_slice( $props, 1 ),
|
'array-portals-rest' => array_slice( $props, 1 ),
|
||||||
'array-portals-first' => $firstPortal,
|
'data-portals-first' => $firstPortal,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $name
|
|
||||||
* @param array|string $content
|
|
||||||
* @param null|string $msg
|
|
||||||
* @param null|string|array $hook
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function buildPortalProps( $name, $content, $msg = null, $hook = null ) : array {
|
|
||||||
if ( $msg === null ) {
|
|
||||||
$msg = $name;
|
|
||||||
}
|
|
||||||
|
|
||||||
$msgObj = $this->getMsg( $msg );
|
|
||||||
|
|
||||||
$props = [
|
|
||||||
'portal-id' => "p-$name",
|
|
||||||
'class' => 'portal',
|
|
||||||
'html-tooltip' => Linker::tooltip( 'p-' . $name ),
|
|
||||||
'msg-label' => $msgObj->exists() ? $msgObj->text() : $msg,
|
|
||||||
'msg-label-id' => "p-$name-label",
|
|
||||||
'html-userlangattributes' => $this->get( 'userlangattributes', '' ),
|
|
||||||
'html-portal-content' => '',
|
|
||||||
'html-after-portal' => $this->getAfterPortlet( $name ),
|
|
||||||
];
|
|
||||||
|
|
||||||
if ( is_array( $content ) ) {
|
|
||||||
$props['html-portal-content'] .= '<ul>';
|
|
||||||
foreach ( $content as $key => $val ) {
|
|
||||||
$props['html-portal-content'] .= $this->makeListItem( $key, $val );
|
|
||||||
}
|
|
||||||
if ( $hook !== null ) {
|
|
||||||
// Avoid PHP 7.1 warning
|
|
||||||
$skin = $this;
|
|
||||||
ob_start();
|
|
||||||
Hooks::run( $hook, [ &$skin, true ] );
|
|
||||||
$props['html-portal-content'] .= ob_get_contents();
|
|
||||||
ob_end_clean();
|
|
||||||
}
|
|
||||||
$props['html-portal-content'] .= '</ul>';
|
|
||||||
} else {
|
|
||||||
// Allow raw HTML block to be defined by extensions
|
|
||||||
$props['html-portal-content'] = $content;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $props;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
|
@ -444,6 +427,8 @@ class VectorTemplate extends BaseTemplate {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $label to be used to derive the id and human readable label of the menu
|
* @param string $label to be used to derive the id and human readable label of the menu
|
||||||
|
* If the key has an entry in the constant MENU_LABEL_KEYS then that message will be used for the
|
||||||
|
* human readable text instead.
|
||||||
* @param array $urls to convert to list items stored as string in html-items key
|
* @param array $urls to convert to list items stored as string in html-items key
|
||||||
* @param int $type of menu (optional) - a plain list (MENU_TYPE_DEFAULT),
|
* @param int $type of menu (optional) - a plain list (MENU_TYPE_DEFAULT),
|
||||||
* a tab (MENU_TYPE_TABS) or a dropdown (MENU_TYPE_DROPDOWN)
|
* a tab (MENU_TYPE_TABS) or a dropdown (MENU_TYPE_DROPDOWN)
|
||||||
|
@ -465,8 +450,10 @@ class VectorTemplate extends BaseTemplate {
|
||||||
$extraClasses = [
|
$extraClasses = [
|
||||||
self::MENU_TYPE_DROPDOWN => 'vector-menu-dropdown vectorMenu',
|
self::MENU_TYPE_DROPDOWN => 'vector-menu-dropdown vectorMenu',
|
||||||
self::MENU_TYPE_TABS => 'vector-menu-tabs vectorTabs',
|
self::MENU_TYPE_TABS => 'vector-menu-tabs vectorTabs',
|
||||||
|
self::MENU_TYPE_PORTAL => 'vector-menu-portal portal',
|
||||||
self::MENU_TYPE_DEFAULT => 'vector-menu',
|
self::MENU_TYPE_DEFAULT => 'vector-menu',
|
||||||
];
|
];
|
||||||
|
$isPortal = self::MENU_TYPE_PORTAL === $type;
|
||||||
|
|
||||||
$props = [
|
$props = [
|
||||||
'id' => "p-$label",
|
'id' => "p-$label",
|
||||||
|
@ -478,6 +465,8 @@ class VectorTemplate extends BaseTemplate {
|
||||||
'html-userlangattributes' => $this->get( 'userlangattributes', '' ),
|
'html-userlangattributes' => $this->get( 'userlangattributes', '' ),
|
||||||
'html-items' => '',
|
'html-items' => '',
|
||||||
'is-dropdown' => self::MENU_TYPE_DROPDOWN === $type,
|
'is-dropdown' => self::MENU_TYPE_DROPDOWN === $type,
|
||||||
|
'html-tooltip' => Linker::tooltip( 'p-' . $label ),
|
||||||
|
'is-portal' => $isPortal,
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ( $urls as $key => $item ) {
|
foreach ( $urls as $key => $item ) {
|
||||||
|
@ -492,6 +481,9 @@ class VectorTemplate extends BaseTemplate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$props['html-after-portal'] = $isPortal ? $this->getAfterPortlet( $label ) : '';
|
||||||
|
|
||||||
return $props;
|
return $props;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,27 @@
|
||||||
{{!
|
{{!
|
||||||
See @typedef MenuDefinition
|
See @typedef MenuDefinition
|
||||||
}}
|
}}
|
||||||
<nav id="{{id}}" class="{{class}}" aria-labelledby="{{label-id}}">
|
<nav id="{{id}}" class="{{class}}" aria-labelledby="{{label-id}}" {{{html-tooltip}}}>
|
||||||
{{#is-dropdown}}
|
{{#is-dropdown}}
|
||||||
<input type="checkbox" class="vectorMenuCheckbox" aria-labelledby="{{label-id}}" />
|
<input type="checkbox" class="vectorMenuCheckbox" aria-labelledby="{{label-id}}" />
|
||||||
<h3 id="{{label-id}}">
|
<h3 id="{{label-id}}" {{{html-userlangattributes}}}>
|
||||||
<span>{{label}}</span>
|
<span>{{label}}</span>
|
||||||
</h3>
|
</h3>
|
||||||
{{/is-dropdown}}
|
{{/is-dropdown}}
|
||||||
{{^is-dropdown}}
|
{{^is-dropdown}}
|
||||||
<h3 id="{{label-id}}">{{label}}</h3>
|
<h3 id="{{label-id}}">{{label}}</h3>
|
||||||
{{/is-dropdown}}
|
{{/is-dropdown}}
|
||||||
|
{{#is-portal}}
|
||||||
|
<div class="body">
|
||||||
|
<ul>{{{html-items}}}</ul>
|
||||||
|
{{{html-after-portal}}}
|
||||||
|
</div>
|
||||||
|
{{/is-portal}}
|
||||||
|
{{^is-portal}}
|
||||||
<ul class="menu" {{{html-userlangattributes}}}>
|
<ul class="menu" {{{html-userlangattributes}}}>
|
||||||
{{{html-items}}}
|
{{{html-items}}}
|
||||||
</ul>
|
</ul>
|
||||||
|
{{/is-portal}}
|
||||||
</nav>
|
</nav>
|
||||||
|
{{! Note: html-hook-vector-after-toolbox is deprecated. }}
|
||||||
|
{{{html-hook-vector-after-toolbox}}}
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
@prop string text
|
@prop string text
|
||||||
|
|
||||||
string html-logo-attributes for site logo. Must be used inside tag e.g. `class="logo" lang="en-gb"`
|
string html-logo-attributes for site logo. Must be used inside tag e.g. `class="logo" lang="en-gb"`
|
||||||
array array-portals contains options for Portal template
|
MenuDefinition data-portals-first
|
||||||
|
MenuDefinition[] array-portals-rest
|
||||||
emphasized-sidebar-action data-emphasized-sidebar-action For displaying an emphasized action in the sidebar.
|
emphasized-sidebar-action data-emphasized-sidebar-action For displaying an emphasized action in the sidebar.
|
||||||
@prop boolean has-logo whether to show a logo or not.
|
@prop boolean has-logo whether to show a logo or not.
|
||||||
}}
|
}}
|
||||||
|
@ -15,11 +16,11 @@
|
||||||
<a {{{html-logo-attributes}}}></a>
|
<a {{{html-logo-attributes}}}></a>
|
||||||
</div>
|
</div>
|
||||||
{{/has-logo}}
|
{{/has-logo}}
|
||||||
{{#array-portals-first}}{{>Portal}}{{/array-portals-first}}
|
{{#data-portals-first}}{{>Menu}}{{/data-portals-first}}
|
||||||
{{#data-emphasized-sidebar-action}}
|
{{#data-emphasized-sidebar-action}}
|
||||||
<div class="vector-emphasized-sidebar-action">
|
<div class="vector-emphasized-sidebar-action">
|
||||||
<a class="vector-emphasized-sidebar-action-link" title="{{title}}" href="{{href}}">{{text}}</a>
|
<a class="vector-emphasized-sidebar-action-link" title="{{title}}" href="{{href}}">{{text}}</a>
|
||||||
</div>
|
</div>
|
||||||
{{/data-emphasized-sidebar-action}}
|
{{/data-emphasized-sidebar-action}}
|
||||||
{{#array-portals-rest}}{{>Portal}}{{/array-portals-rest}}
|
{{#array-portals-rest}}{{>Menu}}{{/array-portals-rest}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
@import '../../variables.less';
|
@import '../../variables.less';
|
||||||
@import 'mediawiki.mixins.less';
|
@import 'mediawiki.mixins.less';
|
||||||
|
|
||||||
.portal {
|
// FIXME: For cached HTML
|
||||||
|
.portal,
|
||||||
|
.vector-menu-portal {
|
||||||
margin: 0 @margin-end-portal 0 @margin-start-portal;
|
margin: 0 @margin-end-portal 0 @margin-start-portal;
|
||||||
padding: 0.25em 0;
|
padding: 0.25em 0;
|
||||||
direction: ltr;
|
direction: ltr;
|
|
@ -19,7 +19,7 @@
|
||||||
@import 'MenuTabs.less';
|
@import 'MenuTabs.less';
|
||||||
@import 'TabWatchstarLink.less';
|
@import 'TabWatchstarLink.less';
|
||||||
@import 'MenuDropdown.less';
|
@import 'MenuDropdown.less';
|
||||||
@import 'Portal.less';
|
@import 'MenuPortal.less';
|
||||||
@import 'Sidebar.less';
|
@import 'Sidebar.less';
|
||||||
@import 'SidebarLogo.less';
|
@import 'SidebarLogo.less';
|
||||||
@import 'Footer.less';
|
@import 'Footer.less';
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
@import 'MenuTabs.less';
|
@import 'MenuTabs.less';
|
||||||
@import 'TabWatchstarLink.less';
|
@import 'TabWatchstarLink.less';
|
||||||
@import 'MenuDropdown.less';
|
@import 'MenuDropdown.less';
|
||||||
@import 'Portal.less';
|
@import 'MenuPortal.less';
|
||||||
@import 'Sidebar.less';
|
@import 'Sidebar.less';
|
||||||
@import 'SidebarLogo.less';
|
@import 'SidebarLogo.less';
|
||||||
@import 'Footer.less';
|
@import 'Footer.less';
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import mustache from 'mustache';
|
import mustache from 'mustache';
|
||||||
import portalTemplate from '!!raw-loader!../includes/templates/Portal.mustache';
|
import { vectorMenuTemplate as portalTemplate } from './MenuDropdown.stories.data';
|
||||||
import '../resources/skins.vector.styles/Portal.less';
|
import '../resources/skins.vector.styles/MenuPortal.less';
|
||||||
import '../.storybook/common.less';
|
import '../.storybook/common.less';
|
||||||
import { placeholder, htmluserlangattributes } from './utils';
|
import { placeholder, htmluserlangattributes } from './utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {PortletContext} data
|
* @param {MenuDefinition} data
|
||||||
* @return {HTMLElement}
|
* @return {HTMLElement}
|
||||||
*/
|
*/
|
||||||
export const wrapPortlet = ( data ) => {
|
export const wrapPortlet = ( data ) => {
|
||||||
|
@ -23,74 +23,83 @@ const portletAfter = ( html ) => {
|
||||||
return `<div class="after-portlet after-portlet-tb">${html}</div>`;
|
return `<div class="after-portlet after-portlet-tb">${html}</div>`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Object.<string, MenuDefinition>}
|
||||||
|
*/
|
||||||
export const PORTALS = {
|
export const PORTALS = {
|
||||||
example: {
|
example: {
|
||||||
'portal-id': 'p-example',
|
id: 'p-example',
|
||||||
class: 'portal',
|
class: 'vector-menu-portal portal',
|
||||||
'html-tooltip': 'Message tooltip-p-example acts as tooltip',
|
'html-tooltip': 'Message tooltip-p-example acts as tooltip',
|
||||||
'msg-label': 'Portal title',
|
label: 'Portal title',
|
||||||
'msg-label-id': 'p-example-label',
|
'label-id': 'p-example-label',
|
||||||
'html-userlangattributes': htmluserlangattributes,
|
'html-userlangattributes': htmluserlangattributes,
|
||||||
'html-portal-content': `<ul>
|
'is-portal': true,
|
||||||
|
'html-items': `
|
||||||
<li><a href='#'>A list of links</a></li>
|
<li><a href='#'>A list of links</a></li>
|
||||||
<li><a href='#'>with ids</a></li>
|
<li><a href='#'>with ids</a></li>
|
||||||
<li><a href='#'>on each list item</a></li>
|
<li><a href='#'>on each list item</a></li>
|
||||||
</ul>`,
|
`,
|
||||||
'html-after-portal': portletAfter(
|
'html-after-portal': portletAfter(
|
||||||
placeholder( `<p>Beware: The <a href="https://codesearch.wmflabs.org/search/?q=BaseTemplateAfterPortlet&i=nope&files=&repos=">BaseTemplateAfterPortlet hook</a> can be used to inject arbitary HTML here for any portlet.</p>`, 60 )
|
placeholder( `<p>Beware: The <a href="https://codesearch.wmflabs.org/search/?q=BaseTemplateAfterPortlet&i=nope&files=&repos=">BaseTemplateAfterPortlet hook</a> can be used to inject arbitary HTML here for any portlet.</p>`, 60 )
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
navigation: {
|
navigation: {
|
||||||
'portal-id': 'p-navigation',
|
id: 'p-navigation',
|
||||||
class: 'portal portal-first',
|
class: 'portal portal-first',
|
||||||
'html-tooltip': 'A message tooltip-p-navigation must exist for this to appear',
|
'html-tooltip': 'A message tooltip-p-navigation must exist for this to appear',
|
||||||
'msg-label': 'Navigation',
|
label: 'Navigation',
|
||||||
'msg-label-id': 'p-navigation-label',
|
'label-id': 'p-navigation-label',
|
||||||
'html-userlangattributes': htmluserlangattributes,
|
'html-userlangattributes': htmluserlangattributes,
|
||||||
'html-portal-content': `<ul>
|
'is-portal': true,
|
||||||
|
'html-items': `
|
||||||
<li id="n-mainpage-description"><a href="/wiki/Main_Page" title="Visit the main page [⌃⌥z]" accesskey="z">Main page</a></li><li id="n-contents"><a href="/wiki/Wikipedia:Contents" title="Guides to browsing Wikipedia">Contents</a></li><li id="n-featuredcontent"><a href="/wiki/Wikipedia:Featured_content" title="Featured content – the best of Wikipedia">Featured content</a></li><li id="n-currentevents"><a href="/wiki/Portal:Current_events" title="Find background information on current events">Current events</a></li><li id="n-randompage"><a href="/wiki/Special:Random" title="Load a random page [⌃⌥x]" accesskey="x">Random page</a></li><li id="n-sitesupport"><a href="https://donate.wikimedia.org/wiki/Special:FundraiserRedirector?utm_source=donate&utm_medium=sidebar&utm_campaign=C13_en.wikipedia.org&uselang=en" title="Support us">Donate</a></li><li id="n-shoplink"><a href="//shop.wikimedia.org" title="Visit the Wikipedia store">Wikipedia store</a></li>
|
<li id="n-mainpage-description"><a href="/wiki/Main_Page" title="Visit the main page [⌃⌥z]" accesskey="z">Main page</a></li><li id="n-contents"><a href="/wiki/Wikipedia:Contents" title="Guides to browsing Wikipedia">Contents</a></li><li id="n-featuredcontent"><a href="/wiki/Wikipedia:Featured_content" title="Featured content – the best of Wikipedia">Featured content</a></li><li id="n-currentevents"><a href="/wiki/Portal:Current_events" title="Find background information on current events">Current events</a></li><li id="n-randompage"><a href="/wiki/Special:Random" title="Load a random page [⌃⌥x]" accesskey="x">Random page</a></li><li id="n-sitesupport"><a href="https://donate.wikimedia.org/wiki/Special:FundraiserRedirector?utm_source=donate&utm_medium=sidebar&utm_campaign=C13_en.wikipedia.org&uselang=en" title="Support us">Donate</a></li><li id="n-shoplink"><a href="//shop.wikimedia.org" title="Visit the Wikipedia store">Wikipedia store</a></li>
|
||||||
</ul>`,
|
`,
|
||||||
'html-after-portal': portletAfter( placeholder( 'Possible hook output (navigation)', 50 ) )
|
'html-after-portal': portletAfter( placeholder( 'Possible hook output (navigation)', 50 ) )
|
||||||
},
|
},
|
||||||
toolbox: {
|
toolbox: {
|
||||||
'portal-id': 'p-tb',
|
id: 'p-tb',
|
||||||
class: 'portal',
|
class: 'vector-menu-portal portal',
|
||||||
'html-tooltip': 'A message tooltip-p-tb must exist for this to appear',
|
'html-tooltip': 'A message tooltip-p-tb must exist for this to appear',
|
||||||
'msg-label': 'Tools',
|
label: 'Tools',
|
||||||
'msg-label-id': 'p-tb-label',
|
'label-id': 'p-tb-label',
|
||||||
'html-userlangattributes': htmluserlangattributes,
|
'html-userlangattributes': htmluserlangattributes,
|
||||||
'html-portal-content': `<ul>
|
'is-portal': true,
|
||||||
|
'html-items': `
|
||||||
<li id="t-whatlinkshere"><a href="/wiki/Special:WhatLinksHere/Spain" title="A list of all wiki pages that link here [⌃⌥j]" accesskey="j">What links here</a></li><li id="t-recentchangeslinked"><a href="/wiki/Special:RecentChangesLinked/Spain" rel="nofollow" title="Recent changes in pages linked from this page [⌃⌥k]" accesskey="k">Related changes</a></li><li id="t-upload"><a href="/wiki/Wikipedia:File_Upload_Wizard" title="Upload files [⌃⌥u]" accesskey="u">Upload file</a></li><li id="t-specialpages"><a href="/wiki/Special:SpecialPages" title="A list of all special pages [⌃⌥q]" accesskey="q">Special pages</a></li><li id="t-permalink"><a href="/w/index.php?title=Spain&oldid=935087243" title="Permanent link to this revision of the page">Permanent link</a></li><li id="t-info"><a href="/w/index.php?title=Spain&action=info" title="More information about this page">Page information</a></li><li id="t-wikibase"><a href="https://www.wikidata.org/wiki/Special:EntityPage/Q29" title="Link to connected data repository item [⌃⌥g]" accesskey="g">Wikidata item</a></li><li id="t-cite"><a href="/w/index.php?title=Special:CiteThisPage&page=Spain&id=935087243" title="Information on how to cite this page">Cite this page</a></li>
|
<li id="t-whatlinkshere"><a href="/wiki/Special:WhatLinksHere/Spain" title="A list of all wiki pages that link here [⌃⌥j]" accesskey="j">What links here</a></li><li id="t-recentchangeslinked"><a href="/wiki/Special:RecentChangesLinked/Spain" rel="nofollow" title="Recent changes in pages linked from this page [⌃⌥k]" accesskey="k">Related changes</a></li><li id="t-upload"><a href="/wiki/Wikipedia:File_Upload_Wizard" title="Upload files [⌃⌥u]" accesskey="u">Upload file</a></li><li id="t-specialpages"><a href="/wiki/Special:SpecialPages" title="A list of all special pages [⌃⌥q]" accesskey="q">Special pages</a></li><li id="t-permalink"><a href="/w/index.php?title=Spain&oldid=935087243" title="Permanent link to this revision of the page">Permanent link</a></li><li id="t-info"><a href="/w/index.php?title=Spain&action=info" title="More information about this page">Page information</a></li><li id="t-wikibase"><a href="https://www.wikidata.org/wiki/Special:EntityPage/Q29" title="Link to connected data repository item [⌃⌥g]" accesskey="g">Wikidata item</a></li><li id="t-cite"><a href="/w/index.php?title=Special:CiteThisPage&page=Spain&id=935087243" title="Information on how to cite this page">Cite this page</a></li>
|
||||||
</ul>`,
|
`,
|
||||||
'html-after-portal': portletAfter( placeholder( 'Possible hook output (tb)', 50 ) )
|
'html-after-portal': portletAfter( placeholder( 'Possible hook output (tb)', 50 ) )
|
||||||
},
|
},
|
||||||
langlinks: {
|
langlinks: {
|
||||||
'portal-id': 'p-lang',
|
id: 'p-lang',
|
||||||
class: 'portal',
|
class: 'vector-menu-portal portal',
|
||||||
'html-tooltip': 'A message tooltip-p-lang must exist for this to appear',
|
'html-tooltip': 'A message tooltip-p-lang must exist for this to appear',
|
||||||
'msg-label': 'In other languages',
|
label: 'In other languages',
|
||||||
'msg-label-id': 'p-lang-label',
|
'label-id': 'p-lang-label',
|
||||||
'html-userlangattributes': htmluserlangattributes,
|
'html-userlangattributes': htmluserlangattributes,
|
||||||
'html-portal-content': `<ul>
|
'is-portal': true,
|
||||||
|
'html-items': `
|
||||||
<li class="interlanguage-link interwiki-ace">
|
<li class="interlanguage-link interwiki-ace">
|
||||||
<a href="https://ace.wikipedia.org/wiki/Seupanyo"
|
<a href="https://ace.wikipedia.org/wiki/Seupanyo"
|
||||||
title="Seupanyo – Achinese" lang="ace" hreflang="ace" class="interlanguage-link-target">Acèh</a>
|
title="Seupanyo – Achinese" lang="ace" hreflang="ace" class="interlanguage-link-target">Acèh</a>
|
||||||
</li><li class="interlanguage-link interwiki-kbd"><a href="https://kbd.wikipedia.org/wiki/%D0%AD%D1%81%D0%BF%D0%B0%D0%BD%D0%B8%D1%8D" title="Эспаниэ – Kabardian" lang="kbd" hreflang="kbd" class="interlanguage-link-target">Адыгэбзэ</a></li><li class="interlanguage-link interwiki-ady"><a href="https://ady.wikipedia.org/wiki/%D0%98%D1%81%D0%BF%D0%B0%D0%BD%D0%B8%D0%B5" title="Испание – Adyghe" lang="ady" hreflang="ady" class="interlanguage-link-target">Адыгабзэ</a></li><li class="interlanguage-link interwiki-af"><a href="https://af.wikipedia.org/wiki/Spanje" title="Spanje – Afrikaans" lang="af" hreflang="af" class="interlanguage-link-target">Afrikaans</a></li><li class="interlanguage-link interwiki-ak"><a href="https://ak.wikipedia.org/wiki/Spain" title="Spain – Akan" lang="ak" hreflang="ak" class="interlanguage-link-target">Akan</a></li><li class="interlanguage-link interwiki-als"><a href="https://als.wikipedia.org/wiki/Spanien" title="Spanien – Alemannisch" lang="gsw" hreflang="gsw" class="interlanguage-link-target">Alemannisch</a></li><li class="interlanguage-link interwiki-am"><a href="https://am.wikipedia.org/wiki/%E1%8A%A5%E1%88%B5%E1%8D%93%E1%8A%95%E1%8B%AB" title="እስፓንያ – Amharic" lang="am" hreflang="am" class="interlanguage-link-target">አማርኛ</a></li><li class="interlanguage-link interwiki-ang"><a href="https://ang.wikipedia.org/wiki/Sp%C4%93onland" title="Spēonland – Old English" lang="ang" hreflang="ang" class="interlanguage-link-target">Ænglisc</a></li><li class="interlanguage-link interwiki-ab"><a href="https://ab.wikipedia.org/wiki/%D0%98%D1%81%D0%BF%D0%B0%D0%BD%D0%B8%D0%B0" title="Испаниа – Abkhazian" lang="ab" hreflang="ab" class="interlanguage-link-target">Аҧсшәа</a></li><li class="interlanguage-link interwiki-ar badge-Q17437798 badge-goodarticle" title="good article"><a href="https://ar.wikipedia.org/wiki/%D8%A5%D8%B3%D8%A8%D8%A7%D9%86%D9%8A%D8%A7" title="إسبانيا – Arabic" lang="ar" hreflang="ar" class="interlanguage-link-target">العربية</a></li><li class="interlanguage-link interwiki-an">
|
</li><li class="interlanguage-link interwiki-kbd"><a href="https://kbd.wikipedia.org/wiki/%D0%AD%D1%81%D0%BF%D0%B0%D0%BD%D0%B8%D1%8D" title="Эспаниэ – Kabardian" lang="kbd" hreflang="kbd" class="interlanguage-link-target">Адыгэбзэ</a></li><li class="interlanguage-link interwiki-ady"><a href="https://ady.wikipedia.org/wiki/%D0%98%D1%81%D0%BF%D0%B0%D0%BD%D0%B8%D0%B5" title="Испание – Adyghe" lang="ady" hreflang="ady" class="interlanguage-link-target">Адыгабзэ</a></li><li class="interlanguage-link interwiki-af"><a href="https://af.wikipedia.org/wiki/Spanje" title="Spanje – Afrikaans" lang="af" hreflang="af" class="interlanguage-link-target">Afrikaans</a></li><li class="interlanguage-link interwiki-ak"><a href="https://ak.wikipedia.org/wiki/Spain" title="Spain – Akan" lang="ak" hreflang="ak" class="interlanguage-link-target">Akan</a></li><li class="interlanguage-link interwiki-als"><a href="https://als.wikipedia.org/wiki/Spanien" title="Spanien – Alemannisch" lang="gsw" hreflang="gsw" class="interlanguage-link-target">Alemannisch</a></li><li class="interlanguage-link interwiki-am"><a href="https://am.wikipedia.org/wiki/%E1%8A%A5%E1%88%B5%E1%8D%93%E1%8A%95%E1%8B%AB" title="እስፓንያ – Amharic" lang="am" hreflang="am" class="interlanguage-link-target">አማርኛ</a></li><li class="interlanguage-link interwiki-ang"><a href="https://ang.wikipedia.org/wiki/Sp%C4%93onland" title="Spēonland – Old English" lang="ang" hreflang="ang" class="interlanguage-link-target">Ænglisc</a></li><li class="interlanguage-link interwiki-ab"><a href="https://ab.wikipedia.org/wiki/%D0%98%D1%81%D0%BF%D0%B0%D0%BD%D0%B8%D0%B0" title="Испаниа – Abkhazian" lang="ab" hreflang="ab" class="interlanguage-link-target">Аҧсшәа</a></li><li class="interlanguage-link interwiki-ar badge-Q17437798 badge-goodarticle" title="good article"><a href="https://ar.wikipedia.org/wiki/%D8%A5%D8%B3%D8%A8%D8%A7%D9%86%D9%8A%D8%A7" title="إسبانيا – Arabic" lang="ar" hreflang="ar" class="interlanguage-link-target">العربية</a></li><li class="interlanguage-link interwiki-an">
|
||||||
</ul>`,
|
`,
|
||||||
'html-after-portal': portletAfter(
|
'html-after-portal': portletAfter(
|
||||||
`<span class="wb-langlinks-edit wb-langlinks-link"><a href="https://www.wikidata.org/wiki/Special:EntityPage/Q29#sitelinks-wikipedia" title="Edit interlanguage links (provided by WikiBase extension)" class="wbc-editpage">Edit links</a></span></div>
|
`<span class="wb-langlinks-edit wb-langlinks-link"><a href="https://www.wikidata.org/wiki/Special:EntityPage/Q29#sitelinks-wikipedia" title="Edit interlanguage links (provided by WikiBase extension)" class="wbc-editpage">Edit links</a></span></div>
|
||||||
${placeholder( `<p>Further hook output possible (lang)</p>`, 60 )}`
|
${placeholder( `<p>Further hook output possible (lang)</p>`, 60 )}`
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
otherProjects: {
|
otherProjects: {
|
||||||
'portal-id': 'p-wikibase-otherprojects',
|
id: 'p-wikibase-otherprojects',
|
||||||
class: 'portal',
|
class: 'vector-menu-portal portal',
|
||||||
'html-tooltip': 'A message tooltip-p-wikibase-otherprojects must exist for this to appear',
|
'html-tooltip': 'A message tooltip-p-wikibase-otherprojects must exist for this to appear',
|
||||||
'msg-label': 'In other projects',
|
label: 'In other projects',
|
||||||
'msg-label-id': 'p-wikibase-otherprojects-label',
|
'label-id': 'p-wikibase-otherprojects-label',
|
||||||
'html-userlangattributes': htmluserlangattributes,
|
'html-userlangattributes': htmluserlangattributes,
|
||||||
'html-portal-content': `<ul>
|
|
||||||
<li class="wb-otherproject-link wb-otherproject-commons"><a href="https://commons.wikimedia.org/wiki/Category:Spain" hreflang="en">Wikimedia Commons</a></li><li class="wb-otherproject-link wb-otherproject-wikinews"><a href="https://en.wikinews.org/wiki/Category:Spain" hreflang="en">Wikinews</a></li><li class="wb-otherproject-link wb-otherproject-wikiquote"><a href="https://en.wikiquote.org/wiki/Spain" hreflang="en">Wikiquote</a></li><li class="wb-otherproject-link wb-otherproject-wikivoyage"><a href="https://en.wikivoyage.org/wiki/Spain" hreflang="en">Wikivoyage</a></li></ul>`,
|
'is-portal': true,
|
||||||
|
'html-items': `
|
||||||
|
<li class="wb-otherproject-link wb-otherproject-commons"><a href="https://commons.wikimedia.org/wiki/Category:Spain" hreflang="en">Wikimedia Commons</a></li><li class="wb-otherproject-link wb-otherproject-wikinews"><a href="https://en.wikinews.org/wiki/Category:Spain" hreflang="en">Wikinews</a></li><li class="wb-otherproject-link wb-otherproject-wikiquote"><a href="https://en.wikiquote.org/wiki/Spain" hreflang="en">Wikiquote</a></li><li class="wb-otherproject-link wb-otherproject-wikivoyage"><a href="https://en.wikivoyage.org/wiki/Spain" hreflang="en">Wikivoyage</a></li>`,
|
||||||
'html-after-portal': ''
|
'html-after-portal': ''
|
||||||
}
|
}
|
||||||
};
|
};
|
|
@ -1,7 +1,7 @@
|
||||||
import { PORTALS, wrapPortlet } from './Portal.stories.data';
|
import { PORTALS, wrapPortlet } from './MenuPortal.stories.data';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Portal'
|
title: 'MenuPortal'
|
||||||
};
|
};
|
||||||
|
|
||||||
export const portal = () => wrapPortlet( PORTALS.example );
|
export const portal = () => wrapPortlet( PORTALS.example );
|
|
@ -1,6 +1,6 @@
|
||||||
import sidebarTemplate from '!!raw-loader!../includes/templates/Sidebar.mustache';
|
import sidebarTemplate from '!!raw-loader!../includes/templates/Sidebar.mustache';
|
||||||
import portalTemplate from '!!raw-loader!../includes/templates/Portal.mustache';
|
import { vectorMenuTemplate } from './MenuDropdown.stories.data';
|
||||||
import { PORTALS } from './Portal.stories.data';
|
import { PORTALS } from './MenuPortal.stories.data';
|
||||||
|
|
||||||
const HTML_LOGO_ATTRIBUTES = `class="mw-wiki-logo" href="/wiki/Main_Page" title="Visit the main page"`;
|
const HTML_LOGO_ATTRIBUTES = `class="mw-wiki-logo" href="/wiki/Main_Page" title="Visit the main page"`;
|
||||||
const SIDEBAR_BEFORE_OUTPUT_HOOKINFO = `Beware: Portals can be added, removed or reordered using
|
const SIDEBAR_BEFORE_OUTPUT_HOOKINFO = `Beware: Portals can be added, removed or reordered using
|
||||||
|
@ -9,7 +9,7 @@ SidebarBeforeOutput hook as in this example.`;
|
||||||
export { sidebarTemplate };
|
export { sidebarTemplate };
|
||||||
|
|
||||||
export const SIDEBAR_TEMPLATE_PARTIALS = {
|
export const SIDEBAR_TEMPLATE_PARTIALS = {
|
||||||
Portal: portalTemplate
|
Menu: vectorMenuTemplate
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SIDEBAR_DATA = {
|
export const SIDEBAR_DATA = {
|
||||||
|
@ -20,7 +20,7 @@ export const SIDEBAR_DATA = {
|
||||||
},
|
},
|
||||||
withPortalsAndOptOut: {
|
withPortalsAndOptOut: {
|
||||||
'has-logo': false,
|
'has-logo': false,
|
||||||
'array-portals-first': PORTALS.navigation,
|
'data-portals-first': PORTALS.navigation,
|
||||||
'data-emphasized-sidebar-action': {
|
'data-emphasized-sidebar-action': {
|
||||||
href: '#',
|
href: '#',
|
||||||
text: 'Switch to old look',
|
text: 'Switch to old look',
|
||||||
|
@ -35,7 +35,7 @@ export const SIDEBAR_DATA = {
|
||||||
},
|
},
|
||||||
withPortals: {
|
withPortals: {
|
||||||
'has-logo': true,
|
'has-logo': true,
|
||||||
'array-portals-first': PORTALS.navigation,
|
'data-portals-first': PORTALS.navigation,
|
||||||
'array-portals-rest': [
|
'array-portals-rest': [
|
||||||
PORTALS.toolbox,
|
PORTALS.toolbox,
|
||||||
PORTALS.otherProjects,
|
PORTALS.otherProjects,
|
||||||
|
|
|
@ -2,7 +2,7 @@ import mustache from 'mustache';
|
||||||
import '../.storybook/common.less';
|
import '../.storybook/common.less';
|
||||||
import '../resources/skins.vector.styles/Sidebar.less';
|
import '../resources/skins.vector.styles/Sidebar.less';
|
||||||
import '../resources/skins.vector.styles/SidebarLogo.less';
|
import '../resources/skins.vector.styles/SidebarLogo.less';
|
||||||
import '../resources/skins.vector.styles/Portal.less';
|
import '../resources/skins.vector.styles/MenuPortal.less';
|
||||||
import { sidebarTemplate, SIDEBAR_DATA, SIDEBAR_TEMPLATE_PARTIALS } from './Sidebar.stories.data';
|
import { sidebarTemplate, SIDEBAR_DATA, SIDEBAR_TEMPLATE_PARTIALS } from './Sidebar.stories.data';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
|
@ -28,19 +28,11 @@
|
||||||
* @prop {string} label-id
|
* @prop {string} label-id
|
||||||
* @prop {string} label
|
* @prop {string} label
|
||||||
* @prop {string} html-items
|
* @prop {string} html-items
|
||||||
|
* @prop {string} [html-tooltip]
|
||||||
* @prop {string} [class] of menu
|
* @prop {string} [class] of menu
|
||||||
* @prop {string} [html-userlangattributes]
|
* @prop {string} [html-userlangattributes]
|
||||||
* @prop {boolean} [is-dropdown]
|
* @prop {boolean} [is-dropdown]
|
||||||
*/
|
* @prop {boolean} [is-portal]
|
||||||
|
* @prop {string} [html-hook-vector-after-toolbox] Deprecated and used by the toolbox portal menu.
|
||||||
/**
|
* @prop {string} [html-after-portal] Additional HTML specific to portal menus.
|
||||||
* @typedef {Object} PortletContext
|
|
||||||
* @prop {string} portal-id
|
|
||||||
* @prop {string} html-tooltip
|
|
||||||
* @prop {string} msg-label-id
|
|
||||||
* @prop {string} [html-userlangattributes]
|
|
||||||
* @prop {string} msg-label
|
|
||||||
* @prop {string} html-portal-content
|
|
||||||
* @prop {string} [html-after-portal]
|
|
||||||
* @prop {string} [html-hook-vector-after-toolbox] Deprecated and used by the toolbox portal.
|
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -161,6 +161,9 @@ class VectorTemplateTest extends MediaWikiIntegrationTestCase {
|
||||||
'html-items' => '',
|
'html-items' => '',
|
||||||
'class' => 'emptyPortlet vector-menu-tabs vectorTabs',
|
'class' => 'emptyPortlet vector-menu-tabs vectorTabs',
|
||||||
'is-dropdown' => false,
|
'is-dropdown' => false,
|
||||||
|
'html-tooltip' => '',
|
||||||
|
'is-portal' => false,
|
||||||
|
'html-after-portal' => ''
|
||||||
] );
|
] );
|
||||||
|
|
||||||
$variants = $props['data-variants'];
|
$variants = $props['data-variants'];
|
||||||
|
|
Loading…
Reference in New Issue