Создание разделов с помощью 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">...&lt;a href="..." title="..."&gt;edit&lt;/a&gt;</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

Это даст вам заголовок, который ссылается на нужное место и выглядит почти так же, как оригинал. Есть только две проблемы:

  1. Цвет ссылки немного неправильный. В MediaWiki внешние ссылки имеют немного другой цвет по сравнению с внутренними ссылками. Здесь мы используем "внешнюю" ссылку на URL-адрес режима редактирования страницы, но ссылки для редактирования, сгенерированные MediaWiki, получают цвет внутренней ссылки. Можно обойти это с разумным использованием стилей, но это оставляет проблему номер два:
  2. Текст "[edit]" включен в оглавление.

К сожалению, я не знаю, как сохранить текст "[edit]" вне оглавления без использования JavaScript. Таким образом, единственное решение, которое будет работать надежно и заставит все выглядеть правильно, - это использовать JavaScript, как вы это сделали.

Другие вопросы по тегам