local p = {}
local variants = {hk = 1, jp = 2, us = 3}
local tileData = {
-- Uni- Western name Japanese name
-- Name in MPSZ code for tooltip iff useful Reserved Standard, JP, US images
_1m = {'1m', '🀇', '1 crak', '1 man', nil, 'MJw1'},
_2m = {'2m', '🀈', '2 craks', '2 man', nil, 'MJw2'},
_3m = {'3m', '🀉', '3 craks', '3 man', nil, 'MJw3'},
_4m = {'4m', '🀊', '4 craks', '4 man', nil, 'MJw4'},
_5m = {'5m', '🀋', '5 craks', '5 man', nil, 'MJw5'},
_6m = {'6m', '🀌', '6 craks', '6 man', nil, 'MJw6'},
_7m = {'7m', '🀍', '7 craks', '7 man', nil, 'MJw7'},
_8m = {'8m', '🀎', '8 craks', '8 man', nil, 'MJw8'},
_9m = {'9m', '🀏', '9 craks', '9 man', nil, 'MJw9'},
_1p = {'1p', '🀙', '1 dot', '1 pin', nil, 'MJt1', 'MJt1bv1', 'MJt1b'},
_2p = {'2p', '🀚', '2 dots', '2 pin', nil, 'MJt2', 'MJt2b'},
_3p = {'3p', '🀛', '3 dots', '3 pin', nil, 'MJt3', 'MJt3b'},
_4p = {'4p', '🀜', '4 dots', '4 pin', nil, 'MJt4', 'MJt4b'},
_5p = {'5p', '🀝', '5 dots', '5 pin', nil, 'MJt5', 'MJt5b'},
_6p = {'6p', '🀞', '6 dots', '6 pin', nil, 'MJt6', 'MJt6b'},
_7p = {'7p', '🀟', '7 dots', '7 pin', nil, 'MJt7', 'MJt7b'},
_8p = {'8p', '🀠', '8 dots', '8 pin', nil, 'MJt8'},
_9p = {'9p', '🀡', '9 dots', '9 pin', nil, 'MJt9', 'MJt9b'},
_1s = {'1s', '🀐', '1 bam', '1 sō', nil, 'MJs1', 'MJs1b', 'MJs1b8'},
_2s = {'2s', '🀑', '2 bams', '2 sō', nil, 'MJs2', nil, 'MJs2b'},
_3s = {'3s', '🀒', '3 bams', '3 sō', nil, 'MJs3', nil, 'MJs3b'},
_4s = {'4s', '🀓', '4 bams', '4 sō', nil, 'MJs4', nil, 'MJs4b'},
_5s = {'5s', '🀔', '5 bams', '5 sō', nil, 'MJs5', nil, 'MJs5b'},
_6s = {'6s', '🀕', '6 bams', '6 sō', nil, 'MJs6', nil, 'MJs6b'},
_7s = {'7s', '🀖', '7 bams', '7 sō', nil, 'MJs7b', 'MJs7'},
_8s = {'8s', '🀗', '8 bams', '8 sō', nil, 'MJs8', nil, 'MJs8b'},
_9s = {'9s', '🀘', '9 bams', '9 sō', nil, 'MJs9', nil, 'MJs9b'},
_1z = {'1z', '🀀', 'east', nil, nil, 'MJf1'},
_2z = {'2z', '🀁', 'south', nil, nil, 'MJf2'},
_3z = {'3z', '🀂', 'west', nil, nil, 'MJf3'},
_4z = {'4z', '🀃', 'north', nil, nil, 'MJf4'},
_5z = {'5z', '🀆', 'white', nil, nil, 'MJd3', 'MJd3e', 'MJd3b'},
_6z = {'6z', '🀅', 'green', nil, nil, 'MJd2', 'MJd2v1', 'MJd2v3'},
_7z = {'7z', '🀄︎', 'red', nil, nil, 'MJd1', nil, 'MJd1v2'},
_1q = {'1q', '🀦', 'spring', nil, nil, 'MJh1'},
_2q = {'2q', '🀧', 'summer', nil, nil, 'MJh2'},
_3q = {'3q', '🀨', 'autumn', nil, nil, 'MJh3'},
_4q = {'4q', '🀩', 'winter', nil, nil, 'MJh4'},
_5q = {'5q', '🀢', 'plum', nil, nil, 'MJh5'},
_6q = {'6q', '🀣', 'orchid', nil, nil, 'MJh6'},
_7q = {'7q', '🀤', 'chrysanthemum', nil, nil, 'MJh7'},
_8q = {'8q', '🀥', 'bamboo', nil, nil, 'MJh8'},
_x = {'X', '🀫', 'tile back', nil, nil, 'MJhide'},
_q = {'?', '🀫', 'unspecified tile',nil, nil, 'MJxx-'}, -- Do not remove hyphen-minus (not a mistake)
-- Used in variants only
_J = {'J', '🀪', 'joker', nil, nil, 'MJj1v1-'}, -- Do not remove hyphen-minus (not a mistake)
_0m = {'0m', '🀋', 'red 5 man', nil, nil, 'MJw5r'},
_0p = {'0p', '🀝', 'red 5 pin', nil, nil, 'MJt5r'},
_0s = {'0s', '🀔', 'red 5 sō', nil, nil, 'MJs5r'}
}
--[[
Images are selected depending on the variant. If none is specified for the
chosen variant, fall back to the standard image.
A suffix, and then filetype, are added to the filename depending on how
specifically the tile needs to be drawn. The files are named systematically.
Players of Japanese mahjong will better understand man/pin/sō than crak/dot/bam.
Using Japanese names of honors would not help most readers.
]]
-- Simple column names for the above table
local MPSZID = 1 -- not used directly right now
local UNICODE = 2
local SCREENREADER_NAME = 3
local SCREENREADER_NAME_JP = 4
local IMAGE = 6
local IMAGE_JP = 7
local IMAGE_US = 8
-- Screen reader descriptions to show only when the arguments call for one, large tile image.
local singleTileAlts = {
MJw1 = 'A mahjong tile with the traditional Chinese characters 一 (blue) over 萬 (red).',
MJw2 = 'A mahjong tile with the traditional Chinese characters 二 (blue) over 萬 (red).',
MJw3 = 'A mahjong tile with the traditional Chinese characters 三 (blue) over 萬 (red).',
MJw4 = 'A mahjong tile with the traditional Chinese characters 四 (blue) over 萬 (red).',
MJw5 = 'A mahjong tile with the traditional Chinese characters 五 (blue) over 萬 (red).',
MJw6 = 'A mahjong tile with the traditional Chinese characters 六 (blue) over 萬 (red).',
MJw7 = 'A mahjong tile with the traditional Chinese characters 七 (blue) over 萬 (red).',
MJw8 = 'A mahjong tile with the traditional Chinese characters 八 (blue) over 萬 (red).',
MJw9 = 'A mahjong tile with the traditional Chinese characters 九 (blue) over 萬 (red).',
MJt1 = 'A mahjong tile with a large circle, filled with smaller concentric circles of different colors and a floral pattern.',
MJt1bv1 = 'A mahjong tile with a large blue circle, filled with smaller concentric circles and red in the center.',
MJt1b = 'A mahjong tile with a large circle, filled with smaller concentric circles of different colors and a floral pattern.',
MJt2 = 'A mahjong tile with a blue circle positioned above a green circle.',
MJt2b = 'A mahjong tile with two blue circles arranged vertically.',
MJt3 = 'A mahjong tile with three circles, in blue, red and green, diagonal from top left to bottom right.',
MJt3b = 'A mahjong tile with three circles, in blue, red and blue, diagonal from top left to bottom right.',
MJt4 = 'A mahjong tile with four circles in alternating blue and green colors.',
MJt4b = 'A mahjong tile with four blue circles.',
MJt5 = 'A mahjong tile with five circles in alternating blue and green colors; the red central circle is surrounded.',
MJt5b = 'A mahjong tile with five circles; the red central circle is surrounded by four blue circles.',
MJt6 = 'A mahjong tile with six circles in two columns of three. They are red, except for the top row, in green.',
MJt6b = 'A mahjong tile with six circles in two columns of three. They are red, except for the top row, in blue.',
MJt7 = 'A mahjong tile with seven circles; a square of four red circles below a diagonal row of three green circles.',
MJt7b = 'A mahjong tile with seven circles; a square of four red circles below a diagonal row of three blue circles.',
MJt8 = 'A mahjong tile with eight blue circles in two columns of four.',
MJt9 = 'A mahjong tile with nine circles in three rows of three. The rows are colored blue, then red, then green.',
MJt9b = 'A mahjong tile with nine circles in three rows of three. The circles are blue, except for the red middle row.',
MJs1 = 'A mahjong tile with an abstract line drawing of a small bird perched on a horizontal branch.',
MJs1b = 'A mahjong tile with a green peacock-like bird. Its blue tail feathers, speckled with red, fill the top half of the tile.',
MJs1b1 = 'A mahjong tile with a blue peacock-like bird. Its green tail feathers, speckled with red, fill the top half of the tile.',
MJs1b8 = 'A mahjong tile with an abstract line drawing of a small red bird perched on a diagonal branch.',
Mjs2 = 'A mahjong tile with two green sticks arranged vertically.',
Mjs2b = 'A mahjong tile with two sticks arranged vertically. A blue stick stands above a green stick.',
Mjs3 = 'A mahjong tile with three vertical green sticks. One is above, while two side-by-side are below.',
Mjs3b = 'A mahjong tile with three vertical sticks. A blue one is above, with two green ones side-by-side below.',
Mjs4 = 'A mahjong tile with four vertical green sticks arranged in two columns of two.',
Mjs4b = 'A mahjong tile with four vertical sticks arranged in two rows of two. The top row is blue and the bottom row is green.',
Mjs5 = 'A mahjong tile with vertical green sticks arranged in two columns of two, flanking a red, fifth stick in the center.',
Mjs5b = 'A mahjong tile with vertical sticks arranged in two rows of two, in alternating blue and green. There is a red, fifth stick in the center.',
Mjs6 = 'A mahjong tile with six vertical green sticks, in two rows of three.',
Mjs6b = 'A mahjong tile with six vertical sticks, in two rows of three. The top row is blue and the bottom row is green.',
Mjs7 = 'A mahjong tile with seven vertical sticks. A red stick stands above three columns of two green sticks each.',
Mjs7b = 'A mahjong tile with seven vertical sticks. A red stick stands above three columns of two sticks each. These columns are green, blue, and green.',
Mjs8 = 'A mahjong tile with eight green sticks. Four are arranged in a diamond shape around the center, and four more stand vertically, two on each side.',
Mjs8b = 'A mahjong tile with eight sticks. Four are arranged in a diamond shape around the center, and four more stand vertically, two on each side. The four in the top half of the tile are blue and the other four are green.',
Mjs9 = 'A mahjong tile with nine sticks arranged in three columns of three. The sticks are green, except for the red ones in the middle column.',
Mjs9b = 'A mahjong tile with nine sticks arranged in three columns of three. The columns are colored green, red and blue.',
Mjf1 = 'A mahjong tile with the blue traditional Chinese character 東.',
Mjf2 = 'A mahjong tile with the blue traditional Chinese character 南.',
Mjf3 = 'A mahjong tile with the blue traditional Chinese character 西.',
Mjf4 = 'A mahjong tile with the blue traditional Chinese character 北.',
Mjd1 = 'A mahjong tile with the red traditional Chinese character 中.',
Mjd1v2 = 'A mahjong tile with a red dragon.',
Mjd2 = 'A mahjong tile with the green traditional Chinese character 發.',
Mjd2v1 = 'A mahjong tile with the green traditional Chinese character 發. The 殳 element is replaced by 矢.',
Mjd2v3 = 'A mahjong tile with a green dragon.',
Mjd3 = 'A mahjong tile with a blue frame.',
Mjd3b = 'A mahjong tile with a blue frame.',
Mjd3e = 'A blank mahjong tile.',
Mjh1 = 'A mahjong tile, labelled 1 春, with three tulips and a butterfly.',
Mjh2 = 'A mahjong tile, labelled 2 夏, with a lotus and three small lilypads.',
Mjh3 = 'A mahjong tile, labelled 3 秋, with three partially peeled fruits. A central, prominent fruit appears to be an orange.',
Mjh4 = 'A mahjong tile, labelled 4 冬, with three daffodils.',
Mjh5 = 'A mahjong tile, labelled 梅 1, with a large plum blossom.',
Mjh6 = 'A mahjong tile, labelled 蘭 2, with a large orchid bulb.',
Mjh7 = 'A mahjong tile, labelled 菊 3, with a large chrysanthemum flower.',
Mjh8 = 'A mahjong tile, labelled 竹 4, with a closeup of a standing bamboo shoot. Leafy branches protrude from the shoot.',
MJw5r = 'A mahjong tile with the traditional Chinese characters 五 over 萬 (both red).',
MJt5r = 'A mahjong tile with five red circles. One central circle is surrounded by the other four.',
MJs5r = 'A mahjong tile with vertical red sticks arranged in two columns of two, flanking a fifth stick in the center.',
MJj1v1 = 'A mahjong tile with a green line drawing of a fish-like creature inside a blue circle, under a red "JOKER" label.',
MJxx = 'A mahjong tile overlaid with a question mark.',
MJhide = 'The reverse side of a mahjong tile.'
}
p.main = function(frame)
local pargs = frame:getParent().args
-- If {{{1}}} is a variant (hk, us, jp) take note of that and use {{{2}}} for the tiles.
-- Otherwise, {{{1}}} is the tiles and just go with basic mahjong.
local variant = pargs[1] or ''
local mpsz = pargs[2] or ''
if #mpsz == 0 then
if #variant == 0 then
-- Long ago, {{mahjong}} used to be a navbox, so let's not show an error if
-- it's called with no arguments (it'd be in a lot of old page revisions).
return ''
end
if not variants[variant] then
mpsz = variant
variant = 'hk' -- Default to "basic" Hong Kong style.
else
-- There are no tiles at all...
return ''
end
end
local root = mw.html.create(pargs['big'] and 'div' or 'span')
:addClass('nowrap')
:css('font-size', '0')
-- Treat dash separators as their own "groups" for our loop
mpsz = mpsz:gsub('-+',' - ')
-- Are we drawing just one big tile?
local bigDemo = false
if pargs['big'] and (mpsz == 'X' or mpsz == '?' or tileData['_' .. mpsz]) then
bigDemo = true
else
-- Get ready to be a container for overlaid images.
if pargs['big'] then
root:css('vertical-align','bottom')
else
root:css('padding-right', '4px')
:css('position','relative')
:css('top','-6px')
:css('margin-bottom','-10px')
:css('display','inline-block')
end
root:attr('role','text')
end
local a = ''
for i in mpsz:gmatch('[^ ]+') do
local suit = i:sub(-1)
if suit == '-' then
-- This is a spacer
root:tag('span')
:css('display','inline-block')
:css('width',pargs['big'] and '12px' or '6px')
:wikitext(' ')
end
if ('mpszX?qJ@'):find(suit) then -- It's a valid character to end a group on, isn't it?
if suit == 'X' or suit == '?' or suit == 'J' then
-- assert that mpsz only contains X/?/J
end
for tile in i:gmatch('[0123456789X%?J][\'"]?@?') do
local filename = ''
local alt = ''
local modifier = tile:sub(-1)
local ctrwidth = pargs['big'] and '36px' or '16px'
local width = pargs['big'] and '45px' or '20px'
local gray = false
if modifier == '@' then
gray = true
tile = tile:sub(1,-2)
modifier = tile:sub(-1)
end
-- Why is it that whenever there's some ugly looking code, it's always you three?
if tile:sub(1,1) == 'X' then
tile = '_x'
elseif tile:sub(1,1) == '?' then
tile = '_q'
elseif tile:sub(1,1) == 'J' then
tile = '_J'
else
tile = '_' .. tile:sub(1,1) .. suit
end
filename = tileData[tile][IMAGE]
alt = tileData[tile][UNICODE] -- Select as the unicode tile, in case this is inline.
if variant == 'us' then
filename = tileData[tile][IMAGE_US] or filename
end
if tile ~= '_x' and tile ~= '_q' and tile ~= '_J' then
if variant == 'jp' then
-- Since it's Japanese mahjong, we have to account for the complicated rules.
filename = tileData[tile][IMAGE_JP] or filename -- Use JP image, if it's different
if (modifier == "'") then
-- This tile needs to be tilted sideways, so prepare accordingly
width = pargs['big'] and '54px' or '24px'
ctrwidth = pargs['big'] and '45px' or '20px'
filename = filename .. '-x'
elseif modifier == '"' then
-- This tile is going to be a stack of two, sideways tiles.
width = pargs['big'] and '54px' or '24px'
ctrwidth = pargs['big'] and '45px' or '20px'
filename = filename .. (tile:sub(2,2) == '0' and '-=' or '=')
alt = alt .. alt -- There's two now
else
filename = filename .. '-' -- Not sideways.
end
-- Sorry, one hopefully temporary bandaid.
-- JP peacock feathers should probably be green, but the rotations don't have that.
if filename == 'MJs1b-' then filename = 'MJs1b1-' end
else
filename = filename .. '-' -- Not Japanese, not sideways.
end
end
if bigDemo then
-- This is a big tile, and it's just one.
ctrwidth = '' -- Do not try to accommodate a second tile
alt = singleTileAlts[filename:gsub('%-','')] or alt -- Use very descriptive alt text
end
-- Add the tile to the page
local tileSpan = root:tag('span')
:css('display', 'inline-block')
:css('filter', gray and 'brightness(80%)' or 'brightness(100%)') -- Gotta have both
:wikitext(table.concat({
'[[File:', filename, '.svg|', width,
bigDemo and '' or '|link=', -- Suppress link for groups of tiles or small tiles
'|alt=', alt,
'|class=notpageimage]]'
}))
if #ctrwidth then
tileSpan:css('width', ctrwidth)
end
if variant == 'jp' and pargs['big'] and modifier == "'" then
-- Improve the appearance of Japanese calls
tileSpan:css('height', '36px')
:css('padding-top', '10px')
:css('vertical-align', 'top')
end
end
else
-- This group doesn't have a valid suit! Complain about it.
end
end
if pargs['big'] then
return tostring(root)
else
-- For inline tiles, add word joiners so that they stick to parentheses
return '⁠' .. tostring(root) .. '⁠'
end
end
return p