Module:Stonecutting: Difference between revisions
Jump to navigation
Jump to search
No edit summary |
No edit summary |
||
| Line 1: | Line 1: | ||
------------------------------------------------------------ | ------------------------------------------------------------ | ||
-- Stone-cutter recipe carousel | -- Stone-cutter recipe carousel | ||
------------------------------------------------------------ | ------------------------------------------------------------ | ||
local p = {} | local p = {} | ||
local getArgs = require('Module:Arguments').getArgs | |||
local getArgs = require( 'Module:Arguments' ).getArgs | |||
local trim = mw.text.trim | local trim = mw.text.trim | ||
------------------------------------------------------------------------ | ------------------------------------------------------------------------ | ||
-- | -- slotImage(label, image, link) → wikitext thumbnail | ||
------------------------------------------------------------------------ | ------------------------------------------------------------------------ | ||
local function slotImage( label, image, link ) | local function slotImage(label, image, link) | ||
if not label or label == '' then return '' end | if not label or label == '' then return '' end | ||
local file = ( image ~= '' | local file = (image ~= '' and image) or ('Grid_' .. label .. '.png') | ||
local | local tgt = (link ~= '' and link ) or label | ||
return string.format( | return string.format( | ||
'[[File:%s|32px|class=pixelated|link=%s|alt=%s]]', | '[[File:%s|32px|class=pixelated|link=%s|alt=%s]]', | ||
file, | file, tgt, label | ||
) | ) | ||
end | end | ||
------------------------------------------------------------------------ | ------------------------------------------------------------------------ | ||
-- | -- buildFrame(args, idx) → html for one output variant | ||
------------------------------------------------------------------------ | ------------------------------------------------------------------------ | ||
local function buildFrame( args, idx ) | local function buildFrame(args, idx) | ||
local inL | local inL = args.input or args[1] or '' | ||
local inI = args['input-image'] or '' | |||
local inLn = args['input-link'] or '' | |||
local | |||
local | |||
local html = mw.html.create( 'div' ):addClass( 'sc-frame' ) | local outL = args['output' .. idx] or args[idx + 1] or '' | ||
html:wikitext( '[[File:StonecutterGUI.png|180px|link=|alt=]]' ) | local outI = args['output' .. idx .. '-image'] or '' | ||
local outLn= args['output' .. idx .. '-link'] or '' | |||
local html = mw.html.create('div'):addClass('sc-frame') | |||
html:wikitext('[[File:StonecutterGUI.png|180px|link=|alt=]]') | |||
-- input (left) | -- input (left) | ||
html:tag('div'):addClass('sc-slot') | html:tag('div'):addClass('sc-slot') | ||
:css{ left = '11px', top = '50px' } | :css{left = '11px', top = '50px'} | ||
:wikitext( slotImage( inL, inI, inLn ) ) | :wikitext(slotImage(inL, inI, inLn)) | ||
-- preview (top-centre) | -- preview (top-centre) | ||
html:tag('div'):addClass('sc-slot') | html:tag('div'):addClass('sc-slot') | ||
:css{ left = '56.5px', top = '23px' } | :css{left = '56.5px', top = '23px'} | ||
:wikitext( slotImage( outL, outI, outLn ) ) | :wikitext(slotImage(outL, outI, outLn)) | ||
-- output (right) | -- output (right) | ||
html:tag('div'):addClass('sc-slot') | html:tag('div'):addClass('sc-slot') | ||
:css{ left = '127px', top = '50px' } | :css{left = '127px', top = '50px'} | ||
:wikitext( slotImage( outL, outI, outLn ) ) | :wikitext(slotImage(outL, outI, outLn)) | ||
return tostring( html ) | return tostring(html) | ||
end | end | ||
| Line 67: | Line 55: | ||
-- main entry | -- main entry | ||
------------------------------------------------------------------------ | ------------------------------------------------------------------------ | ||
function p.carousel( frame ) | function p.carousel(frame) | ||
local args = getArgs( frame, { removeBlanks = false } ) | local args = getArgs(frame, {removeBlanks = false}) | ||
-- count | -- count non-blank outputs | ||
local count = 0 | local count = 0 | ||
while true do | while true do | ||
local raw = args[ 'output' .. ( count + 1 ) ] or args[ count + 2 ] | local raw = args['output' .. (count + 1)] or args[count + 2] | ||
if not raw or trim( tostring( raw ) ) == '' then break end | if not raw or trim(tostring(raw)) == '' then break end | ||
count = count + 1 | count = count + 1 | ||
end | end | ||
| Line 81: | Line 69: | ||
end | end | ||
-- | -- outer wrapper | ||
local outer = mw.html.create('div') | |||
:addClass('stonecutting-carousel') | |||
local outer = mw.html.create( 'div' ) | :css{width = '180px', height = '131px', position = 'relative'} | ||
:addClass( 'stonecutting-carousel' ) | |||
:css{ width = '180px', height = '131px', position = 'relative' } | |||
for i = 1, count do | for i = 1, count do | ||
outer:wikitext( buildFrame( args, i ) ) | outer:wikitext(buildFrame(args, i)) | ||
end | end | ||
-- | -- static stylesheet (positioning etc.) | ||
outer:wikitext(frame:extensionTag( | |||
'templatestyles', '', { src = ' | 'templatestyles', '', {src = 'Stonecutting/styles.css'} | ||
) | )) | ||
------------------------------------------------------------------ | ------------------------------------------------------------------ | ||
-- dynamic stylesheet | -- dynamic stylesheet: duration & delays | ||
------------------------------------------------------------------ | ------------------------------------------------------------------ | ||
local dur = count * 4 | local dur = count * 4 -- seconds; 4 s per recipe | ||
local pct = 100 / count | local pct = 100 / count -- slice size | ||
local css = {} | |||
-- global rule | |||
css[#css+1] = string.format( | |||
'.stonecutting-carousel .sc-frame{animation:sc-cycle %ds steps(1) infinite;}', | |||
dur | |||
) | ) | ||
-- per-frame delays | |||
for i = 1, count do | for i = 1, count do | ||
css[#css+1] = string.format( | |||
'.stonecutting-carousel .sc-frame:nth-child(%d){animation-delay:%ds;}', | |||
i, (i-1)*4 | |||
) | ) | ||
end | end | ||
-- keyframes | |||
css[#css+1] = string.format( | |||
'@keyframes sc-cycle{0%%{opacity:1;} %.2f%%{opacity:1;} %.2f%%{opacity:0;} 100%%{opacity:0;}}', | |||
pct, pct + 0.01 | |||
) | ) | ||
outer:wikitext(frame:extensionTag( | |||
'templatestyles', | 'templatestyles', | ||
table.concat( | table.concat(css), | ||
{ lang = 'css' } | {lang = 'css'} | ||
) | )) | ||
return tostring( outer ) | return tostring(outer) | ||
end | end | ||
return p | return p | ||
Revision as of 22:04, 13 June 2025
Documentation for this module may be created at Module:Stonecutting/doc
------------------------------------------------------------
-- Stone-cutter recipe carousel
------------------------------------------------------------
local p = {}
local getArgs = require('Module:Arguments').getArgs
local trim = mw.text.trim
------------------------------------------------------------------------
-- slotImage(label, image, link) → wikitext thumbnail
------------------------------------------------------------------------
local function slotImage(label, image, link)
if not label or label == '' then return '' end
local file = (image ~= '' and image) or ('Grid_' .. label .. '.png')
local tgt = (link ~= '' and link ) or label
return string.format(
'[[File:%s|32px|class=pixelated|link=%s|alt=%s]]',
file, tgt, label
)
end
------------------------------------------------------------------------
-- buildFrame(args, idx) → html for one output variant
------------------------------------------------------------------------
local function buildFrame(args, idx)
local inL = args.input or args[1] or ''
local inI = args['input-image'] or ''
local inLn = args['input-link'] or ''
local outL = args['output' .. idx] or args[idx + 1] or ''
local outI = args['output' .. idx .. '-image'] or ''
local outLn= args['output' .. idx .. '-link'] or ''
local html = mw.html.create('div'):addClass('sc-frame')
html:wikitext('[[File:StonecutterGUI.png|180px|link=|alt=]]')
-- input (left)
html:tag('div'):addClass('sc-slot')
:css{left = '11px', top = '50px'}
:wikitext(slotImage(inL, inI, inLn))
-- preview (top-centre)
html:tag('div'):addClass('sc-slot')
:css{left = '56.5px', top = '23px'}
:wikitext(slotImage(outL, outI, outLn))
-- output (right)
html:tag('div'):addClass('sc-slot')
:css{left = '127px', top = '50px'}
:wikitext(slotImage(outL, outI, outLn))
return tostring(html)
end
------------------------------------------------------------------------
-- main entry
------------------------------------------------------------------------
function p.carousel(frame)
local args = getArgs(frame, {removeBlanks = false})
-- count non-blank outputs
local count = 0
while true do
local raw = args['output' .. (count + 1)] or args[count + 2]
if not raw or trim(tostring(raw)) == '' then break end
count = count + 1
end
if count == 0 then
return '<span style="color:red">Stonecutting: no outputs supplied</span>'
end
-- outer wrapper
local outer = mw.html.create('div')
:addClass('stonecutting-carousel')
:css{width = '180px', height = '131px', position = 'relative'}
for i = 1, count do
outer:wikitext(buildFrame(args, i))
end
-- static stylesheet (positioning etc.)
outer:wikitext(frame:extensionTag(
'templatestyles', '', {src = 'Stonecutting/styles.css'}
))
------------------------------------------------------------------
-- dynamic stylesheet: duration & delays
------------------------------------------------------------------
local dur = count * 4 -- seconds; 4 s per recipe
local pct = 100 / count -- slice size
local css = {}
-- global rule
css[#css+1] = string.format(
'.stonecutting-carousel .sc-frame{animation:sc-cycle %ds steps(1) infinite;}',
dur
)
-- per-frame delays
for i = 1, count do
css[#css+1] = string.format(
'.stonecutting-carousel .sc-frame:nth-child(%d){animation-delay:%ds;}',
i, (i-1)*4
)
end
-- keyframes
css[#css+1] = string.format(
'@keyframes sc-cycle{0%%{opacity:1;} %.2f%%{opacity:1;} %.2f%%{opacity:0;} 100%%{opacity:0;}}',
pct, pct + 0.01
)
outer:wikitext(frame:extensionTag(
'templatestyles',
table.concat(css),
{lang = 'css'}
))
return tostring(outer)
end
return p