Jump to content
Menú alternativo
Alternar el menú de preferencias
Menú alternativo personal
No has accedido
Tu dirección IP será visible si haces alguna edición

La documentación para este módulo puede ser creada en Módulo:Mainpage/Hero/doc

require('strict')

--- @module Mainpage/Hero
--- The full-bleed hero band: patch status, wiki statline, lede, search trigger
--- and the chip strip.
---
--- NOTHING here fetches the artwork. The band carries the image URL in a
--- `data-gadget-mainpage-hero-src` attribute and the `mainpage` gadget
--- ([[MediaWiki:Gadget-mainpage.js]]) loads it after `window.load`, fading it in
--- by adding `home-hero--loaded`. That is what keeps a 1920px photograph off the
--- critical path and lets the band render — legibly, over its own ground colour
--- — for a reader on Save-Data or with scripts off.
---
--- The gadget hooks are all `data-gadget-mainpage-*`, per the house convention:
--- prefixing by gadget name means `grep gadget-mainpage-` finds every emitter
--- and the one gadget that consumes them.
---
--- Everything variable here comes from [[Module:Mainpage/settings.json]].

local cfg = require('Module:Mainpage/Config')
local nav = require('Module:Mainpage/Nav')

--- Width of the thumbnail handed to the gadget. Large enough for a 2x 960px
--- band; the gadget requests it lazily so the size costs nothing up front.
local HERO_WIDTH = '1920'

local p = {}

--- The build chips, one per entry in `patches`. The live build takes the
--- filled marker and the live colour, every other channel the hollow one —
--- and WHICH entry is live is Config's answer, not one computed here, so the
--- chip and the patch card below can never disagree.
---
--- An entry with no name is skipped, and with none left the strip is not
--- emitted at all rather than rendered empty.
---
--- @param root mw.html
local function renderStatus(root)
	local status = mw.html.create('div'):addClass('home-hero__status')
	local live = cfg.livePatch()
	local any = false

	for _, patch in ipairs(cfg.list('patches')) do
		if patch.name then
			local isLive = patch == live
			local label = patch.channel and (patch.channel .. ' ' .. patch.name) or patch.name

			status:tag('span'):addClass(isLive and 'home-hero__status-live' or 'home-hero__status-ptu'):wikitext(
				(isLive and '●' or '◌')
					.. ' '
					.. (patch.page and string.format('[[%s|%s]]', patch.page, label) or label)
			)
			any = true
		end
	end

	if any then
		root:node(status)
	end
end

--- @param content mw.html
--- @param frame mw.frame
local function renderSearch(content, frame)
	local tails = cfg.section('hero').searchTails or {}

	-- `role="button"` and not a real <button>: the element opens Citizen's own
	-- search overlay, which the skin binds by the `citizen-search-trigger`
	-- class. A <button> here would be a second, competing control.
	local search = content
		:tag('div')
		:addClass('home-hero__search')
		:addClass('citizen-search-trigger')
		:attr('role', 'button')
		:wikitext('[[File:Codex_icon_search_color-placeholder_(v2.6).svg|16px|link=|alt=]]')

	local label = search:tag('span'):addClass('home-hero__search-label')
	label:wikitext('Busca&nbsp;')

	local tail = label:tag('span'):addClass('home-hero__search-tail')
	if tails[1] ~= nil then
		-- The tail the gadget rolls through. The FIRST value is also what is
		-- rendered here, so the server-side text is one of the real phrases
		-- rather than a placeholder that flashes and is replaced.
		tail:attr('data-gadget-mainpage-search-tails', table.concat(tails, '|'))
		tail:wikitext(tails[1])
	else
		tail:wikitext('en esta wiki')
	end

	search:wikitext(frame:expandTemplate({ title = 'Key press', args = { '/' } }))
end

--- @param content mw.html
local function renderChips(content)
	local strip = content:tag('div'):addClass('home-hero__tabs')
	for _, chip in ipairs(nav.chips()) do
		local wikitext = nav.renderLink(chip)
		if wikitext then
			strip:wikitext(wikitext)
		end
	end
end

--- @class HeroProps
--- @field lazyArt? boolean  Emit the gadget's artwork hook. False renders the
---        band exactly as a reader with no JavaScript, or with Save-Data on,
---        receives it: no artwork is ever fetched.

--- @param props HeroProps
--- @return string
function p.render(props)
	props = props or {}
	local frame = mw.getCurrentFrame()

	local root = mw.html.create('div'):addClass('home-band'):addClass('home-hero')

	if props.lazyArt ~= false then
		local image = cfg.section('hero').image
		if image then
			root:attr('data-gadget-mainpage-hero-src', frame:callParserFunction('filepath', { image, HERO_WIDTH }))
		end
	end

	-- Both are empty and both are painted entirely in CSS: the media box is
	-- where the gadget puts the photograph, the scrim is the gradient that
	-- keeps the text legible over whatever the photograph turns out to be.
	root:tag('div'):addClass('home-hero__media')
	root:tag('div'):addClass('home-hero__scrim')

	renderStatus(root)

	-- home-band__inner is the measured column every band shares, so the hero's
	-- text lines up with the cards below it.
	local content = root:tag('div'):addClass('home-band__inner'):addClass('home-hero__content')

	renderStatline(content)

	-- The trailing space is load-bearing: the two halves are one sentence set in
	-- two tones, and mw.html concatenates its children with nothing between
	-- them, so without it the dim half would butt against the bright one.
	local hero = cfg.section('hero')
	content
		:tag('div')
		:addClass('home-hero__title')
		:wikitext((hero.lede or 'Espacio de trabajo de Wikimedia Small Projects.') .. ' ')
		:tag('span')
		:addClass('home-hero__title-dim')

	renderSearch(content, frame)
	renderChips(content)

	return tostring(root)
end

return p