This is a private module sandbox of Dine2016, for his own experimentation. Items in this module may be added and removed at Dine2016's discretion; do not rely on this module's stability.
local export = {}
local m_utilities = require("Module:utilities")
local m_ja = require("Module:ja")
local title = mw.title.getCurrentTitle()
local PAGENAME = title.text
local NAMESPACE = title.nsText
local lang = require("Module:languages").getByCode("ja")
-- TODO: centralize internal tables here
local kanji_pattern = "㐀-䶵一-鿌\239\164\128-\239\171\153𠀀-"
local kanji_grade_links = {
"]",
"]",
"]",
"]",
"]",
"]",
"]", -- 7
"]", -- 8
"]" -- 9
}
local function link(text)
if text == title then
return '<span lang="ja" class="Jpan" style="font-weight: bold;">' .. text .. '</span>'
else
return '<span lang="ja" class="Jpan">' .. ']' .. '</span>'
end
end
-- export this?
local function shin_to_kyu(shin)
local ambiguous_char = '' -- TODO: check if there is more
if mw.ustring.find(shin, ambiguous_char) then return nil end
local s_to_k = {
= "亞", = "惡", = "壓", = "圍", = "醫", = "爲",
= "壹", = "逸", = "隱", = "榮", = "營", = "衞",
= "驛", = "謁", = "圓", = "鹽", = "緣", = "艷",
= "應", = "歐", = "毆", = "櫻", = "奧", = "橫",
= "溫", = "穩", = "假", = "價", = "禍", = "畫",
= "會", = "悔", = "海", = "繪", = "壞", = "懷",
= "慨", = "槪", = "擴", = "殼", = "覺", = "學",
= "嶽", = "樂", = "喝", = "渴", = "褐", = "罐",
= "卷", = "陷", = "勸", = "寬", = "漢", = "關",
= "歡", = "觀", = "氣", = "祈", = "卽", = "歸",
= "器", = "僞", = "戲", = "犧", = "舊", = "據",
= "擧", = "虛", = "峽", = "挾", = "狹", = "鄕",
= "響", = "曉", = "勤", = "謹", = "區", = "驅",
= "勳", = "薰", = "徑", = "莖", = "惠", = "揭",
= "溪", = "經", = "螢", = "輕", = "繼", = "鷄",
= "藝", = "擊", = "缺", = "硏", = "縣", = "儉",
= "劍", = "險", = "圈", = "檢", = "獻", = "權",
= "顯", = "驗", = "嚴", = "廣", = "效", = "恆",
= "黃", = "鑛", = "號", = "國", = "黑", = "穀",
= "碎", = "濟", = "齋", = "劑", = "殺", = "雜",
= "參", = "棧", = "蠶", = "慘", = "贊", = "殘",
= "絲", = "祉", = "視", = "齒", = "兒", = "辭",
= "濕", = "實", = "寫", = "社", = "者", = "煮",
= "釋", = "壽", = "收", = "臭", = "從", = "澁",
= "獸", = "縱", = "祝", = "肅", = "處", = "暑",
= "署", = "緖", = "諸", = "敍", = "將", = "祥",
= "稱", = "涉", = "燒", = "證", = "獎", = "條",
= "狀", = "乘", = "淨", = "剩", = "疊", = "繩",
= "壤", = "孃", = "讓", = "釀", = "觸", = "囑",
= "神", = "眞", = "寢", = "愼", = "盡", = "圖",
= "粹", = "醉", = "穗", = "隨", = "髓", = "樞",
= "數", = "瀨", = "聲", = "齊", = "靜", = "竊",
= "攝", = "節", = "專", = "淺", = "戰", = "踐",
= "錢", = "潛", = "纖", = "禪", = "祖", = "雙",
= "壯", = "爭", = "莊", = "搜", = "插", = "巢",
= "曾", = "瘦", = "裝", = "僧", = "層", = "總",
= "騷", = "增", = "憎", = "藏", = "贈", = "臟",
= "卽", = "屬", = "續", = "墮", = "對", = "體",
= "帶", = "滯", = "臺", = "瀧", = "擇", = "澤",
= "擔", = "單", = "膽", = "嘆", = "團", = "斷",
= "彈", = "遲", = "癡", = "蟲", = "晝", = "鑄",
= "著", = "廳", = "徵", = "聽", = "懲", = "敕",
= "鎭", = "塚", = "遞", = "鐵", = "點", = "轉",
= "傳", = "都", = "燈", = "當", = "黨", = "盜",
= "稻", = "鬭", = "德", = "獨", = "讀", = "突",
= "屆", = "難", = "貳", = "惱", = "腦", = "霸",
= "拜", = "廢", = "賣", = "梅", = "麥", = "發",
= "髮", = "拔", = "繁", = "晚", = "蠻", = "卑",
= "祕", = "碑", = "濱", = "賓", = "頻", = "敏",
= "甁", = "侮", = "福", = "拂", = "佛", = "倂",
= "竝", = "塀", = "餠", = "邊", = "變", = "勉",
= "步", = "寶", = "豐", = "襃", = "墨", = "飜",
= "每", = "萬", = "滿", = "免", = "麵", = "彌",
= "默", = "譯", = "藥", = "與", = "豫", = "餘",
= "譽", = "搖", = "樣", = "謠", = "來", = "賴",
= "亂", = "覽", = "欄", = "龍", = "隆", = "虜",
= "兩", = "獵", = "綠", = "淚", = "壘", = "類",
= "禮", = "勵", = "戾", = "靈", = "齡", = "曆",
= "歷", = "戀", = "練", = "鍊", = "爐", = "勞",
= "郞", = "朗", = "廊", = "樓", = "錄", = "灣",
-- TODO: add Z-variants like 青/靑, 説/說
}
return mw.ustring.gsub(shin, '.', s_to_k)
end
local function genspec(args)
--[=[
kanji_length -- the number of kanji in the term
kanji -- e.g. { '追払', '追拂' }
kanji_types -- e.g. { 'shin', 'kyu' } (or 位: { 'shinkyu' }, 儘/侭: { 'kyu', 'extshin' })
kanji_spellings -- e.g. { '追い払う', '追い拂う' }
yomi -- a list of { original reading, actual reading, okurigana } of the kanji spans, e.g. { { 'お', 'お', 'い' }, { 'はら', 'はら', 'う' } }.
yomi_types -- a list of reading types, each formatted like { 'on', span=1 }, { 'jukujikun', span=2 }. The sum of the spans should equal kanji_length.
altforms -- e.g. { { '追いはらう', type='' }, { '追払う', '追拂う', type='irregular okurigana' }, { '追ひ払ふ', '追ひ拂ふ', type='historical kana' } }
]=]
local kanji_types = {}
local kanji_spellings = {}
local shin = args.s; if shin == '-' then shin = nil end
local kyu = args.k; if kyu == '-' then kyu = nil end
local extshin = args.es; if extshin == '-' then extshin = nil end
if kyu and not shin and not extshin then shin = PAGENAME end
if extshin and not shin and not kyu then kyu = PAGENAME end
if shin and kyu and not extshin then
kanji_types = { 'shin', 'kyu' }
kanji_spellings = { shin, kyu }
elseif kyu and extshin and not shin then
kanji_types = { 'kyu', 'extshin' }
kanji_spellings = { kyu, extshin }
elseif not kyu and not extshin then
if not shin then shin = PAGENAME end
kanji_types = { 'shin', 'kyu' }
kanji_spellings = { shin, shin_to_kyu(shin) or error('automatic jitai conversion of ' .. shin .. ' failed, please supply the kyujitai manually') }
else
error('combination of kanji types not yet supported') -- shin + kyu + extshin can be supported if needed
end
if #kanji_spellings == 2 and kanji_spellings == kanji_spellings then
kanji_types = { 'shinkyu' }
kanji_spellings = { kanji_spellings }
end
local kanji = {}
for _, i in ipairs(kanji_spellings) do
local kj = mw.ustring.gsub(i, '()々', '%1%1')
kj = mw.ustring.gsub(kj, '', '')
table.insert(kanji, kj)
end
local kanji_length = mw.ustring.len(kanji)
if kanji_length == 0 then error('there is no kanji in the term ' .. kanji) end
local yomi = {}
for i = 1, args.maxindex do
local ym = args or ''
if not mw.ustring.find(ym, '%.') then ym = ym .. '.' end
if not mw.ustring.find(ym, '>') then ym = mw.ustring.gsub(ym, '^(.*)%.(.*)$', '%1>%1.%2') end
local _, _, a, b, c = mw.ustring.find(ym, '^(.*)>(.*)%.(.*)$')
table.insert(yomi, { a, b, c })
end
local yomi_types = {}
local yt = args or ''
local yomi_code = {
o = 'on', on = 'on',
kanon = 'kanon',
goon = 'goon',
toon = 'toon',
kan = 'kanyoon', kanyo = 'kanyoon', kanyoon = 'kanyoon',
k = 'kun', kun = 'kun',
juku = 'jukujikun', jukuji = 'jukujikun', jukujikun = 'jukujikun', -- j alone is jūbakoyomi (on+kun) for backward compatibility
irr = 'irregular', irreg = 'irregular', irregular = 'irregular',
p = 'phonetic', phonetic = 'phonetic',
nanori = 'nanori',
= '', none = '',
}
if yt == 'j' then yt = 'on,kun' elseif yt == 'y' then yt='kun,on' end
if not mw.ustring.find(yt, ',') and not yomi_code*$', '%1')] then
yt = mw.ustring.gsub(mw.ustring.gsub(yt, '(*)', '%1,'), ',$', '') -- 'j2kk' to 'j2,k,k'
end
yt = mw.text.split(yt, ',')
for _, i in ipairs(yt) do
local _, _, a, b = mw.ustring.find(i, '^(*)(*)$')
a = yomi_code or error('cannot recognize yomi type "' .. args .. '"')
b = tonumber(b) or 1
table.insert(yomi_types, { a, span=b })
end
-- allow using a single yomi type for the whole kanji
-- Case 1: {{ja-kanjitab|かん|れん|yomi=kan|s=関連}} -> kanon, kanon
-- Case 2: {{ja-kanjitab|やまと|yomi=j|s=大和}} -> jukujikun2
if #yomi_types == 1 and yomi_types.span == 1 and kanji_length > 1 then
local yomi_jukujikun_type = { = true, = true, = true }
if yomi_jukujikun_type] then -- Case 2
yomi_types.span = kanji_length
else -- Case 1
local a = yomi_types
local b = yomi_types.span
for i = 2, kanji_length do table.insert(yomi_types, { a, span=b }) end
end
end
-- check the sum of the spans
local span_sum = 0
for _, i in ipairs(yomi_types) do span_sum = span_sum + i.span end
if span_sum ~= kanji_length then error('the |yomi= parameter does not match the number of kanji: ' .. span_sum .. ' vs ' .. kanji_length) end
local altforms = {}
local af = args.alt or ''
af = mw.text.split(af, ',')
for _, i in ipairs(af) do
if i ~= '' then
if not mw.ustring.find(i, '-') then i = i .. '-' end
local _, _, a, b = mw.ustring.find(i, '^(.*)%-(.*)$')
local alt_code = {
= 'irregular okurigana',
= 'historical kana',
= 'variant kana',
= 'obsolete kana', -- e.g. 用ひる
}
if alt_code then b = alt_code end
-- syntax borrowed from {{zh-l}}: *字体 supresses automatic conversion, and 字体/字體 provides manual conversions
if mw.ustring.find(a, '%*') then
table.insert(altforms, { mw.ustring.gsub(a, '%*', ''), type=b })
elseif mw.ustring.find(a, '/') then
a = mw.text.split(a, '/')
a = b
table.insert(altforms, a)
else
local shin = a
local kyu = shin_to_kyu(shin) or shin
if shin == kyu then
table.insert(altforms, { shin, type=b })
else
table.insert(altforms, { shin, kyu, type=b })
end
end
end
end
return { kanji_length = kanji_length, kanji = kanji, kanji_types = kanji_types, kanji_spellings = kanji_spellings, yomi = yomi, yomi_types = yomi_types, altforms = altforms }
end
local function gentable(spec, collapsed)
local table_code = '{| align=right style="clear: right;margin: 1em;border-collapse: collapse;text-align: center"\n!\n'
-- generate the yomi tabs
for i, j in ipairs(spec.yomi_types) do
local yomi = spec.yomi or { '', '', '' }
local yomi_text = (yomi == yomi) and (yomi .. '`') or (yomi .. '` > ' .. yomi .. '`')
yomi_text = mw.ustring.gsub(yomi_text, '`', (yomi == '') and '' or ('(' .. yomi .. ')'))
local yomi_type = j
local yomi_link = {
on = "]",
kanon = "]",
goon = "]",
kanyoon = "]",
toon = "]",
kun = "]",
jukujikun = "]",
irregular = "irregular",
phonetic = "phonetic",
nanori = "]",
= "",
}
local span = j.span
table_code = table_code .. '! style="padding: 0.5em;border: 1px solid #aaa;background:#F5F5DC;font-weight: normal;font-size: 85%;" colspan=' .. span .. '|<span class="Jpan" lang="ja">' .. yomi_text .. '</span><br>' .. yomi_link .. '\n'
end
-- generate the main jitai lines
for i = 1, #spec.kanji_types do
table_code = table_code .. '|- style="line-height:1.3"\n'
local jitai_link = {
shin = ']',
kyu = ']',
shinkyu = '] and ]',
extshin = '] (])',
}
local kanji_type = spec.kanji_types
-- cell showing the jitai type and the spelling
table_code = table_code .. '! style="padding: 0.5em;border: 1px solid #aaa;background: #E0FFFF;font-weight: normal;font-size: smaller;" |' .. jitai_link
local kanji_spelling = spec.kanji_spellings
if mw.ustring.len(kanji_spelling) > 6 then
table_code = table_code .. ' <span style="font-size:100%">(' .. link(kanji_spelling) .. ')</span>'
elseif mw.ustring.len(kanji_spelling) > 1 then
table_code = table_code .. ' <span style="font-size:140%">(' .. link(kanji_spelling) .. ')</span>'
end
table_code = table_code .. '\n'
-- cells showing the kanji
local kanji_string = spec.kanji
for j = 1, mw.ustring.len(kanji_string) do
local kanji = mw.ustring.sub(kanji_string, j, j)
table_code = table_code .. '| style="padding: 0.5em; background-color:white;border-right: 1px solid #aaa;border-bottom: 1px solid #aaa;" | <span style="font-size:x-large">' .. link(kanji) .. '</span>'
local kanji_grade = m_ja.kanji_grade(kanji)
table_code = table_code .. '<br><small>' .. kanji_grade_links .. '</small>'
table_code = table_code .. '\n'
end
end
-- alt forms cell
if #spec.altforms > 0 then
table_code = table_code .. '|-\n| style="background-color:white;border: 1px solid #aaa; font-size:90%;" colspan=' .. spec.kanji_length + 1 .. '|\n<b>Variant forms</b><br>'
local alt1 = {}
for _, altform in ipairs(spec.altforms) do
local alt2 = {}
for _, i in ipairs(altform) do table.insert(alt2, link(i)) end
alt2 = table.concat(alt2, '/')
if altform and altform ~= '' then
alt2 = alt2 .. ' <span style="font-size:70%"><i>' .. altform .. '</i></span>'
end
table.insert(alt1, alt2)
end
table_code = table_code .. table.concat(alt1, '<br>') .. '\n'
end
table_code = table_code .. '|}\n'
return table_code
end
function export.show(frame)
local params = {
= { list = true, allow_holes = true, allow_empty = true },
= {},
= {},
= {},
= {},
= {},
= {},
= {},
}
local args, unrecognized_args = require("Module:parameters").process(frame:getParent().args, params, true)
for key, value in pairs(unrecognized_args) do
local additional
if mw.ustring.sub(key, 1, 1) == "y" then
additional = " Perhaps you meant “yomi”?"
end
error("“" .. key .. "” is not a recognized parameter." .. (additional or ""))
end
if args.pagename then
if NAMESPACE == "" then error("The pagename parameter should not be used in entries, as it is only for testing.") end
PAGENAME = args.pagename
end
return gentable(genspec(args))
end
function export:test()
--[[
mw.logObject(genspec({
= { 'き', 'つ>づ.く', maxindex = 2 },
s = '気付く',
yomi = 'ok',
alt = '気づく,気ずく-ik',
}))
mw.logObject(genspec({
= { 'とう', 'きょう', 'けしき', maxindex = 3 },
s = '東京景色',
yomi = 'kan,go,j2',
}))
mw.logObject(genspec({
= { 'まま', maxindex = 1 },
k = '儘',
es = '侭',
yomi = 'k',
}))
mw.logObject(genspec({
= { maxindex = 0 },
s = 'かんじなし',
}))
mw.logObject(genspec({
= { 'やまと', maxindex = 1 },
s = '大和',
yomi = 'j',
}))
]]--
mw.log(gentable(genspec({
= { 'こく', 'さい', 'おん', 'せい', 'き', 'ごう', maxindex = 6 },
s = '国際音声記号',
yomi = 'o',
})))
end
return export