Module:Magenta message

From PickiPedia: A knowledge base of bluegrass, old time psychedelic jams, and other public domain music
Jump to navigationJump to search

Documentation for this module may be created at Module:Magenta message/doc

-- A magenta message, shown on PickiPedia as a card: who said it, where (its Mood), when (its date and
-- its Ethereum block), and its words -- as many characters as `chars` asks (280 unless told; "all" for
-- every one) -- with a link to the message in its Mood. Used by [[Template:Magenta message]].
--
-- The words travel inside the template call, written there by magenta with every character that wikitext
-- would read as markup turned into an entity (& < > { } | [ ] ~), so a message's own pipes, braces and
-- tildes can't break the call. They are decoded here and shown exactly as said: nothing in them is a link,
-- a template or a heading. (magenta: memory-lane conversations/services/wiki_embed.py writes the call.)

local p = {}

local MAGENTA = 'https://magenta.cryptograss.live'
local DEFAULT_CHARS = 280

local function arg(args, name)
	local v = args[name]
	if v == nil then return '' end
	return mw.text.trim(v)
end

-- The words cut to `chars` characters, at a word's end where one is near, with an ellipsis; and whether cut.
local function trimmed(text, chars)
	if chars == 'all' then return text, false end
	local n = tonumber(chars) or DEFAULT_CHARS
	if n < 1 or mw.ustring.len(text) <= n then return text, false end
	local cut = mw.ustring.sub(text, 1, n)
	local lastSpace = mw.ustring.find(cut, '%s%S*$')
	if lastSpace and lastSpace > n * 0.6 then
		cut = mw.ustring.sub(cut, 1, lastSpace - 1)
	end
	cut = mw.ustring.gsub(cut, '[%s%p]+$', '')
	return cut .. '…', true
end

-- Exactly as said: escaped, line breaks kept.
local function literal(text)
	local lines = {}
	for line in mw.text.gsplit(text, '\n', true) do
		table.insert(lines, mw.text.nowiki(line))
	end
	return table.concat(lines, '<br>')
end

local function when(at)
	if at == '' then return '' end
	local ok, shown = pcall(function()
		return mw.getContentLanguage():formatDate('j M Y, H:i', at, false) .. ' UTC'
	end)
	return ok and shown or at
end

function p.card(frame)
	local args = frame:getParent().args
	local id = arg(args, 'id')
	if id == '' then id = arg(args, 1) end
	if not id:match('^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$') then
		return '<strong class="error">Magenta message: id= wants a message id (the part after #m- in its link)</strong>'
	end
	local who, user, mood = arg(args, 'who'), arg(args, 'user'), arg(args, 'mood')
	local block, at = arg(args, 'block'), arg(args, 'at')
	local text = mw.text.trim(mw.text.decode(args.text or '', true))
	local shown, cut = trimmed(text, arg(args, 'chars'))
	local here = MAGENTA .. '/messages/' .. id

	local head = {}
	if who ~= '' then
		table.insert(head, user ~= '' and ('[[User:' .. user .. '|' .. who .. ']]') or ("'''" .. who .. "'''"))
	end
	if mood ~= '' then
		table.insert(head, '[' .. MAGENTA .. '/moods/' .. mood .. '/ #' .. mood .. ']')
	end
	if at ~= '' then
		table.insert(head, '[' .. here .. ' ' .. when(at) .. ']')
	end
	if block:match('^%d+$') then
		table.insert(head, '[https://etherscan.io/block/' .. block .. ' block '
			.. mw.getContentLanguage():formatNum(tonumber(block)) .. ']')
	end

	local box = mw.html.create('div')
		:addClass('magenta-message')
		:attr('data-message', id)
		:css({
			['border-left'] = '3px solid #d6249f',
			['border-radius'] = '4px',
			['background'] = 'rgba(214, 36, 159, 0.06)',
			['padding'] = '6px 12px',
			['margin'] = '8px 0',
		})
	box:tag('div')
		:addClass('magenta-message-head')
		:css({ ['font-size'] = '85%', ['opacity'] = '0.8' })
		:wikitext(table.concat(head, ' · '))
	box:tag('div')
		:addClass('magenta-message-words')
		:css({ ['margin'] = '4px 0 2px' })
		:wikitext(shown ~= '' and literal(shown) or "''(no words)''")
	box:tag('div')
		:css({ ['font-size'] = '85%' })
		:wikitext('[' .. here .. ' ' .. (cut and 'the rest, in the Mood ↗' or 'in the Mood ↗') .. ']')
	return tostring(box)
end

return p