This is the module sandbox page for Module:GHG (diff). |
This module is a work in progress to reimplement Gesenius' Hebrew Grammar templates in Lua. This will allow adding new functionality, such as linking to any verse in the Hebrew Bible in the Hebrew Wikisource, and it will allow easier porting of this functionality to editions of Wikisource in other languages.
The plan for now is to keep using the templates and to implement the internal functions, such as {{GHGpage-calc}} and {{GHGbible-ref/linker}} in Lua. At this stage the module will be used in the templates and not directly in pages. At a later stage the templates may be completely deprecated.
require('strict')
local p = {}
local getArgs = require('Module:Arguments').getArgs
local yesno = require('Module:Yesno')
local error_message = require('Module:Error')['error']
-- Begin things that need localization
local SCANNED_FILE_NAME = "Gesenius' Hebrew Grammar (1910 Kautzsch-Cowley edition).djvu"
local current_frame = mw.getCurrentFrame()
-- See also:
-- * romanPages in p._page
-- * "Invalid book name"
-- End things that need localization
function p._pageCalc(number)
if not number then
return nil
end
local romanPages = {
i = 5,
ii = 6,
iii = 7,
iv = 8,
v = 9,
vi = 10,
vii = 11,
viii = 12,
ix = 13,
x = 14,
xi = 15,
xii = 16,
xiii = 17,
xiv = 18,
xv = 19,
xvi = 20,
xviii = 22,
xix = 23
}
if romanPages[number] then
return romanPages[number]
end
return(number + 24)
end
function p._page(number)
if not number then
return nil
end
return "[[Page:" .. SCANNED_FILE_NAME .. "/" .. p._pageCalc(number) .. "|" .. number .. "]]"
end
function p.page(frame)
local args = getArgs(frame)
return p._page(args[1])
end
function p.pages(frame)
local args = getArgs(frame)
local section = args["section"]
local layout = current_frame:expandTemplate {
title = "Default layout",
args = {"Layout 2"}
}
local pagesTag = current_frame:extensionTag {
name = "pages",
content = "",
args = {
index = SCANNED_FILE_NAME,
from = p._pageCalc(args["from"]),
to = p._pageCalc(args["to"]),
fromsection = section,
tosection = section
}
}
return layout .. pagesTag
end
-- Converts a number to a Hebrew ("Gematria") number.
-- This doesn't cover all the Hebrew numbers, but only what is needed for
-- Bible chapters and verses.
local function toHebrewNumber(numberStr)
local hebrewNumber = ""
local numberNum = tonumber(numberStr) or 0
if (numberNum >= 100) then
hebrewNumber = hebrewNumber .. "ק"
end
local modulo100 = numberNum % 100
if (modulo100 == 15) then
return hebrewNumber .. "טו"
end
if (modulo100 == 16) then
return hebrewNumber .. "טז"
end
local onesNumber = numberNum % 10
local tensNumber = math.floor(modulo100 / 10)
local tensLetter = {
"י",
"כ",
"ל",
"מ",
"נ",
"ס",
"ע",
"פ",
"צ"
}
if (tensNumber ~= 0) then
hebrewNumber = hebrewNumber .. tensLetter[tensNumber]
end
local onesLetter = {
"א",
"ב",
"ג",
"ד",
"ה",
"ו",
"ז",
"ח",
"ט"
}
if (onesNumber ~= 0) then
hebrewNumber = hebrewNumber .. onesLetter[onesNumber]
end
return hebrewNumber
end
-- Converts a number to a Greek numeral.
-- This doesn't cover all the Greek numbers, but only what is needed for
-- Bible chapters and verses.
local function toGreekNumber(numberStr)
local numberNum = tonumber(numberStr, 10)
local greekNumber = ""
local onesLetter = { "Α", "Β", "Γ", "Δ", "Ε", "ΣΤ", "Ζ", "Η", "Θ" }
local tensLetter = { "Ι", "Κ", "Λ", "Μ", "Ν", "Ξ", "Ο", "Π", "ϟ" }
if (numberNum >= 10) then
tensNumber = math.floor(numberNum / 10)
greekNumber = greekNumber .. tensLetter[tensNumber]
end
local onesNumber = numberNum % 10
if (onesNumber > 0) then
greekNumber = greekNumber .. onesLetter[onesNumber]
end
greekNumber = greekNumber .. "'"
return greekNumber
end
local function verseLink(targetLanguage, linkTargetTitle, chapter, verseStr)
local verseNum = string.match(verseStr, "[0-9]+")
local verseLinkWikitext = "[[:" .. targetLanguage .. ":" .. linkTargetTitle
if (targetLanguage == "he") then
verseLinkWikitext = verseLinkWikitext .. " " .. toHebrewNumber(chapter) .. " " .. toHebrewNumber(verseNum) .. "|" .. verseStr
if (string.match(verseStr, "f$")) then
verseLinkWikitext = verseLinkWikitext .. "."
end
verseLinkWikitext = verseLinkWikitext .. "]]"
else
-- Greek Wikisource doesn't support verses at the moment
end
return verseLinkWikitext
end
local function verseLinks(targetLanguage, linkTargetTitle, chapter, versesStr)
-- Greek Wikisource and Hebrew Sirac don't support verses at the moment
if (targetLanguage == "el" or linkTargetTitle == "בן סירא") then
return versesStr
end
local formattedLinks = {}
local verseStrs = mw.text.split(versesStr or "", "%." )
for i, verse in ipairs(verseStrs) do
if verse then
formattedLinks[i] = verseLink(
targetLanguage,
linkTargetTitle,
chapter,
verse
)
end
end
local wholeVersesString = table.concat(formattedLinks, ".")
-- Remove repeated periods (can appear after f./ff.)
wholeVersesString = mw.ustring.gsub( wholeVersesString, "%.%]%]%.", "]].")
-- Remove spaces in the beginning of links
wholeVersesString = mw.ustring.gsub( wholeVersesString, "%| ", "|")
wholeVersesString = mw.ustring.gsub( wholeVersesString, "f%]%]%.%[%[", "f]]. [[")
return wholeVersesString
end
local function bibleRefContent(book, chapter, verse, hideBook, fullSizeVerse, actualBook)
local linkTargetBook = {
["Gn"] = "בראשית",
["Gen"] = "בראשית",
["Gn."] = "בראשית",
["Ex"] = "שמות",
["Lv"] = "ויקרא",
["Lev"] = "ויקרא",
["Lv."] = "ויקרא",
["Nu"] = "במדבר",
["Dt"] = "דברים",
["Dt."] = "דברים",
["Jos"] = "יהושע",
["Ju"] = "שופטים",
["Jud"] = "שופטים",
["Ju."] = "שופטים",
["1 S"] = "שמואל א",
["2 S"] = "שמואל ב",
["1 K"] = "מלכים א",
["2 K"] = "מלכים ב",
["Is"] = "ישעיהו",
["Is."] = "ישעיהו",
["Jer"] = "ירמיהו",
["Je"] = "ירמיהו",
["Jer."] = "ירמיהו",
["Ez"] = "יחזקאל",
["Ez."] = "יחזקאל",
["Eze"] = "יחזקאל",
["Hos"] = "הושע",
["Ho"] = "הושע",
["Jo"] = "יואל",
["Joel"] = "יואל",
["Am"] = "עמוס",
["Amos"] = "עמוס",
["Ob"] = "עובדיה",
["Jon"] = "יונה",
["Jn"] = "יונה",
["Mi"] = "מיכה",
["Mic"] = "מיכה",
["Na"] = "נחום",
["Nah"] = "נחום",
["Hb"] = "חבקוק",
["Hab"] = "חבקוק",
["Zp"] = "צפניה",
["Hag"] = "חגי",
["Zc"] = "זכריה",
["Mal"] = "מלאכי",
["Mal."] = "מלאכי",
["Ps"] = "תהלים",
["PsPs"] = "תהלים",
["Pr"] = "משלי",
["Jb"] = "איוב",
["Job"] = "איוב",
["Ct"] = "שיר השירים",
["Cant"] = "שיר השירים",
["Ru"] = "רות",
["La"] = "איכה",
["Lam"] = "איכה",
["Ec"] = "קהלת",
["Est"] = "אסתר",
["Dn"] = "דניאל",
["Ezr"] = "עזרא",
["Neh"] = "נחמיה",
["Ne"] = "נחמיה",
["1 Ch"] = "דברי הימים א",
["1 Chr"] = "דברי הימים א",
["2 Ch"] = "דברי הימים ב",
["2 Chr"] = "דברי הימים ב",
["3 Ezr"] = "Έσδρας_Α",
["1 Macc."] = "Μακκαβαίων_Α'",
-- The only reference that uses Ecclus is relevant for the Hebrew text
["Ecclus"] = "בן סירא",
["Sirac"] = "Σοφία_Σειράχ",
["St. Mark"] = "Κατά Μάρκον",
["John"] = "Κατά Ιωάννην",
["Acts"] = "Πράξεις των Αποστόλων",
["Rv"] = "Αποκάλυψις Ιωάννου"
}
if (not linkTargetBook[book]) or (actualBook and not linkTargetBook[actualBook]) then
return "'''''[[Template:GHGbible-ref/invalid book|Invalid book name]]'''''"
end
local greekBook = {
["3 Ezr"] = true,
["1 Macc."] = true,
["Sirac"] = true,
["Mark"] = true,
["St. Mark"] = true,
["John"] = true,
["Acts"] = true,
["Rv"] = true
}
-- At least one abbreviation is known to be ambiguous in the 1910 edition:
-- Jn may mean both Jonah and John (New Testament).
-- There may be others.
local linkTargetTitle = linkTargetBook[actualBook or book]
local targetLanguage
if (greekBook[book] or greekBook[actualBook]) then
targetLanguage = "el"
else
targetLanguage = "he"
end
local linkBeginning = "[[:" .. targetLanguage .. ":"
local linkEnding = "]]"
local bibleRef = ""
if (hideBook ~= "completely") then
if not hideBook then
local displayBook
if book == "Ps" then
displayBook = "ψ"
elseif book == "PsPs" then
displayBook = "ψψ"
else
displayBook = book
end
bibleRef = bibleRef .. displayBook .. " "
end
-- Obadiah has only one chapter, so the chapter number is not needed
-- and only the verse number is shown.
-- All the existing references to Obadiah have a verse.
if book == "Ob" then
bibleRef = bibleRef .. linkBeginning .. linkTargetTitle .. " א " .. toHebrewNumber(verse) .. "|" .. verse .. linkEnding
end
bibleRef = bibleRef .. linkBeginning .. linkTargetTitle
if (targetLanguage == "he") then
bibleRef = bibleRef .. " " .. toHebrewNumber(chapter)
else
-- This works only with some Greek books for now.
-- See el:Συζήτηση:Η_Αγία_Γραφή#Numbering_of_chapters
bibleRef = bibleRef .. "#Κεφάλαιον " .. toGreekNumber(chapter)
end
bibleRef = bibleRef .. "|"
if hideBook and (string.match(hideBook, "^v")) then
bibleRef = bibleRef .. hideBook .. "."
else
bibleRef = bibleRef .. chapter
end
bibleRef = bibleRef .. linkEnding
end
if not verse then
local verseLinksContent = verseLinks(
targetLanguage,
linkTargetTitle,
chapter,
verse
)
if not fullSizeVerse then
verseLinksContent = "<sup>" .. verseLinksContent .. "</sup>"
end
bibleRef = bibleRef .. verseLinksContent
end
return bibleRef
end
function p._bibleRef(book, chapter, verse, hideBook, fullSizeVerse, actualBook)
local content = bibleRefContent(
book,
chapter,
verse,
hideBook,
fullSizeVerse,
actualBook
)
local formattedContent = current_frame:expandTemplate {
title = "nowrap",
args = {content}
}
return formattedContent
end
function p.bibleRef(frame)
local args = getArgs(frame)
return p._bibleRef(args["book"], args["chapter"], args["verse"], args["hidebook"], args["fullsizeverse"], args["actualbook"])
end
function p._heb(text, translate, pron, en, indexitem)
local tag = "span" -- Will probably also support <div> in the future
local hebElement = mw.html.create(tag)
hebElement
:wikitext( text )
:attr( "lang", "hbo" )
:attr( "dir", "rtl" )
:addClass( "he_GHG" )
-- Calling HTML class "he_GHG" to render Hebrew text,
-- which is available at Template:GHGheb/styles.css.
if (indexitem) then
hebElement:addClass( "indexitem" )
end
local hebText = tostring( hebElement )
if pron then
hebText = hebText .. " " .. p._pron(pron)
end
if translate then
hebText = hebText .. " " .. p._translate(translate, en, "")
end
return hebText
end
function p.heb(frame)
local args = getArgs(frame)
return p._heb(args["text"], args["translate"], args["pron"], args["en"], yesno(args["indexitem"]))
end
function p._pron(text)
return current_frame:expandTemplate{
title = "nowrap",
args = {"''" .. text .. "''"}
}
end
function p.pron(frame)
local args = getArgs(frame)
return p._pron(args[1])
end
function p._translate(text, en, lang)
if not text then
return ''
end
local translation = "''" .. text .. "''"
if en then
if lang then
lang = "la"
end
local translatedElement = mw.html.create( "span" )
translatedElement
:wikitext( translation )
:attr( "lang", lang )
:attr( "title", en )
:css( "border-bottom", "1px dotted" )
translation = tostring(translatedElement)
end
return translation
end
function p.translate(frame)
local args = getArgs(frame)
return p._translate(args[1], args["en"], args["lang"])
end
local function margin_letter_fmt(text)
local span = mw.html.create('span')
:addClass('wst-serif')
:css({['font-family'] = 'serif', ['font-style'] = 'italic'})
:wikitext(text or '')
return tostring(span)
end
function p._paragraph(args)
local parNum = args[1]
local subParLetter = args[2]
local aOrB = args[3]
local nonumber = yesno(args.nonumber or false)
local nosign = yesno(args.nosign or false)
local doublesign = yesno(args.doublesign or false)
local linkText = 'Gesenius\' Hebrew Grammar/' .. (parNum or '') .. (aOrB or '')
local anchorText = ''
if subParLetter then
anchorText = '#GHGpar-' .. (parNum or '') .. (aOrB or '') .. '-' .. subParLetter
end
local numberDisplay = ''
if not nonumber then
local sign = '§ '
if nosign then
sign = ''
elseif doublesign then
sign = '§§ '
end
local abSup = ''
if aOrB then
abSup = '<sup>\'\'' .. aOrB .. '\'\'</sup>'
end
numberDisplay = sign .. (parNum or '') .. abSup
end
local letterDisplay = ''
if subParLetter then
if numberDisplay == '' then
letterDisplay = subParLetter
else
letterDisplay = ' ' .. subParLetter
end
letterDisplay = margin_letter_fmt(letterDisplay)
end
return '[[' .. linkText .. anchorText .. '|' .. numberDisplay .. letterDisplay .. ']]'
end
function p.paragraph(frame)
return p._paragraph(getArgs(frame))
end
function p._translit(args)
if not args[1] then
return error_message({'Missing first parameter'})
end
local shortcuts = {
['a-brev-acut'] = 'ắ',
['a-dier-brev'] = 'ä̆',
['a-dier-macr'] = 'ǟ',
['a-di-ma-ac '] = 'ǟ́',
['a-macr-acut'] = 'ā́',
['a-ring-macr'] = 'å̄',
['a-ring-brev'] = 'å̆',
['a-ring-circ'] = 'å̂',
['u-inv-brev '] = 'u̯',
['i-inv-brev '] = 'i̯'
}
if not shortcuts[args[1]] then
return error_message({'Error: Unknown [[' .. 'Template:GHGtranslit' .. '|GHGtranslit]] term' .. '[[Category:' .. 'GHGtranslit errors' .. ']]'})
end
return shortcuts[args[1]]
end
function p.translit(frame)
return p._translit(getArgs(frame))
end
return p