Модуль:HTMLUtils

Материал из Minecraft Wiki
Перейти к: навигация, поиск

Этот модуль предназначен для создания HTML-структур более ёмким способом, чем встроенная в Scribunto библиотека mw.html.

Описание работы[править код]

Этот модуль изменяет создаваемые mw.html объекты, добавляя в них методы с более ёмким синтаксисом. Эти методы, к тому же, автоматически изменяют создаваемые ими объекты.

Этот модуль не изменяет объекты mw.html, возвращаемые стандартными функциями, или объекты, полученные извне, но в модуле содержится функция для внедрения методов в такие объекты.

Ряд функций этого модуля принимает селекторы, позволяющие сразу задать тип элемента, HTML-идентификатор и фиксированные CSS-классы. Формат селекторов модуля похож на селекторы CSS.

Селекторы, принимаемые этим модулем, состоят из одной или нескольких частей, которые на усмотрение пользователя могут быть разделены пробелами. Сами части пробелов содержать не могут. Первая часть должна состоять исключительно из названия элемента (например span или div). Последующие части должны начинаться или на точку (.), за которой следует название CSS-класса, или на знак решётки (#), за которым следует HTML-идентификатор.

Примеры селекторов:

  • div — элемент div без особых свойств, но с поддержкой расширенных методов этого модуля
  • span.invslot — элемент span с классом invslot
  • table .wikitable .collapsible .collapsed #item-list — таблица (table) с классами wikitable, collapsible и collapsed, а также идентификатором item-list

Функции[править код]

Функции, которые вызываются из модуля, обозначены как p.function_name. Функции, которые вызываются из объектов, возвращаемых модулем (то есть в дополнение к стандартным функциям mw.html), обозначены как node:function_name.

p.make_node, p.make_node_fmt[править код]

Синтаксис:

  • p.make_node(selector, ...)
  • p.make_node_fmt(selector, fmt, ...)

Эти две функции создают элемент mw.html с возможностью сразу задать классы и идентификатор через селектор selector, а также установить начальный текст. В функции make_node после селектора может следовать произвольное число аргументов, добавляемых в элемент как вики-текст (что эквивалентно стандартному методу mw.html:wikitext(...)). В варианте make_node_fmt после селектора идёт строка-формат, которая передаётся стандартной функции string.format вместе со всеми аргументами, которые следуют после строки-формата.

Пример:

local html = require("Module:HTMLUtils")
-- ...

local node = html.make_node("div .greeting", "Добрый день, ", name, "!")
-- что то же самое, что:
local node_fmt = html.make_node_fmt("div .greeting", "Добрый день, %s!", name)

-- или со стандартными функциями:
local std_node = mw.html.create("div")
    :addClass("greeting")
    :wikitext("Добрый день, ", name, "!")
local std_node_fmt = mw.html.create("div")
    :addClass("greeting")
    :wikitext(string.format("Добрый день, %s!", name))

p.inject_methods[править код]

Берёт объект mw.html и внедряет в него методы, добавляемые этим модулем. Возвращает изменённый объект.

local html = require("Module:HTMLUtils")
local another = require("Module:SomeOtherModule")
-- ...

-- функция another.make_html не использует HTMLUtils, и возвращаемый ей объект
-- mw.html не поддерживает расширенные методы из этого модуля
local node = html.inject_methods(another.make_html())

-- но после вызова inject_methods этот объект может быть передан методам HTMLUtils
node:sel_node("div .test", "Привет, мир!")

node:sel_node, node:sel_node_fmt[править код]

Эти две функции эквивалентны стандартному методу mw.html:node, но внедряют методы HTMLUtils. Синтаксис аналогичен таковым у make_node и make_node_fmt.

local html = require("Module:HTMLUtils")
-- ...

-- все три вызова идентичны
local wrapper = html.make_node("div .wrapper")
    :sel_node("div .greeting", "Добрый день, ", name, "!")
    :sel_node_fmt("div .greeting", "Добрый день, %s!", name)
    :node(mw.html.create("div")
        :addClass("greeting")
        :wikitext("Добрый день, ", name, "!")
    )

-- Обратите внимание, что стандартный метод :node возвращает тот же объект,
-- то есть методы HTMLUtils не исчезают.

node:sel_tag, node:sel_tag_fmt[править код]

Эти две функции эквивалентны стандартному методу mw.html:tag, но внедряют методы HTMLUtils. Синтаксис аналогичен таковым у make_node и make_node_fmt.

local html = require("Module:HTMLUtils")
-- ...

-- все три вызова идентичны
local wrapper = html.make_node("div .wrapper")
    :sel_tag("div .greeting", "Добрый день, ", name, "!")
        :done()
    :sel_tag_fmt("div .greeting", "Добрый день, %s!", name)
        :done()
    :tag("div")
        :addClass("greeting")
        :wikitext("Добрый день, ", name, "!")
        :done()

-- Обратите внимание, что стандартный метод :tag создаёт новый объект,
-- и методы HTMLUtils на этот новый объект не переносятся. При этом :done
-- возвращает уже созданный объект, из которого методы HTMLUtils не убираются.
local p = {}

local node_methods = {
	"sel_node",
	"sel_tag",
	"sel_node_fmt",
	"sel_tag_fmt"
}

local inner = {}

function inner.parse_selector(selector)
	local element, remainder = selector:match("^%s*(%w+)%s*(.-)%s*$")
	if not element then
		return nil
	end
	local parts = {}
	local part
	while remainder and remainder ~= "" do
		part, remainder = remainder:match("^([#%.][^ %.#]+)%s*(.-)$")
		table.insert(parts, part)
	end
	
	local id
	local classes = {}
	for _, part in ipairs(parts) do
		if part:sub(1, 1) == "#" then
			if id then
				mw.log("Warning: Redefining ID")
			end
			id = part:sub(2)
		else -- class
			table.insert(classes, part:sub(2))
		end
	end
	return element, id, classes
end

function inner.modify_node(node, id, classes, ...)
	node:attr("id", id)
	for _, class in ipairs(classes) do
		node:addClass(class)
	end
	node:wikitext(...)
	p.inject_methods(node)
	
	return node
end

function inner.sel_node(self, selector, ...)
	self:node(p.make_node(selector, ...))
	return self
end

function inner.sel_tag(self, selector, ...)
	local element, id, classes = inner.parse_selector(selector)
	return inner.modify_node(self:tag(element), id, classes, ...)
end

function inner.sel_node_fmt(self, selector, fmt, ...)
	return self:sel_node(selector, fmt:format(...))
end

function inner.sel_tag_fmt(self, selector, fmt, ...)
	return self:sel_tag(selector, fmt:format(...))
end

function p.inject_methods(node)
	for _, method in ipairs(node_methods) do
		node[method] = node[method] or inner[method]
	end
	return node
end

function p.make_node(selector, ...)
	local element, id, classes = inner.parse_selector(selector)
	return inner.modify_node(mw.html.create(element), id, classes, ...)
end

function p.make_node_fmt(selector, fmt, ...)
	return p.make_node(selector, fmt:format(...))
end

return p