local cfg = mw.loadData('Module:Quran/Configuration')
local gdata = mw.loadData('Module:Quran/data general')
local quran_data
local quran_norm
local aya_symbol_template = cfg.default.aya_symbol_template
local sour
local quran_shape = cfg.default.shape
local string = mw.ustring
local text = mw.text
local strspace = "[ " .. string.char(160) .. "]"
local lua_data = {Othmani = true, text = true, KFGQPC = true}
local function eastern_numbers(thenumber)
local str_number = tostring(thenumber)
local ret_str = ''
for i=1,#str_number do
ret_str = ret_str .. string.char(0x0660 + tonumber(string.sub(str_number,i,i)))
end
return ret_str
end
local function shape_numbers(thenumber)
local str_number = tostring(thenumber)
local numbers_shape = cfg.presentation.numbers_shape
if numbers_shape == "" then
return str_number
end
local ret_str = ''
local c_n
for i=1,#str_number do
c_n = tonumber(string.sub(str_number,i,i))+1
ret_str = ret_str .. string.sub(numbers_shape, c_n,c_n)
end
return ret_str
end
local gtonumber = tonumber
local function tonumber(str)
if not str then
return nil
end
local thenumber = gtonumber(str) or mw.language.getContentLanguage():parseFormattedNumber(str)
if not thenumber then
return nil
end
return math.floor(thenumber)
end
local function set_quran_shape(in_shape)
if in_shape then
for k, shapelist in pairs(cfg.shape_aliases) do
for _, shapevalue in ipairs(shapelist) do
if in_shape == shapevalue then
quran_shape = k
return
end
end
end
end
end
local function soura_count(soura_num)
return gdata.aya_count[gdata.shape_def[quran_shape] and gdata.shape_def[quran_shape].aya_count or 1][soura_num]
end
local function quran_replaces(intext)
local gsub = mw.ustring.gsub
local char = mw.ustring.char
if quran_shape == "KFGQPC" or quran_shape == "Warsh" then
intext = gsub(intext,'آ', 'آ')
end
if quran_shape == "Warsh" or quran_shape == "Qaloun" or quran_shape == "Douri" or quran_shape == "Sousi" or quran_shape == "Bazzi" or quran_shape == "Qunbul" then
intext = gsub(intext,char(160) .. "َ۟", ' ۟<span style="position: relative;top: -0.25em;left: -0.02em;">َ</span>') --اَ۟لِهَةٗ آية
end
if quran_shape == "Warsh" or quran_shape == "Qaloun" or quran_shape == "Bazzi" or quran_shape == "Qunbul" then
intext = gsub(intext,char(160, 1648), '<span style="position: relative;top: -0.5em;letter-spacing: -0.12em;"> ٰ</span>') -- ءَا۬ ٰمَنتُم
end
if quran_shape == "Warsh" or quran_shape == "Qaloun" then
intext = gsub(intext, "ۓ", 'ۓ')
intext = gsub(intext, "ا۬" .. char(65279, 1614), 'ا۬<span style="position: relative;top: -0.8em;left: -0.05em;">َ</span>') --فتحة فوق سكون
intext = gsub(intext, "ا۪" .. char(847, 1616), 'ا۪͏<span style="position: relative;top: 0.05em;">ِ</span>') --فتحة فوق سكون
end
if quran_shape == "Warsh" then
--
-- intext = gsub(intext, char(65279, 1619), '<span style="position: relative;top: -0.72em;left: 0.3em;">ٓ</span>') --المدة بعد لام ألف
intext = gsub(intext, "و۬" .. char(65279, 1614), 'و۬<span style="position: relative;top: -0.5em;left: 0.075em;">َ</span>')
intext = gsub(intext, "ي۬" .. char(65279, 1614), 'ي۬ـ<span style="position: relative;top: -0.07em;left: 0.25em;">َ</span>')
end
if quran_shape == "Douri" or quran_shape == "Sousi" or quran_shape == "Bazzi" or quran_shape == "Qunbul" then
intext = gsub(intext, "ا۪" .. char(847, 1616), 'ا۪͏<span style="position: relative;top: 0.1em;left: -0.05em;">ِ</span>') --فتحة فوق سكون
intext = gsub(intext, "ا۬" .. char(847, 1614), 'ا۬͏<span style="position: relative;top: -0.92em;">َ</span>') --فتحة فوق سكون
end
if quran_shape == "Douri" or quran_shape == "Sousi" then
intext = gsub(intext, char(160, 1648), '<span style="position: relative;left: 0.05em;top: -0.085em;letter-spacing: -0.12em;"> ٰ</span>') -- ءَا۬ ٰمَنتُم
end
return intext
end
local function substitute( msg, args )
return args and mw.message.newRawMessage( msg, args ):plain() or msg;
end
local function error_comment(msg, args )
return substitute( cfg.presentation.error, {mw.getCurrentFrame():getParent():getTitle() , substitute( msg, args )} );
end
local function some_aya(souranum,ayanum,start_word,end_word)
if not start_word and not end_word then
return quran_data[souranum][ayanum],true
end
local fullaya = true
local ayaText = ' ' .. quran_data[souranum][ayanum] .. ' '
local f,l,wb
local fnorm=1
local norm_ayaText
if start_word then
f=string.find(ayaText,' ' .. start_word .. ' ',1,true)
if not f then
if not quran_norm then
quran_norm = mw.loadData('Module:Quran/data norm')
end
norm_ayaText=' ' .. quran_norm[souranum][ayanum] .. ' '
f=string.find(string.gsub(norm_ayaText, string.char(160),' '), ' ' .. start_word .. ' ',1,true)
fnorm=f
if not f then
return error_comment(cfg.msgs.from_word_err)
end
if quran_shape ~= 'text' and string.sub(norm_ayaText,f,f)==string.char(160) then
ff=1
tmp=1
while tmp do
tmp = string.find(string.sub(norm_ayaText,1,f),' ',ff+1,true)
if tmp then
ff=tmp
end
end
f=ff
end
_, wb = string.gsub(string.sub(norm_ayaText,1,f-1),strspace," ")
f=1
for i=1,wb do
f=string.find(ayaText," ",f+1)
end
end
end
f=f or 1
if end_word then
l=string.find(ayaText,' ' .. end_word .. ' ',f,true)
if l then
l=l + end_word:len()
else
if not quran_norm then
quran_norm = mw.loadData('Module:Quran/data norm')
end
norm_ayaText=' ' .. quran_norm[souranum][ayanum] .. ' '
l = string.find(string.gsub(norm_ayaText,string.char(160),' '),' ' .. end_word .. ' ',fnorm,true)
if not l then
return error_comment(cfg.msgs.to_word_err)
end
l=l + string.len(end_word)
_, wb =string.gsub(string.sub(norm_ayaText,1,l-1),strspace," ")
l=1
for i=1,wb do
l=string.find(ayaText, " ",l+1)
end
end
if l<#ayaText then
fullaya=false
end
end
return text.trim(string.sub(ayaText,f,l)),fullaya
end
local function argument_wrapper(arg)
local nilargs = {}
return setmetatable({},
{
__index = function ( tbl, k )
local v = rawget(tbl,k)
if v then
return v
elseif nilargs[k] then
return nil
end
local list = cfg.aliases[k];
for _,arglist in ipairs(arg) do
if type( list ) == 'table' then
for _, alias_key in ipairs( list ) do
if arglist[alias_key] then
v = arglist[alias_key]
break;
end
end
elseif list ~= nil then
v = arglist[list]
end
if v then
break;
end
end
if v == nil then
nilargs[k] = true
elseif string.len(v) == 0 then
nilargs[k] = true
v = nil
else
rawset( tbl, k, v )
end
return v
end,
});
end
local function soura_number( str_soura )
for i=1,114 do
if sour[i].name == str_soura then
return i
end
end
for i=1,114 do
for _, v in ipairs(sour[i].search) do
if v == str_soura then
return i
end
end
end
return nil
end
local function arg2soura_num(arg_soura)
local soura_num = tonumber(arg_soura)
if soura_num and (soura_num < 1 or soura_num > 114) then
return 0, error_comment(cfg.msgs.soura_num_err)
end
if not soura_num then
soura_num = soura_number(arg_soura)
if not soura_num then
return 0, error_comment(cfg.msgs.soura_name_err)
end
end
return soura_num, ""
end
local function load_data()
if lua_data[quran_shape] then
quran_data = mw.loadData('Module:Quran/data ' .. quran_shape)
else
quran_data = mw.loadJsonData('Module:Quran/data ' .. quran_shape .. '.json')
end
end
local function aya_number(aya_num, frame)
if aya_symbol_template then
if cfg.presentation[aya_symbol_template] then
return substitute(cfg.presentation[aya_symbol_template], shape_numbers(aya_num))
else
return frame:expandTemplate{ title = aya_symbol_template, args = { aya_num } }
end
else
return '۝' .. eastern_numbers(aya_num)
end
end
local function get_ayat(soura, start_aya, end_aya)
local ret_text = ''
for aya_num = start_aya, end_aya do
ret_text = ret_text .. quran_data[soura][aya_num] .. aya_number(aya_num)
end
return string.sub(ret_text,1,#ret_text -1)
end
local function aya(frame)
local A = argument_wrapper({frame.args, frame:getParent().args})
local soura = tonumber(A[1] or A.soura or A.s)
local aya = tonumber(A.from_aya or A.a)
local ret = ''
if soura> 114 or soura<1 then
return error_comment(cfg.msgs.soura_num_err)
end
if A.shape then
set_quran_shape(A.shape)
end
local soura_data = gdata.sour[soura]
local aya_count = soura_count(soura)
if aya <1 or aya > aya_count then
return error_comment(cfg.msgs.from_aya_err,{soura_data.name,aya_count})
end
load_data()
local ret = quran_data[soura][aya]
if quran_shape == "KFGQPC" then
ret= string.gsub(ret,'آ', 'آ')
end
return ret
end
local function search(A, frame)
local soura= A[1] or A.soura
local start_soura
local ret = ''
sour = gdata.sour
if soura then
start_soura, errmsg = arg2soura_num(soura)
if start_soura == 0 then
return errmsg
end
end
quran_norm = mw.loadData('Module:Quran/data norm')
start_soura = start_soura or 1
for soura_num=start_soura,114 do
for aya_num=1,sour[soura_num].ayacount do
if quran_norm[soura_num][aya_num]:gsub("\160"," "):find(A.search) then
if not quran_data then load_data() end
ret = ret .. "*" .. substitute(cfg.presentation.quran, { quran_shape, quran_data[soura_num][aya_num] .. ' ' .. aya_number(aya_num,frame)}) .. substitute(cfg.presentation.cite_quran, { sour[soura_num].name, ':' .. aya_num}) .. "\n"
if A.viewtemplate and A.viewtemplate=="1" or A.viewtemplate=="نعم" then
ret = ret .. substitute("<pre>{{قرآن|$1|$2}}</pre>",{soura_num,aya_num}) .. "\n"
end
end
end
end
if #ret==0 then
return error_comment("لا نتائج")
else
return ret
end
end
local function ayat(frame)
local A = argument_wrapper({frame:getParent().args, frame.args})
if A.shape and string.len(A.shape)>0 then
set_quran_shape(A.shape)
if quran_shape=='Text' then
strspace = "[ " .. string.char(160) .. "]"
else
strspace = " "
end
end
if A.aya_template and (cfg.presentation[A.aya_template] or mw.title.new("template:" .. A.aya_template).exists) then
aya_symbol_template = A.aya_template
end
if A.search and string.len(A.search)>0 then
return search(A,frame)
end
sour = gdata.sour
local ret_text = ""
if A.from_aya and string.len(A.from_aya)> 0 then
local soura_num, soura, from_aya, to_aya, errmsg
soura_num, errmsg = arg2soura_num(A[1] or A.soura)
if soura_num == 0 then
return errmsg
end
soura = sour[soura_num]
local aya_count = soura_count(soura_num)
from_aya = tonumber(A.from_aya)
if not from_aya or from_aya>aya_count or from_aya<1 then
return error_comment(cfg.msgs.from_aya_err,{soura.name,aya_count})
end
local arg_aya_add = A.addition_ayat
if arg_aya_add then
to_aya = from_aya + (tonumber(arg_aya_add) or 0)
elseif A.to_aya then
to_aya = tonumber(A.to_aya)
else
to_aya = from_aya
end
if to_aya > aya_count or to_aya<1 then
return error_comment(cfg.msgs.to_aya_err, {soura.name,aya_count})
end
load_data()
for aya_num = from_aya, to_aya do
local fullaya=true
if (aya_num==from_aya or aya_num == to_aya) and (A.from_word or A.to_word) then
local temp_text
temp_text, fullaya = some_aya(soura_num,aya_num,
(aya_num==from_aya and A.from_word or nil),
(aya_num == to_aya and A.to_word or nil))
if temp_text:find("error") then
return temp_text
end
ret_text = ret_text .. temp_text
else
ret_text = ret_text .. quran_data[soura_num][aya_num]
end
if fullaya then
ret_text = ret_text .. ' ' .. aya_number(aya_num, frame) .. ' '
end
end
ret_text = quran_replaces(ret_text)
return substitute(cfg.presentation.quran, { quran_shape, text.trim(ret_text) }) .. substitute(cfg.presentation.cite_quran, { soura.name, ':' .. from_aya .. ((to_aya>from_aya) and ("–" .. to_aya) or '')})
else
ret_text = substitute(cfg.presentation.quran, { quran_shape, A[1] or A.user_text })
if A.s and string.len(A.s)>0 then
local soura_num, errmsg = arg2soura_num(A.s)
if soura_num == 0 then
return errmsg
end
local soura=sour[soura_num]
ret_text = ret_text .. substitute(cfg.presentation.cite_quran, { soura.name, (A.a and (":" .. A.a) or "")})
end
return ret_text
end
end
local function number_of_soura( frame )
local idx = tonumber(frame.args[1])
if idx and idx>=1 and idx <=114 then
return idx
end
sour = gdata.sour
return soura_number(frame.args[1])
end
local function soura_name( frame )
sour = gdata.sour
local idx = arg2soura_num(frame.args[1]) + (tonumber(frame.args[2]) or 0)
if not idx or idx<1 or idx > 114 then
return nil
end
return sour[idx].name
end
local function aya_count( frame )
local idx = tonumber(frame.args[1])
if not idx or idx<1 or idx > 114 then
return nil
end
local argshape = frame:getParent().args[2] or frame.args[2]
if argshape then
set_quran_shape(argshape)
end
return soura_count(idx)
end
local function ws_soura(frame)
quran_shape = "Othmani"
local A = argument_wrapper({frame:getParent().args, frame.args})
if A.shape and string.len(A.shape)>0 then
set_quran_shape(A.shape)
if quran_shape=='Text' then
strspace = "[ " .. string.char(160) .. "]"
else
strspace = " "
end
end
if quran_shape == "DKhatt" then
aya_symbol_template = nil
end
local soura_num, soura,hzb, soura_hzb, errmsg
sour = gdata.sour
local ret_text = ""
soura_num, errmsg = arg2soura_num(frame.args[1])
if soura_num == 0 then
return errmsg
end
hzb = gdata.ahzab[gdata.shape_def[quran_shape] and gdata.shape_def[quran_shape].hzb or 1]
soura_hzb = hzb and hzb[soura_num] or nil
local hzb_counter
-- if soura_hzb and hzb.addition then
-- for _,v in ipairs(soura_hzb) do
-- hzb_counter = v
-- break
-- end
-- end
load_data()
local aya_num = 1
local bsmala = gdata.bsmala[quran_shape]
-- إضافة البسملة لغير الفاتحة أو التوبة
if not (soura_num == 9) then
if soura_num==1 and bsmala.s1aya then
ret_text = '<center>' .. bsmala[bsmala.dif[soura_num] or 1] .. ' ' .. aya_number(aya_num, frame) .. '</center>'
aya_num = 2
else
ret_text = '<center>' .. bsmala[bsmala.dif[soura_num] or 1] .. '</center>'
end
end
while quran_data[soura_num][aya_num] do
local hzb_text = ""
local aya_text = quran_data[soura_num][aya_num]
local hzbargs
if soura_hzb then
if soura_hzb[aya_num] or (hzb.addition and string.find(aya_text, "۞")) then
hzb_counter = soura_hzb[aya_num] or (hzb_counter + hzb.addition)
hzbargs = {
math.floor(hzb_counter/ (hzb.hparts * 2) + 1),
math.floor(hzb_counter/hzb.hparts) + 1,
}
local hzb_msg = ""
local hl = 3
if hzb_counter % (2 * hzb.hparts) == 0 then
hzb_msg = 'الجزء ' .. hzbargs[1] .. "، الحزب " .. hzbargs[2]
hl=2
else
hzb_msg = mw.message.newRawMessage (hzb.fra[hzb_counter% hzb.hparts], hzbargs):plain()
end
if aya_num>1 then
hzb_text = '<span class="start-of-rub" title="' .. hzb_msg .. '">۞</span>'
end
hzb_text = hzb_text .. '<span class="hzb-fra">' .. hzb_msg .. '</span> '
end
end
if hzb_text ~="" then
local r = 0
if aya_num > 1 then
aya_text, r =string.gsub(aya_text, "۞ ", hzb_text)
end
if r==0 then
aya_text = hzb_text .. aya_text
end
end
if string.sub(aya_text,-1) == '۩' then
aya_text = aya_text .. '<span class="hzb-fra">سجدة</span>'
end
ret_text = ret_text .. aya_text .. ' ' .. aya_number(aya_num, frame) .. ' '
aya_num = aya_num + 1
end
ret_text= quran_replaces(ret_text)
return '<div class="soura-block quran-' .. quran_shape .. '">' .. text.trim(ret_text) .. '</div>'
end
local function ws_soura_header(frame)
quran_shape = "Othmani"
local A = argument_wrapper({frame:getParent().args, frame.args})
local basepage = mw.title.getCurrentTitle().basePageTitle.fullText
local bsae2shape = {
["القرآن الكريم (بالرسم الإملائي)"] = "text",
["القرآن الكريم (حفص)"] = "Othmani",
["القرآن الكريم (حفص، المدينة النبوية)"] = "KFGQPC",
["القرآن الكريم (ورش)"] = "Warsh",
["القرآن الكريم (قالون)"] = "Qaloun",
["القرآن الكريم (شعبة)"] = "Shuba",
["القرآن الكريم (الدوري)"] = "Douri",
["القرآن الكريم (السوسي)"] = "Sousi",
["القرآن الكريم (البزي)"] = "Bazzi",
["القرآن الكريم (قنبل)"] = "Qunbul"
}
local argshape = frame:getParent().args[2] or frame.args[2] or bsae2shape[basepage]
if argshape then
set_quran_shape(argshape)
end
sour = gdata.sour
local suraname = frame.args[1] or mw.ustring.gsub(mw.title.getCurrentTitle().subpageText,'سورة ','')
local soura_num, errmsg = arg2soura_num(suraname)
if soura_num == 0 then
return errmsg
end
local args={}
if soura_num >1 then
args["سابق"] = '[[' .. mw.title.getCurrentTitle().rootPageTitle.fullText .. '/سورة ' .. sour[soura_num-1].name ..'|سورة ' .. sour[soura_num-1].name ..']]'
end
args["عنوان"] = "[[" .. mw.title.getCurrentTitle().basePageTitle.fullText .. "|القرآن الكريم]]"
args["عنوان فرعي"] = gdata.shape_desc[quran_shape]
args["باب"]="سورة " .. sour[soura_num].name
if soura_num <114 then
args["تالي"] = '[[' .. mw.title.getCurrentTitle().rootPageTitle.fullText .. '/سورة ' .. sour[soura_num+1].name ..'|سورة ' .. sour[soura_num+1].name ..']]'
end
args["ملاحظات"] = 'آياتها ' .. soura_count(soura_num) .. "، يتوفر نص السورة أيضًا [[القرآن الكريم (توضيح)/سورة " .. sour[soura_num].name .. "|بروايات أخرى]]"
-- local ret_text = [[<div class="ws-noexport">
-- {| class="headertemplate" id="headertemplate"
-- |-
-- | class="header_backlink" |]]
-- if soura_num >1 then
-- ret_text = ret_text .. '→ [[' .. mw.title.getCurrentTitle().rootPageTitle.fullText .. '/سورة ' .. sour[soura_num-1].name ..'|' .. 'سورة ' .. sour[soura_num-1].name ..']]'
-- end
-- ret_text = ret_text .. "\n| class=\"header_title\" | '''[[" .. mw.title.getCurrentTitle().basePageTitle.fullText .. "|القرآن الكريم]]'''\n\nسورة " .. sour[soura_num].name .. '<br>آياتها ' .. soura_count(soura_num)
-- ret_text = ret_text .. '\n| class="header_forelink" |'
-- ret_text = ret_text .. '[[' .. mw.title.getCurrentTitle().rootPageTitle.fullText .. '/سورة ' .. sour[soura_num+1].name ..'|' .. 'سورة ' .. sour[soura_num+1].name ..']] ←'
-- end
-- ret_text = ret_text .. '\n|}\n{| class="header_notes"\n|-\n|' .. gdata.shape_desc[quran_shape] .. "، يتوفر نص السورة أيضًا [[القرآن الكريم (توضيح)/سورة " .. sour[soura_num].name .. "|بروايات أخرى]]\n|}</div>"
return frame:expandTemplate{ title = "ترويسة", args=args }
end
local function test()
return "OK"
end
return {
aya = aya,
ayat=ayat,
number_of_soura = number_of_soura,
soura_name = soura_name,
aya_count = aya_count,
ws_soura = ws_soura,
ws_soura_header = ws_soura_header,
test = test
}