
Свободного времени становится всё меньше и меньше, поэтому перейду сразу к делу.
В прошлых статьях я обещал поделиться еще парой приёмов по настройке XWiki, которую я использую как портал для технической документации.
Лучше поздно чем никогда, поэтому сегодня мы:
Я буду давать минимум пояснений, ибо стал забывать, что да как. Примеры должны работать для XWiki 12.10.10 и 13.10.2.
Чиним связку ShowHide macro и аннотации
Популярный макрос ShowHide при добавлении аннотаций к тексту страницы перестает реагировать на клик мышью.
Это связано с особенностями отображения контента аннотированной страницы.
За помощь с решением проблемы большое спасибо @alexkhotkevich.
Для начала включите в настройках пользователя отображение скрытых страниц или просто нажмите комбинацию x+x+x+h
.
Затем перейдите на страницу {XwikiURL)/bin/view/Macros/ShowHideMacro
Откройте редактор объектов и в объекте JavaScriptExtension
замените код на следующий:
require(['jquery'], function($) {
function onClick () {
var button = $(this),
content = button.parent().next(),
effect = button.attr('data-show-effect'),
data = button.data();
if($.inArray(effect,['toggle','fadeToggle','slideToggle']) == -1) effect = 'toggle';
data.showHideState = !(('showHideState' in data) ? data.showHideState : content.is(':visible'));
button.html(button.attr(data.showHideState ? 'data-hide-message' : 'data-show-message'));
content.stop()[effect](parseInt(button.attr('data-show-duration')));
return false;
}
$(document).on('xwiki:dom:updated',
function(){
$('.showhidebutton').children('a').off('click');
$('.showhidebutton').children('a').click(onClick);
}
)
});
Получится вот так:

Не забудьте сохранить.
Чиним проблемы с поиском
Иногда полезно запустить индексацию. Перейдите в раздел "Поиск" в админ-панели, ничего не меняйте и нажмите кнопку "Подтвердить".
Через некоторое время отобразится прогресс индексации (если нет обновите страницу).

Меняем шаблон страницы авторизации
Создадим свой скин. Для начала создайте пустую страницу и добавьте к ней объект XWikiSkins
с любым названием и базовым скином flamingo

Сохраните страницу и закройте редактор объектов. На странице скина перейдите по ссылке "Редактировать скин".
Переопределите шаблон login.vm
и вставьте этот код:
Показать код
## ---------------------------------------------------------------------------
## See the NOTICE file distributed with this work for additional
## information regarding copyright ownership.
##
## This is free software; you can redistribute it and/or modify it
## under the terms of the GNU Lesser General Public License as
## published by the Free Software Foundation; either version 2.1 of
## the License, or (at your option) any later version.
##
## This software is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
## Lesser General Public License for more details.
##
## You should have received a copy of the GNU Lesser General Public
## License along with this software; if not, write to the Free
## Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
## 02110-1301 USA, or see the FSF site: http://www.fsf.org.
## ---------------------------------------------------------------------------
#if ($xcontext.user != 'XWiki.XWikiGuest')
#if ($request.xredirect)
$response.sendRedirect($request.xredirect)
#else
$response.sendRedirect($xwiki.getURL($services.model.resolveDocument('', 'default', $doc.documentReference.extractReference('WIKI'))))
#end
#elseif($doc.fullName != 'XWiki.XWikiLogin')
#set($qs = "$!{request.queryString}")
#if(!$request.getParameter('xredirect'))
#set($qs = "xredirect=$escapetool.url($doc.getURL('view'))&${qs}")
#end
$response.sendRedirect($xwiki.getURL('XWiki.XWikiLogin', 'login', $qs))
#else
###
### Login page
###
###
#template("startpage.vm")
<div class="main layoutsubsection">
<div id="mainContentArea">
<form id="loginForm" action="$doc.getURL('loginsubmit')" method="post" class="xform">
<div class="hidden"><input type="hidden" name="xredirect" value="$!{escapetool.xml($request.xredirect)}"/>
#if("$!request.srid" != '')
<input type="hidden" name="srid" value="$!escapetool.xml($request.srid)"/>
#end
<input type="hidden" name="form_token" value="$!{services.csrf.getToken()}"/>
</div>
#xwikimessageboxstart($services.localization.render('login') '')
#set($message = $xcontext.message)
#if($message)
<!-- previous login errors -->
#error($services.localization.render($message))
#end
#set($authFailureStrategyMessage = $services.security.authentication.getErrorMessage($request.j_username))
#if ("$!authFailureStrategyMessage" != '')
#error($authFailureStrategyMessage)
#end
#set ($supplementaryForm = $services.security.authentication.getForm($request.j_username))
<dl>
<dt>
<label for="j_username">$services.localization.render('username')</label>
#if($xwiki.exists('XWiki.ForgotUsername') && $xwiki.hasAccessLevel('view', 'XWiki.ForgotUsername'))
<span class="xAdditional"><a href="$xwiki.getURL('XWiki.ForgotUsername')" tabindex="500">$services.localization.render('xe.admin.forgotUsername.loginMessage')</a></span>
#end
</dt>
<dd class="input-group">
<span class="input-group-addon">$services.icon.renderHTML('user')</span>
<input class="form-control" type="text" id="j_username" size="60" name="j_username" value="" tabindex="100"/>
</dd>
<dt>
<label for="j_password">$services.localization.render('password')</label>
#if($xwiki.exists('XWiki.ResetPassword') && $xwiki.hasAccessLevel('view', 'XWiki.ResetPassword'))
<span class="xAdditional"><a href="$xwiki.getURL('XWiki.ResetPassword')" tabindex="600">$services.localization.render('xe.admin.passwordReset.loginMessage')</a></span>
#end
</dt>
<dd class="input-group">
<span class="input-group-addon">$services.icon.renderHTML('lock')</span>
<input type="password" id="j_password" size="60" name="j_password" value="" tabindex="200"/>
</dd>
<dt></dt>
<dd>
<label class="xHint" for="rememberme">
<input id="rememberme" type="checkbox" name="j_rememberme" value="true" tabindex="300"/> $services.localization.render('remembermeonthiscomp')
</label>
</dd>
#if ("$!supplementaryForm" != "")
<div id="dedicated-auth-failures-field">
$supplementaryForm
</div>
#end
<dt><input type="submit" class="btn btn-primary col-xs-12" value="$services.localization.render('login')" tabindex="400"/></dt>
</dl>
#xwikimessageboxend()
</form>
</div>## mainContentArea
</div>## main
## Ensure that the username field of the login form has the focus to make it easy for users to log in quickly
<script>
//<![CDATA[
document.forms.loginForm.j_username.focus();
//]]>
</script>
<div id="customLogin"> ## info about wiki admins
<h2> Xwiki </h2>
Это мой скин страницы для входа, а это мой профиль на <a href="https://habr.com/ru/users/BosonBeard/">Habr</a>
</div>
<style>
#customLogin{
max-width: 450px;
margin:auto;
}
#customLoginOlimp h2{
color:#999;
}
</style>
#template("endpage.vm")
#end
Код шаблона login.vm
из репозитория темы flamingo, я лишь немного его модифицировал для примера.
Остаётся только выбрать новый скин в параметрах темы.

Проверяем страницу входа

Оглавление страницы в боковой панели
Просто создайте панель со следующим кодом и разместите её в боковой панели (про панели см. в прошлой статье).
{{velocity}}
{{context document="$services.model.serialize($doc.documentReference)" transformationContext="document"}}
#set ($hasHeaders = [])
#set ($mydoc = $doc.getDocument())
#foreach ($block in $mydoc.getXDOM().getBlocks('class:HeaderBlock', 'DESCENDANT'))
#set ($discard = $hasHeaders.add($block))
#end
#if($hasHeaders.size()>0)
#panelheader('Table of Contents')
{{box cssClass="righttoc"}}{{toc/}}{{/box}}
#end
{{/context}}
{{/velocity}}

Панель будет скрыта, если на странице нет оглавления.
Устанавливаем пакет из расширенного поиска и размещаем Swagger на странице
Иногда нужно установить расширения, которые не находит обычный поиск.
Для начала найдем нужный WebJar в репозитории.
Мы возьмем для примера Swagger UI 4.4.1
Откроем расширенный поиск и введем название и версию файла из описания:

Установите расширение.
Создайте пустую страницу.
Добавьте к ней вложение (у меня это swagger.json).
Откройте редактор, перейдите в режим редактирования исходного кода и вставьте этот код:
Открыть код
{{velocity}}
#set ($discard = $xwiki.linkx.use($services.webjars.url('swagger-ui', 'swagger-ui.css',
{'evaluate': true}), {'type': 'text/css', 'rel': 'stylesheet'}))
{{html clean=false}}
<style type="text/css">
hgroup.main {
left:0px !important;
}
hgroup.main a {
word-wrap: break-word !important;
}
</style>
<div id="status">Загрузка Swagger</div>
<div id="swagger-ui">...</div>
<script>
var swaggerContainer = document.getElementById("swagger-ui")
swaggerContainer.style.display="none";
swagerContent = swaggerContainer.textContent
require.config({
paths: {
SwaggerUIBundle: "$services.webjars.url('swagger-ui','swagger-ui-bundle')",
SwaggerUIStandalonePreset: "$services.webjars.url('swagger-ui','swagger-ui-standalone-preset')"
}
});
require(["SwaggerUIBundle","SwaggerUIStandalonePreset"], function(SwaggerUIBundle,SwaggerUIStandalonePreset) {
statusDom=document.getElementById("status");
statusDom.textContent = 'Вставка Swagger...'
window.onload = function(){
// Begin Swagger UI call region
// Don't forget to change url.
const ui = SwaggerUIBundle({
url:"http://localhost:8080/bin/download/%D0%9F%D1%80%D0%BE%D1%87%D0%B0%D1%8F%20%D0%B4%D0%BE%D0%BA%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D0%B0%D1%86%D0%B8%D1%8F/%D0%9F%D1%80%D0%BE%D0%B2%D0%B5%D1%80%D0%BA%D0%B0%20%D0%B3%D0%B8%D0%BF%D0%BE%D1%82%D0%B5%D0%B7%20%28%D1%82%D0%B5%D1%85%D0%BF%D0%B8%D1%81%29/Test%20Swagger/WebHome/swagger.json",
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
});
// End Swagger UI call region
window.ui = ui;
statusDom.textContent = '';
statusDom.style.display="none";
swaggerContainer.style.display="block";
};
});
</script>
{{/html}}{{/velocity}}
Не забудьте в url указать вашу ссылку на вложение.
Это вариант кода "на скорую руку" если будет время, в следующих статьях я покажу как сделать макрос для вставки Swagger.

Спасибо, что прочитали до конца. Надеюсь, что мои рецепты кому-то будут полезны.