Создание разделов с помощью Scribunto со ссылкой редактирования
Я пытаюсь создать модуль Scribunto, который, помимо прочего, может создать заголовок раздела в своем выводе.
Если возвращаемая строка содержит, например, == Hello World ==
Полученная страница правильно отображает раздел и даже включает раздел в оглавление. Однако в разделе нет ссылки на раздел редактирования.
В некоторой степени это понятно; раздел на самом деле не существует в источнике страницы. Но я хотел бы иметь возможность разместить ссылку для редактирования, откуда исходит содержание раздела. Я пробовал две разные версии buildHeader
функция:
-- version 1:
function p.buildHeader(level, title, page)
local open = '<span class="mw-editsection-bracket">[</span>'
local close = '<span class="mw-editsection-bracket">]</span>'
local link = '<a href="/w/index.php?title='..p.urlsafe(page)..'&action=edit" title="Edit section: '..title..'">edit</a>'
local edit = '<span class="mw-editsection">'..open..link..close..'</span>'
local text = '<span id="'..p.urlsafe(title)..'" class="mw-headline">'..title..'</span>'
return '<h'..level..'>'..title..edit..'</h'..level..'>'
end
-- version 2:
function p.buildHeader(level, title, page)
local result = mw.html.create('h'..level)
result:tag('span')
:attr({id=p.urlsafe(title), class='mw-headline'})
:wikitext(title)
:done()
:tag('span')
:attr('class', 'mw-editsection'):tag('span')
:attr('class', 'mw-editsection-bracket')
:wikitext('[')
:done()
:tag('a')
:attr({href='/w/index.php?title='..p.urlsafe(page)..'&action=edit', title='Edit section: '..title})
:wikitext('edit')
:done()
:tag('span')
:attr('class', 'mw-editsection-bracket')
:wikitext(']')
:allDone()
return tostring(result)
end
В обоих случаях HTML тега привязки был экранирован (например, <span class="mw-editsection">...<a href="..." title="...">edit</a></span>
), и весь раздел mw-editsection был включен в текст оглавления.
Есть ли способ для меня, чтобы получить мою произвольную ссылку редактирования там, или я должен жить с разделами Scribunto без редактирования разделов?
2 ответа
Мое рабочее решение (но не мое предпочтительное решение) - вставить ссылку с помощью JavaScript. buildHeader
функция становится:
function p.buildHeader(level, title, page)
local result = mw.html.create('h'..level)
result:attr('data-source', page):wikitext(title)
return tostring(result)
end
Затем в MediaWiki:Common.js я добавляю:
$('h1[data-source],h2[data-source],h3[data-source],h4[data-source],h5[data-source],h6[data-source]').append(function() {
var source = $(this).data('source'),
title = $(this).text(),
$editsection = $('<span>').attr('class', 'mw-editsection'),
$open = $('<span>').attr('class', 'mw-editsection-bracket').text('['),
$close = $('<span>').attr('class', 'mw-editsection-bracket').text(']'),
$link = $('<a>').attr('title', 'Edit section: ' + title)
.attr('href', '/w/index.php?title=' + source + '&action=edit')
.text('edit');
$editsection.append($open).append($link).append($close);
return $editsection;
});
То, что вы пытаетесь сделать, почти возможно без JavaScript, но не совсем.
Попытка № 1: нормальные заголовки
Во-первых, причина проста == Hello World ==
Scribunto не работает из-за того, что вики-текст, который вы генерируете в Scribunto, автоматически не обрабатывается анализатором MediaWiki автоматически. Из документов Scribunto:
Функция модуля обычно должна возвращать одну строку; все возвращаемые значения будут переданы через tostring(), а затем объединены без разделителя. Эта строка включена в вики-текст как результат
{{#invoke:}}
,На этом этапе анализа страницы шаблоны уже были расширены, функции синтаксического анализатора и теги расширения уже обработаны, а преобразования перед сохранением (например, расширение подписи тильды и трюк канала) уже произошли. Поэтому модуль не может использовать эти функции в своем выходном тексте. Например, если модуль возвращает
"Hello, [[world]]! {{welcome}}"
, на странице будет написано "Привет, мир! {{welcome}}".
Чтобы обойти это, вы можете использовать метод Scribunto frame: preprocess для предварительной обработки строк с помощью анализатора MediaWiki перед их выводом. Например, предварительная обработка == Hello World ==
зарегистрирует заголовок с помощью анализатора и добавит маркер полосы перед заголовком заголовка. Затем в процессе синтаксического анализа анализатор удаляет маркер полосы и добавляет ссылку на раздел редактирования.
Вы можете сделать это с помощью следующего кода модуля:
local p = {}
function p.main(frame)
return frame:preprocess("== Hello World ==")
end
return p
Когда этот код вызывается на вики-странице, он дает вам законную ссылку для редактирования MediaWiki. К сожалению, это ссылка на первый раздел на странице модуля, и нажатие на нее приведет к ошибке "редактирование раздела не поддерживается".
Вы можете обойти это, используя другой объект кадра для выполнения предварительной обработки. Если вы хотите, чтобы ссылка раздела редактирования указывала на страницу, с которой вы вызвали модуль, вы можете использовать родительский фрейм:
local p = {}
function p.main(frame)
return frame:getParent():preprocess("== Hello World ==")
end
return p
И если вы хотите, чтобы ссылка указывала на произвольную страницу, вы можете создать новый дочерний фрейм:
local p = {}
function p.main(frame)
local childFrame = frame:newChild{title = "Your page here"}
return childFrame:preprocess("== Hello World ==")
end
return p
Проблема с двумя приведенными выше примерами заключается в том, что они оба указывают на первый раздел на странице - и заголовки разделов, добавленные через #invoke, не учитываются в счетчике разделов. Поэтому, если вы не знаете, что вам нужно редактировать первый раздел, эти ссылки не будут работать для вас. К сожалению, я не знаю ни одного способа изменить номер раздела ссылок редактирования, сгенерированных таким образом.
Попытка № 2: поддельные заголовки
Вы были довольно близки к тому, чтобы попытаться эмулировать заголовок HTML. Проблема в том, что MediaWiki не позволяет <a>
теги в викитексте для предотвращения атак межсайтовых скриптов. Вы можете легко обойти это, используя синтаксис внешней ссылки MediWiki ([http://www.example.com Example]
).
Вот что-то ближе к тому, к чему вы стремились:
local p = {}
function p.makeHeading(title, page)
local result = mw.html.create('h2')
result
:tag('span')
:attr({id = title, class='mw-headline'})
:wikitext(title)
:done()
:tag('span')
:addClass('mw-editsection')
:addClass('plainlinks')
:tag('span')
:attr('class', 'mw-editsection-bracket')
:wikitext('[')
:done()
:wikitext(string.format(
'[%s %s]',
tostring(mw.uri.fullUrl(page, {action = 'edit'})),
'edit'
))
:tag('span')
:attr('class', 'mw-editsection-bracket')
:wikitext(']')
return tostring(result)
end
return p
Это даст вам заголовок, который ссылается на нужное место и выглядит почти так же, как оригинал. Есть только две проблемы:
- Цвет ссылки немного неправильный. В MediaWiki внешние ссылки имеют немного другой цвет по сравнению с внутренними ссылками. Здесь мы используем "внешнюю" ссылку на URL-адрес режима редактирования страницы, но ссылки для редактирования, сгенерированные MediaWiki, получают цвет внутренней ссылки. Можно обойти это с разумным использованием стилей, но это оставляет проблему номер два:
- Текст "[edit]" включен в оглавление.
К сожалению, я не знаю, как сохранить текст "[edit]" вне оглавления без использования JavaScript. Таким образом, единственное решение, которое будет работать надежно и заставит все выглядеть правильно, - это использовать JavaScript, как вы это сделали.