-- This module implements Template:Bibleverse. local p = {}  --codes from bvf that may be in use local version_num_codes = { 	[9] = 'kjv', [31] = 'niv', [45] = 'amp', [49] = 'nasb', [64] = 'nivuk', 	[51] = 'nlt', [65] = 'msg', [76] = 'nirv', [105] = 'he', [104] = 'jps', 	[120] = 'opb', [121] = 'bb', [122] = 'bbc', [123] = 'bbl', [131] = 'nrsv', }  --possible book inputs, based on Chicago Manual local book_aliases = { 	['genesis'] = {'gen', 'gn'},                          --old testament/tanakh 	['exodus'] = {'exod', 'ex'}, 	['leviticus'] = {'lev', 'lv'}, 	['numbers'] = {'num', 'nm'}, 	['deuteronomy'] = {'deut', 'dt'}, 	['joshua'] = {'josh' , 'jo'}, 	['judges'] = {'judg', 'jgs'}, 	['ruth'] = {'ru'}, 	['1_samuel'] = {'1sam', '1sm'}, 	['2_samuel'] = {'2sam', '2sm'}, 	['1_kings'] = {'1kgs'}, 	['2_kings'] = {'2kgs'}, 	['1_chronicles'] = {'1chron', '1chr'}, 	['2_chronicles'] = {'2chron', '2chr'}, 	['ezra'] = {'ezr'}, 	['nehemiah'] = {'neh'}, 	['esther'] = {'est'}, 	['job'] = {'jb'}, 	['psalms'] = {'ps', 'pss', 'psalm'}, 	['proverbs'] = {'prov', 'prv'}, 	['ecclesiastes'] = {'eccles', 'eccl', 'qoheleth'}, 	['song_of_solomon'] = {'songofsol', 'songofsongs', 'song', 'sg', 'canticles', 'canticleofcanticles'}, 	['isaiah'] = {'isa', 'is'}, 	['jeremiah'] = {'jer'}, 	['lamentations'] = {'lam'}, 	['ezekiel'] = {'ezek', 'ez'}, 	['daniel'] = {'dan', 'dn'}, 	['hosea'] = {'hos'}, 	['joel'] = {'jl'}, 	['amos'] = {'am'}, 	['obadiah'] = {'obad', 'ob'}, 	['jonah'] = {'jon'}, 	['micah'] = {'mic', 'mi'}, 	['nahum'] = {'nah', 'na'}, 	['habakkuk'] = {'hab', 'hb'}, 	['zephaniah'] = {'zeph', 'zep'}, 	['haggai'] = {'hag', 'hg'}, 	['zechariah'] = {'zech', 'zec'}, 	['malachi'] = {'mal'}, 	['baruch'] = {'bar'},                                 --apocrypha/deuterocanon 	['ecclesiasticus'] = {'ecclus', 'wisdomofsirach', 'sirach', 'sir'}, 	['1_esdras'] = {'1esd'}, 	['2_esdras'] = {'2esd'}, 	['judith'] = {'jth', 'jdt'}, 	['1_maccabees'] = {'1macc', '1mc'}, 	['2_maccabees'] = {'2macc', '2mc'}, 	['3_maccabees'] = {'3macc', '3mc'}, 	['4_maccabees'] = {'4macc', '4mc'}, 	['prayer_of_manasseh'] = {'profman', 'prayerofmanasses'}, 	['susanna'] = {'sus'}, 	['tobit'] = {'tob', 'tb'}, 	['wisdom_of_solomon'] = {'ws', 'wisdom', 'wisofsol'}, 	['prayer_of_azariah'] = {'prayerofazariahandhymnofthethreechildren'}, 	['rest_of_esther'] = {'additionstoesther'}, 	['bel_and_the_dragon'] = {'bel'}, 	['epistle_of_jeremiah'] = {'letterofjeremiah'}, 	['matthew'] = {'matt', 'mt'},                         --new testament 	['mark'] = {'mk'}, 	['luke'] = {'lk'}, 	['john'] = {'jn'}, 	['acts'] = {'actsoftheapostles'}, 	['romans'] = {'rom'}, 	['1_corinthians'] = {'1cor'}, 	['2_corinthians'] = {'2cor'}, 	['galatians'] = {'gal'}, 	['ephesians'] = {'eph'}, 	['philippians'] = {'phil'}, 	['colossians'] = {'col'}, 	['1_thessalonians'] = {'1thess', '1thes'}, 	['2_thessalonians'] = {'2thess', '2thes'}, 	['1_timothy'] = {'1tim', '1tm'}, 	['2_timothy'] = {'2tim', '2tm'}, 	['titus'] = {'ti'}, 	['philemon'] = {'philem', 'phlm'}, 	['hebrews'] = {'heb'}, 	['james'] = {'jas'}, 	['1_peter'] = {'1pet', '1pt'}, 	['2_peter'] = {'2pet', '2pt'}, 	['1_john'] = {'1jn'}, 	['2_john'] = {'2jn'}, 	['3_john'] = {'3jn'}, 	['jude'] = {'jude'}, 	['revelation'] = {'rev', 'apocalypse', 'apoc', 'rv'}, }  local apoc = { 	['1_esdras'] = true, ['2_esdras'] = true, ['judith'] = true, ['1_maccabees'] = true, 	['2_maccabees'] = true, ['3_maccabees'] = true, ['4_maccabees'] = true, 	['prayer_of_manasseh'] = true, ['susanna'] = true, ['tobit'] = true, 	['wisdom_of_solomon'] = true, ['prayer_of_azariah'] = true, ['rest_of_esther'] = true, 	['bel_and_the_dragon'] = true, ['epistle_of_jeremiah'] = true, 	['sirach'] = true, ['ecclesiasticus'] = true, }  --these books only have one chapter, have to be handled differently local no_chapters = { 	['obadiah'] = true, ['epistle_of_jeremiah'] = true, ['prayer_of_azariah'] = true, 	['susanna'] = true, ['bel_and_the_dragon'] = true, ['prayer_of_manasseh'] = true, 	['philemon'] = true, ['2_john'] = true, ['3_john'] = true, ['jude'] = true, }  --sets the website to be used for each version, biblegateway is the fallback so don't define any for it local site_tbl = { 	nrsv = 'oremus', nrsvae = 'oremus', 	kjv = 'wikisource', asv = 'wikisource', wyc = 'wikisource', ws = 'wikisource', web = 'wikisource', 	he = 'mechon_mamre', jps = 'mechon_mamre', 	niv = 'biblica', nivuk = 'biblica', nirv = 'biblica', 	nab = 'usccb', 	bb = 'bible_hub', bbc = 'bible_hub', bbl = 'bible_hub', opb = 'bible_hub', 	esv = 'esv_bible', }  --pattern for the url of each site using _book etc. (underscore then letters [a-z]) for variables local urlpat_tbl = { 	oremus = 'https://bible.oremus.org/?passage=_book%20_vrange&version=_version', 	wikisource = 's:Bible (_version)/_book#_schap:_svers', 	mechon_mamre = 'https://mechon-mamre.org/_version_book_schap.htm#_svers', 	biblica = 'https://www.biblica.com/bible/?osis=_version:_book%20_vrange', 	usccb = 'https://bible.usccb.org/bible/_book/_schap?_svers', 	biblegateway = 'https://www.biblegateway.com/passage/?search=_book+_vrange&version=_version', 	bible_hub = 'https://_version/_book/_schap-_svers.htm', 	esv_bible = 'https://www.esv.org/_book+_schap:_svers', }  --changes book name to use in url for each site, only if necessary local site_book_tbl = { 	oremus = { 		['epistle_of_jeremiah'] = 'letter of jeremiah', 	}, 	usccb = { 		['song_of_solomon'] = 'song_of_songs', 		['wisdom_of_solomon'] = 'wisdom', 		['ecclesiasticus'] = 'sirach', 	}, 	mechon_mamre = { 		['genesis'] = '01', ['exodus'] = '02', ['leviticus'] = '03', 		['numbers'] = '04', ['deuteronomy'] = '05', ['joshua'] = '06', 		['judges'] = '07', ['1_samuel'] = '08a', ['2_samuel'] = '08b', 		['1_kings'] = '09a', ['2_kings'] = '09b', ['isaiah'] = '10', 		['jeremiah'] = '11', ['ezekiel'] = '12', ['hosea'] = '13', 		['joel'] = '14', ['amos'] = '15', ['obadiah'] = '16', ['jonah'] = '17', 		['micah'] = '18', ['nahum'] = '19', ['habakkuk'] = '20', 		['zephaniah'] = '21', ['haggai'] = '22', ['zechariah'] = '23', 		['malachi'] = '24', ['1_chronicles'] = '25a', ['2_chronicles'] = '25b', 		['psalms'] = '26', ['job'] = '27', ['proverbs'] = '28', ['ruth'] = '29', 		['song_of_solomon'] = '30', ['ecclesiastes'] = '31', ['lamentations'] = '32', 		['esther'] = '33', ['daniel'] = '34', ['ezra'] = '35a', ['nehemiah'] = '35b', 	} }  --changes to the version name to be used in urls, only if necessary local site_version_tbl = { 	mechon_mamre = { 		he = 'p/pt/pt', 		jps = 'e/et/et', 	}, 	wikisource = { 		kjv = 'King James', ['9'] = 'King James', 		asv = 'American Standard', 		ws = 'Wikisource', 		web  = 'World English', 		wyc = 'Wycliffe', 	}, 	bible_hub = { 		bb = 'biblebrowser.com', 		bbc = 'biblecommenter.com', 		bbl = 'scripturetext.com', 		opb = 'bible.cc', 	} }  local function trimArg(text) 	if type(text) == 'string' then 		text = text:match('(%S.-)%s*$')  --trimmed text or nil if empty 	end 	return text end  local function valueExists(tbl, value) 	for _, v in pairs(tbl) do 		if value == v then 			return true 		end 	end 	return false end  local function titlecase(arg) 	-- http://grammar.yourdictionary.com/capitalization/rules-for-capitalization-in-titles.html 	-- recommended by The U.S. Government Printing Office Style Manual: 	-- 'Capitalize all words in titles of publications and documents, 	-- except a, an, the, at, by, for, in, of, on, to, up, and, as, but, or, and nor.' 	local alwayslower = { 		['a'] = true, ['an'] = true, ['the'] = true, 		['and'] = true, ['but'] = true, ['or'] = true, ['for'] = true, 		['nor'] = true, ['on'] = true, ['in'] = true, ['at'] = true, ['to'] = true, 		['from'] = true, ['by'] = true, ['of'] = true, ['up'] = true, 	} 	local words = mw.text.split(mw.text.trim(arg or ), '_') 	for i, s in ipairs(words) do 		s = string.lower(s) 		if i > 1 then 			if not alwayslower[s] then 				s = mw.getContentLanguage():ucfirst(s) 			end 		else 			s = mw.getContentLanguage():ucfirst(s) 		end 		words[i] = s 	end 	return table.concat(words, '_') end  function p.main(frame) 	local targs = frame:getParent().args 	local args = {} 	for _, param in ipairs({1, 2, 3, 4, 5, 'nobook', 'wlink', 'multi'}) do 		args[param] = trimArg(targs[param]) 	end 	local default_version = 'nrsv' 	local input_book =  	local ref = 	local version =  	local version_num 	local text = 	local wikilink =  	local mainspace = mw.title.getCurrentTitle():inNamespaces(0) 	if args[1] == nil or args[2] == nil or tonumber(args[1]) ~= nil then 		-- first argument is a numeric prefix and second is book name 		input_book = trimArg((args[1] or ) .. ' ' .. (args[2] or )) or 		wikilink = trimArg((args[1] or 'Book of') .. ' ' .. (args[2] or )) or 		ref = args[3] or  		version = mw.ustring.lower(args[4] or default_version) 		text = args[5] or trimArg((input_book .. ' ' .. ref)) 	else 		-- first argument is the whole book name 		input_book = args[1] or 		wikilink = 'Book of ' .. args[1] 		ref = args[2] or  		version = mw.ustring.lower(args[3] or default_version) 		text = args[4] or (input_book .. ' ' .. ref) 	end 	if args.nobook == 'yes' then 		text = ref 	end 	if args.wlink == 'yes' then 		text = ref 		wikilink = '' .. input_book .. ' ' 	else 		wikilink = 	 	end 	if args.multi == 'yes' then 		local linktext = text:gsub(' ', '+') 		return '.. linktext .. '&version=NRSV' .. ' ' .. text .. '' 	end 	 	text = text:gsub('-', '–')  --change hyphens to en dashes (3:2-5 → 3:2–5)  	if tonumber(version) then 		version = version_num_codes[tonumber(version)] or version 		version_num = true 	end  	local errors = {} 	if version == 'jpr' or version == 'jp' then  --chabad doesn't work so reroute 		version = 'he' 		if mainspace then 			table.insert(errors, 'Category:Pages with Bible version errors') 		end 	end  	local book = input_book:gsub('%p', ):gsub(' ', '_') 	book = mw.ustring.lower(book)  	local book_found = false 	local standard = book:gsub('_', ) 	for full_book, aliases in pairs(book_aliases) do 		if standard == full_book:gsub('_', ) or valueExists(aliases, standard) then 			book = full_book 			book_found = true 			break 		end 	end  	local site = site_tbl[version] or 'biblegateway'    --fall back on biblegateway for unrecognized version because it has so many versions  	if apoc[book] and version == 'nrsv' and site == 'oremus' then  --oremus's nrsv doesn't have the apocrypha 		version = 'nrsvae'  --the anglicized version does 	end  	local urlpat = urlpat_tbl[site]  	local split_ref = mw.text.split(ref, '[-–—]')       --split the ref into the part before and after the dash/hyphen 	local s_ref = mw.text.split(split_ref[1], '%p')     --any punctuation can be used to separate chapter from verse 	local e_ref = split_ref[2] or split_ref[1] 	e_ref = mw.text.split(e_ref, '%p') 	for i, v in ipairs(s_ref) do s_ref[i] = v:gsub('%D', ) end  --remove any non-numeric character (such as f) 	for i, v in ipairs(e_ref) do e_ref[i] = v:gsub('%D', ) end  	local e_chap, e_vers, s_chap, s_vers 	local chapter_only = not s_ref[2] 	if no_chapters[book] then 		chapter_only = false 		s_chap = 1 		s_vers = s_ref[2] or s_ref[1] or 1   --verse 3 can be specified as "3" or "1:3" 		e_chap = 1 		e_vers = e_ref[2] or e_ref[1] or 1 	else 		s_chap = s_ref[1] or 1 		s_vers = s_ref[2] or 1 		if e_ref[2] or not s_ref[2] then     --chapter-chapter or chapter(:verse)?-chapter:verse 			e_chap = e_ref[1] or s_chap 		else                                 --chapter:verse-verse 			e_chap = s_chap 		end 		e_vers = e_ref[2] or e_ref[1] or s_vers 	end  	if type(site_book_tbl[site]) == 'table' then 		book = site_book_tbl[site][book] or book 	end  	book = titlecase(book)  --title case looks better at oremus where they display the input  	if site == 'mechon_mamre' then    --special case handling for components of the url 		if not tonumber(s_chap) then  --non-numeric characters were omitted above so this may not be what was entered 			error('Bibleverse error: start chapter should be a number', 0) 		end 		s_chap = string.format('%x', s_chap/10) .. (s_chap % 10) 	elseif site == 'biblica' or site == 'oremus' then 		book = book:gsub('_', '%%20') 	elseif site == 'esv_bible' or site == 'biblegateway' then 		book = book:gsub('_', '+') 	elseif site == 'bible_hub' then 		book = string.lower(book) 	elseif site == 'usccb' then 		book = book:gsub('_', '') 	end 	if type(site_version_tbl[site]) == 'table' then 		version = site_version_tbl[site][version] 	end  	local v_range 	if chapter_only then 		if e_chap == s_chap then 			v_range = s_chap 		else 			v_range = s_chap .. '–' .. e_chap 		end 	else 		if e_chap == s_chap and e_vers == s_vers then 			v_range = s_chap ..':' .. s_vers 		elseif e_chap == s_chap then 			v_range = s_chap .. ':' .. s_vers .. '–' .. e_vers 		else 			v_range = s_chap .. ':' .. s_vers .. '–' .. e_chap .. ':' .. e_vers 		end 	end  	local url = urlpat:gsub('_%l+', {  --get the components into the url 					_book    = book, 					_schap   = s_chap, 					_svers   = s_vers, 					_echap   = e_chap, 					_evers   = e_vers, 					_vrange  = v_range, 					_version = version, 				})  	local fulllink 	if site == 'wikisource' then  --interwikilink 		fulllink = wikilink .. '' .. text .. '' 	else 		fulllink = wikilink .. '[' .. url .. ' ' .. text .. ']' 	end  	if mainspace then 		if not book_found then 			table.insert(errors, 'Template:Bibleverse with invalid bookCategory:Pages with Bible book errors') 		end 		if version_num then 			table.insert(errors, 'বিষয়শ্রেণী:সংখ্যাসূচক বাইবেল সংস্করণ সূত্র সহ পাতা') 		end 	end 	return fulllink .. table.concat(errors) end  return p