Module:Interlinear/sandbox2
local p = {}
local data = mw.loadData( 'Module:Interlinear/data' )
local gloss_override = {} -- for custom gloss abbreviations
local getArgs = require('Module:Arguments').getArgs
local yesno = require('Module:Yesno')
local lang_data = mw.loadData( 'Module:Lang/data' )
local gcltest = require('Module:Interlinear/sandbox2/gcl').gcl
--------------------------
-- Almost-global variables
--------------------------
local glossing_type, displaying_messages, free_translation, msg, buffer
-------------------
-- General settings
-------------------
local conf = { --settings
WordSeparator = " \n\r\t", -- Don't replace with %s as this would include non-breaking spaces
GlossAbbrPattern = "^([Ø0-9A-Z]+)$", -- this isn't a full regex, but a Lua pattern
-- NOTE: The following characters must be formatted for use in a pattern set.
GlossAbbrBoundary = "-.,;:<>‹›/\\~+=%?%s%[%]()%_\127'",
GlossExcludeTable = {I = true,}, --strings not be treated as glossing abbreviations
GlossExcludePattern = '^[0-9][0-9]+$', -- excludes strings consisting entirely of digits
GlossSmallCapsExclude = "^[AOPS]$", -- glossing abbreviations matching this pattern will not be rendered in small caps
GlossingType = "label", -- if set to "label" gloss abbreviations are formatted as an <abbr> with the "label" appearing in a tooltip
-- if set to "wikilink" the abbreviation is formatted as a wikilink to the relevant wikipedia article
-- if set to "none" abbreviations aren't formatted at all
ErrorCategory = "[[Category:Pages with errors in interlinear text]]",
AmbiguousGlossCategory = "[[Category:Articles with ambiguous glossing abbreviations]]",
MessageGlossingError = "Error(s) in interlinear glossing",
combining_gender_numbers = "[0-9][0-9]?$", --e.g. G4 '4th gender' or CL7 'class 7'
combining_gender_prefixes = {G = "gender", CL = "class"},
combining_person = {
["1"] = "first person",
["2"] = "second person",
["3"] = "third person"
},
combining_number = {
S = "singular", SG = "singular",
P = "plural", PL = "plural",
D = "dual", DU = "dual",
TRI = "trial"
},
combining_gender = {
F = "feminine",
M = "masculine",
N = "neuter"
},
LowerCaseGlosses = {
["1sg"] = true, ["2sg"] = true, ["3sg"] = true,
["1du"] = true, ["2du"] = true, ["3du"] = true,
["1pl"] = true, ["2pl"] = true, ["3pl"] = true,
["Fsg"] = true, ["Fpl"] = true,
["Msg"] = true, ["Mpl"] = true,
},
ErrorHelpLocation = "Template:Interlinear",
}
---------------------
-- CSS styles and classes
---------------------
conf.style = { --CSS styles
GlossAbbr = "font-variant: small-caps; font-variant-numeric: oldstyle-nums; text-transform: lowercase; ", -- won't be applied to gloss abbreviations containing lower-case characters
}
conf.class = { --CSS classes
GlossAbbr = "gloss-abbr",
GlossAbbrAmb = "gloss-abbr-ambiguous",
GlossAbbrError = "gloss-abbr-error",
ErrorMessage = "error",
}
---------------------
-- Section transclusion
---------------------
local page_content = nil -- lazy initilization
local function get_section(frame, section_name)
if page_content == nil then
local current_title = mw.title.getCurrentTitle()
page_content = current_title:getContent()
end
if page_content then
if mw.ustring.find(page_content, section_name, 1, true) then
return frame:preprocess('{{#section:{{FULLPAGENAME}}|' .. section_name .. '}}')
end
end
return ''
end
---------------------
-- Sundry small functions
---------------------
local function normalise(str)
return mw.ustring.gsub(str,"[" .. conf.WordSeparator .. "]+"," ")
end
local function tidyCss(str)
str = mw.ustring.gsub(str, '^[\"\']*(.-)[\"\']*$', "%1") -- trims quotation marks
if mw.ustring.sub(str, -1) ~= ";" then str = str .. ";" end -- appends ";" if missing
return str
end
local function highlight(text)
if text then
return '<b>' .. text .. '</b>'
else return "" end
end
local function tone_sup(str)
return mw.ustring.gsub(str, "([^%p%s0-9])([0-9]+)", "%1<sup>%2</sup>")
end
local function is_empty(str) -- returns "false" if its argument is a string containing chars other than spaces &c.
if not str then return true end
if mw.ustring.find(str, "[^" .. conf.WordSeparator .. "]")
then return false
else return true end
end
local function help_link (anchor)
if anchor then
return " ([[" .. conf.ErrorHelpLocation .. "#" .. anchor .. "|help]])"
else return "" end
end
--------------------
-- The following two functions update the glossing settings based on the received
-- template arguments. set_global_glossing_settings() updates the global settings
-- that are valid for all gloss abbreviations. set_glossing_type()
-- returns the glossing type, which can vary between the different lines.
--------------------
local function set_global_glossing_settings(a)
local style = ""
if a.style then style = tidyCss(a.style) end
if a.underline == "no" then
style = style .. "text-decoration: none;" end
if a.small_caps == "no" then
style = style .. "font-variant:normal; text-transform: none;" end
--if style ~= "" then conf.style.GlossAbbr = conf.style.GlossAbbr .. style end
end
local function set_glossing_type(glossing)
if glossing then
local GlossingType
glossing = mw.ustring.lower(mw.text.trim(glossing))
if mw.ustring.find(glossing, 'link') then
GlossingType = "wikilink"
elseif mw.ustring.find(glossing, 'label')
or mw.ustring.find(glossing, 'no link') then
GlossingType = 'label'
elseif mw.ustring.find(glossing, 'no abbr') then
GlossingType = "no abbr"
elseif yesno(glossing) == false then
GlossingType = nil
elseif yesno(glossing) then
GlossingType = conf.GlossingType
else
msg:add('error', 'Glossing type "' .. glossing .. '" not recognised') end
return GlossingType
else error("set_glossing_type: 'glossing' is nil or false", 2)
end
end
local function set_custom_glosses(list)
local abbs = mw.text.split(list, '[;\n\t]')
for _,v in pairs(abbs) do
local gloss = mw.text.split(v, ':')
local a = mw.text.trim(gloss[1])
if a and a ~= "" then
gloss_override[a] = {}
gloss_override[a].expansion = gloss[2]
gloss_override[a].wikipage = gloss[3]
end
end
end
---------------------
-- The UserMessages object contains and processes error messages and warnings
---------------------
local UserMessages = {errors = {}, warnings = {}, gloss_messages = {}}
function UserMessages:add(msgtype, text, gloss)
if msgtype == "gloss_message" then
self.gloss_messages[gloss] = text
elseif msgtype == "warning" then
table.insert(self.warnings, text)
elseif msgtype == "non-repeating error" then
self.errors.nre = text
elseif msgtype == "ambiguous gloss" then
self.if_ambiguous_glosses = true
elseif msgtype == "error" then
table.insert(self.errors, text)
else return error("UserMessages:add(): unknown message type", 2)
end
end
function UserMessages:print_errors()
local out = ""
local namespace = mw.title.getCurrentTitle().namespace
if next(self.errors) or self.warnings[1] then
local err_span = mw.html.create("span")
err_span:addClass(conf.class.ErrorMessage)
for _,v in pairs(self.errors) do
err_span:wikitext(" " .. v .. ";") end
if namespace % 2 == 0 and namespace ~= 2 -- non-talk namespaces, excluding user pages; if modifying please update the description on the category page
then err_span:wikitext(conf.ErrorCategory)
end
out = tostring(err_span)
mw.addWarning(conf.MessageGlossingError)
end
if self.if_ambiguous_glosses then
if namespace == 0 -- article namespace
then out = out .. conf.AmbiguousGlossCategory -- this category will only track articles
end
end
return out
end
function UserMessages:print_warnings()
local out = ""
-- Messages and warnings get displayed only if the page is being viewed in "preview" mode:
if displaying_messages and (next(self.gloss_messages) or next(self.warnings)) then
local div = mw.html.create("div")
div:addClass("interlinear-preview-warning")
:wikitext("<i>This message box is shown only in preview:</i>")
:newline()
for _,v in ipairs(self.warnings) do
local p = div:tag("p")
p:addClass(conf.class.ErrorMessage)
p:wikitext(v)
end
if self.gloss_messages then
div:wikitext("<p> To change any of the following default expansions, see [[Template:Interlinear/doc#Custom abbreviations|the template's documentation]]:</p>")
end
for _,v in pairs(self.gloss_messages) do
div:wikitext("<p>" .. v .. "</p>")
end
out = out .. "\n\n" .. tostring(div)
end
return out
end
---------------------
-- gloss_lookup() receives a gloss abbreviation and tries to uncover its meaning.
---------------------
local function gloss_lookup(a, label, wikilink)
local _label, _wikilink, _lookup, source = nil, nil, nil, nil
if gloss_override[a] then
_lookup = gloss_override[a]
source = "local"
elseif data.abbreviations[a] then _lookup = data.abbreviations[a] end
if _lookup and _lookup.expansion ~= "" then
_label, _wikilink = _lookup.expansion, _lookup.wikipage
else
local prefix = mw.ustring.sub(a,1,1)
local suffix = mw.ustring.sub(a,2)
if conf.combining_person[prefix] then -- is it of the form 1PL or 3FS?
_label = conf.combining_person[prefix]
local _suffix = conf.combining_number[suffix] or conf.combining_gender[suffix]
if _suffix then
_label = _label .. ", " .. _suffix
else
local suffix1 = mw.ustring.sub(suffix,1,1)
local suffix2 = mw.ustring.sub(suffix,2)
if conf.combining_gender[suffix1]
and conf.combining_number[suffix2] then
_label = _label .. ", " .. conf.combining_gender[suffix1] .. ", " .. conf.combining_number[suffix2]
else _label = nil end
end
elseif mw.ustring.match(suffix,conf.combining_gender_numbers) then -- cases like G4 = gender 4
local _i,_j = mw.ustring.find(a, conf.combining_gender_numbers)
local _pre = mw.ustring.sub(a, 1, _i - 1)
local _suff = mw.ustring.sub(a, _i)
if conf.combining_gender_prefixes[_pre] then
_label = conf.combining_gender_prefixes[_pre] .. " " .. _suff
end
elseif prefix == "N" then -- dealing with cases like NPST = non-past
local s = gloss_override[suffix] or data.abbreviations[suffix]
if s ~= nil and not s.ExcludeNegation then
_label = "non-" .. s.expansion
_wikilink = s.wikipage
end
s = nil
end
end
if _label == "" then _label = nil end
if _wikilink == "" then _wikilink = nil end
if not label then label = _label end
if not wikilink then wikilink = _wikilink end
return label, wikilink, source
end
---------------------
-- format_gloss() calls gloss_lookup() to find the meaning of a gloss
-- abbreviation, which it then proceeds to format
---------------------
local function format_gloss(gloss, label, wikilink)
if string.sub(gloss,1,3) == "000" then -- checks for a common component of exposed strip markers (see [[:mw:Strip marker]])
return gloss
end
local gloss2 = mw.ustring.gsub(gloss,"<.->","") -- remove any html fluff
gloss2 = mw.ustring.gsub(gloss2, "%'%'+", "") -- remove wiki bold/italic formatting
gloss2 = mw.text.trim(mw.ustring.upper(gloss2))
if not (label or wikilink)
or (not label and glossing_type == "label")
or (not wikilink and glossing_type == "wikilink")
then
if glossing_type ~= "no abbr"
then label, wikilink, source = gloss_lookup(gloss2, label, wikilink)
end
end
local gloss_node
if glossing_type == "no abbr"
then gloss_node = mw.html.create("span")
else gloss_node = mw.html.create("abbr") end
gloss_node:addClass("gloss-abbr")
if label or wikilink then
--if not mw.ustring.match(gloss, "%l") -- excluding glosses that contain lower-case characters
-- and not mw.ustring.match(gloss,conf.GlossSmallCapsExclude) -- and also excluding A, O etc. from rendering in small caps
-- then gloss_node:addClass("gloss_node")
--end
local abbr_label
if label then abbr_label = label
else abbr_label = wikilink end
gloss_node:attr("title", abbr_label)
if source ~= "local" and data.abbreviations[gloss2] then
if data.abbreviations[gloss2].ambiguous then
gloss_node:addClass(conf.class.GlossAbbrAmb)
msg:add("ambiguous gloss")
end
end
if glossing_type == "wikilink" and wikilink
then gloss_node:wikitext("[[", wikilink, "|" , gloss, "]]")
else gloss_node:wikitext(gloss) end
if source ~= "local" and displaying_messages then -- logging gloss lookups:
local message = ""
if label then
message = "assuming " .. gloss2 .. " means \"" .. abbr_label .. "\";" end
if glossing_type == "wikilink" and wikilink then
message = message .. " linking to [[" .. wikilink .. "]];"
end
msg:add("gloss_message", message, gloss)
end
elseif glossing_type == "no abbr"
then gloss_node
:addClass("gloss-abbr")
:wikitext(gloss)
else
if displaying_messages then
msg:add("warning", "Gloss abbreviation " .. highlight(gloss2) .. " not recognised" .. help_link("gloss abbr"))
end
msg:add("non-repeating error", "Unknown glossing abbreviation(s)" .. help_link("gloss abbr"))
gloss_node
:addClass(conf.class.GlossAbbrError)
:addClass("error")
:attr("title", gloss2 .. ": glossing abbreviation not found")
:wikitext(gloss)
end
return tostring(gloss_node)
end
---------------------
-- find_gloss() parses a word into morphemes, and it calls format_gloss()
-- for anything that looks like a glossing abbreviation.
---------------------
local function find_gloss(word)
local function scan_gloss(boundary, gloss_abbr) -- checks a morpheme if it is a gloss abbreviation
if (mw.ustring.match(gloss_abbr, conf.GlossAbbrPattern)
or conf.LowerCaseGlosses[gloss_abbr])
and not (conf.GlossExcludeTable[gloss_abbr]
or mw.ustring.match(gloss_abbr, conf.GlossExcludePattern))
then gloss_abbr = format_gloss(gloss_abbr) -- frame:extensionTag('gcl', gloss_abbr)
end
return boundary .. gloss_abbr
end
local word = mw.text.decode(word, true)
if word == "I" -- for the case of the English word "I", the 1SG pronoun
then return word end
local pattern = "([" .. conf.GlossAbbrBoundary .. "]?)([^" .. conf.GlossAbbrBoundary .. "]+)"
word = mw.ustring.gsub(word, pattern, scan_gloss) -- splits into morphemes
return word
end
---------------------
-- The main purpose of the bletcherous parse() is to split a line into words and and then for each eligible word
-- to call find_gloss(). The parser outputs the individual words (with any gloss abbreviation formatting applied).
-- The simple job of splitting at whitespaces has been made complicated by a) the fact that the input can contain
-- whitespaces inside the various html elements that are the result of the application of various formatting templates;
-- and b) the need to be able to recognise the output of the template that formats custom gloss abbreviations
-- (and hence skip passing it on to find_gloss). See talk for a suggestion about its future.
---------------------
local function parse(cline, i, tags_found,ifglossing)
local function issue_error(message, culprit)
UserMessages:add("error", message .. ": ''" .. mw.ustring.sub(cline.whole, 1, i-1) .. "'''" .. culprit .. "'''''")
end
if i > cline.length then return i end --this will only be triggered if the current line has less words than line 1
local next_step, j, _, chunk
local probe = mw.ustring.sub(cline.whole,i,i)
if mw.ustring.match(probe,"[" .. conf.WordSeparator .. "]") and tags_found == 0
then next_step = i-1
elseif probe == "[" then --Wikilink?
if mw.ustring.sub(cline.whole,i+1,i+1) == "[" then
_,j,chunk = mw.ustring.find(cline.whole,"(%[%[.-%]%])", i)
else chunk = "["; j = i end --not a wikilink then
buffer = buffer .. chunk
next_step = parse(cline, j+1,tags_found,ifglossing)
elseif probe == "{" and tags_found == 0 then --curly brackets enclose a sequence of words to be treated as a single unit
_,j,chunk = mw.ustring.find(cline.whole,"(.-)(})", i+1)
if not chunk then
issue_error("Unclosed curly bracket", "{")
chunk = highlight("{"); j = i
elseif ifglossing==true then
chunk = find_gloss(chunk)
else
if cline.tone_sup then chunk = tone_sup(chunk) end
end
buffer = buffer .. chunk
next_step = parse(cline, j+1,tags_found,ifglossing)
elseif probe == "<" then -- We've encountered an HTML tag. What do we do now?
local _,j,chunk = mw.ustring.find(cline.whole,"(<.->)",i)
if not chunk then
issue_error("Unclosed angle bracket", "<")
chunk = highlight("<"); j = i
elseif mw.ustring.sub(cline.whole,i,i+1) == "</" then -- It's a CLOSING tag
if cline.glossing
and ifglossing==false
and mw.ustring.match(chunk,"</abbr>")
then ifglossing=true end
tags_found = tags_found - 1
elseif not mw.ustring.match(chunk, "/>$") -- It's an OPENING tag, unless it opens a self-closing element (in which case the element is ignored)
then if ifglossing == true -- the following checks for the output of {{ggl}}:
and mw.ustring.find(chunk, conf.class.GlossAbbr, 1, true) -- it's important that the "find" function uses literal strings and not patterns
then ifglossing = false end
tags_found = tags_found + 1
end
buffer = buffer .. chunk
next_step = parse(cline, j+1,tags_found,ifglossing)
else -- No HTML tags, so we only need to find where the word ends
local _,k,chunk = mw.ustring.find(cline.whole,"(..-)([ <[])",i)
if k then --ordinary text
if ifglossing==true then
buffer = buffer .. find_gloss(chunk)
else
if cline.tone_sup then chunk = tone_sup(chunk) end
buffer = buffer .. chunk
end
next_step = parse(cline, k, tags_found, ifglossing)
else -- reached end of string
if ifglossing == true then
chunk = find_gloss(mw.ustring.sub(cline.whole,i))
else
chunk = mw.ustring.sub(cline.whole,i)
if cline.tone_sup then chunk = tone_sup(chunk) end
end
buffer = buffer .. chunk
next_step = cline.length
end
end
return next_step
end
--------------------
-- The following function is called by Template:gcl and is used for formatting an individual glossing abbreviation
--------------------
function p.gcl(frame)
local args = getArgs(frame,{
trim = true,
removeBlanks = false,
parentOnly = true,
wrappers = {'Template:Gcl'},
})
msg = UserMessages
set_global_glossing_settings{
style = args.style,
underline = args.underline,
small_caps = args['small-caps']
}
if not args.glossing then
glossing_type = conf.GlossingType -- a global variable
else glossing_type = set_glossing_type(args.glossing)
end
local gloss, label, wikilink = args[1], args[2], args[3]
if not gloss then UserMessages:add("error", "No gloss supplied")
return UserMessages:print() end
if wikilink and not args.glossing then -- if a wikilink is supplied and glossing isn't set to 'label'...
glossing_type = 'wikilink' end -- .. then the wikilink will be formatted as such
if label == "" then label = nil end
if wikilink == "" then wikilink = nil end
local result = format_gloss(gloss, label, wikilink)
return result
end
---------------------
-- HTML stuff
---------------------
local function build_interlinear_html(args, number_of_words, line)
local interlinear_wrapper = mw.html.create("div")
interlinear_wrapper:addClass("interlinear")
-- right-to-left script
if yesno(args.rtl) == true
then interlinear_wrapper:addClass("right_to_left") end
-- box
if yesno(args.box) == true
then interlinear_wrapper:addClass("box") end
-- numbering and/or indent in the left margin
local number, indent = nil, nil
if args.number and args.number ~= ""
then number = args.number end
if args.indent and args.indent ~=""
then indent = args.indent end
if indent or number then
if not indent then indent = "4" end --default value
interlinear_wrapper:css("margin-left", indent .. 'em')
if number then
interlinear_wrapper:tag("div")
:addClass("number")
:wikitext(args.number)
end
end
--lines to display above the interlinear block
if args.top and args.top ~= "" then
interlinear_wrapper:tag("div")
:addClass("top")
:wikitext(args.top)
end
-- Producing the interlinear block
local block_wrapper = interlinear_wrapper:tag("div")
:addClass("block_wrapper")
-- non-standard spacing
local _spacing = tonumber(args.spacing)
if _spacing and _spacing <= 20 then
block_wrapper:css('column-gap', _spacing .. 'em')
--block_wrapper:css('margin-right', _spacing .. 'em')
end
for wi = 1, number_of_words do
local block = block_wrapper:tag("div")
:addClass("word_block")
for i,_ in ipairs (line) do
if line[i].whole ~= "" then -- skipping empty lines
local p = block:tag("p")
p:attr(line[i].attr)
if line[i].class then
p:addClass(line[i].class)
end
local _text = line[i].words[wi]
if _text == "" or _text == " "
then _text = " " end
-- <p> elements without content mess up the interlinear display
p:wikitext(_text)
end
end
end
--- "comments", added at the end of each line
if line.hasComments then
local comment_block = block_wrapper:tag("div")
:addClass("comment_block")
for i,_ in ipairs (line) do
local p = comment_block:tag("p")
if line[i].c then
p:wikitext(line[i].c)
else p:wikitext(" ")
end
end
end
--Add hidden lines containing the content of each line of interlinear text
-- this is for accessibility
for i,v in ipairs(line) do
local hidden_line = interlinear_wrapper:tag("p")
hidden_line:addClass("hidden_text")
:wikitext(v.whole)
end
-- Free translation
local ft_line = interlinear_wrapper:tag("p")
if free_translation and free_translation ~= "" then
ft_line:addClass("free_translation")
ft_line:wikitext(free_translation)
end
ft_line:node(msg:print_errors()) -- for error messages
-- bottom
if args.bottom and args.bottom ~= "" then
local bottom = interlinear_wrapper:tag('p')
:addClass('bottom')
:wikitext(args.bottom)
end
return interlinear_wrapper
end
--------------------
-- The following is the function called by Template:Interlinear.
-- It processes the template arguments, then calls parse() to split the input lines into words
-- and it then builds the output html.
--------------------
function p.interlinearise(frame)
---------------------
-- Prepare arguments
---------------------
local if_auto_translit = false
local args = getArgs(frame, { -- configuration for Module:Arguments
trim = true,
removeBlanks = false,
parentFirst = true,
wrappers = {
'Template:Interlinear', 'Template:Fs interlinear',
'Template:Interlinear/sandbox', 'Template:Fs interlinear/sandbox'
},
})
local template_name = frame:getParent():getTitle()
if template_name == 'Template:Fs interlinear/sandbox' then
args.italics1 = args.italics1 or "no"
args.italics2 = args.italics2 or "yes"
args.glossing3 = args.glossing3 or "yes"
if args.lang and not args.lang2 then args.lang2 = args.lang .."-Latn" end
if args.transl and not args.transl2 then args.transl2 = args.transl end
if_auto_translit = true
end
if args.wordseparator and (args.wordseparator ~= "") then
conf.WordSeparator = conf.WordSeparator .. args.wordseparator
end
local revid = frame:preprocess( "{{REVISIONID}}" )
if revid == "" then
if not args['display-messages'] or yesno(args['display-messages']) then
displaying_messages = true end-- messages will be displayed only in preview mode
end
msg = UserMessages
local line = {}
local function set_italics(n)
line[n].class = "italics"
line[n].tone_sup = true -- single digits are assumed to be tone markers and will hence be superscripted
if args['tone-superscripting'] and not yesno(args['tone-superscripting'])
then line[n].tone_sup = false end
end
if args.glossing then -- the glossing= parameter sets the default glossing type
local _gl = set_glossing_type(args.glossing)
if _gl then conf.GlossingType = _gl end
end
--this looks for a list of glossing abbreviations on the page that transcludes the template:
local _ablist_section = get_section(frame, 'list-of-glossing-abbreviations')
if _ablist_section and _ablist_section ~= "" then
local _a = mw.ustring.gsub(_ablist_section, '</?div [^\n]*>', '') -- strips off the div tags
set_custom_glosses(_a)
end
--and this looks looks for a list of abbreviations set within the template:
local _ablist = args.abbreviations
if _ablist and _ablist ~= ""
then set_custom_glosses(_ablist) end
local _ablist = args.ablist
if _ablist and _ablist ~= ""
then set_custom_glosses(_ablist) end
local _spacing = tonumber(args.spacing)
if _spacing and _spacing <= 20
then conf.style.WordDiv = 'margin-right: ' .. _spacing .. 'em;'
end
local offset, last_line = 0, 0
for j,v in ipairs(args) do -- iterates over the unnamed parameters from the template
last_line = last_line +1
if is_empty(v)
then offset = offset + 1
else
local i = j - offset
line[i] = {}
v = normalise(v)
line[i].whole = v
line[i].length = mw.ustring.len(v)
local _c = args["c" .. i]
if _c and _c ~= "" then
line.hasComments = true
line[i].c = _c
end
---prepare style arguments----
line[i].class = ""
local _style = args["style" .. i]
if not _style then _style = ""
else _style = tidyCss(_style) end
--line[i].attr holds the attributes for the <p> elements that enclose the words in line i
line[i].attr = {
style = _style,
}
local _lang = args["lang" .. i]
if _lang and #_lang > 1 then
line[i].lang = _lang
else _lang = args.lang
if _lang and #_lang > 1 and i == 1 then -- if a lang= parameter is supplied, it's assumed to apply to line 1
line[i].lang = _lang
end
end
line[i].attr.lang = line[i].lang
if yesno(args["italics" .. i]) then
set_italics(i)
end
local _transl = args["transl" .. i]
if _transl and #_transl > 1 then
_transl = mw.ustring.lower(_transl)
local _lookup = lang_data.translit_title_table[_transl]
if _lookup then
if _lang and _lookup[_lang] then
_transl = _lookup[_lang]
else _transl = _lookup.default
end
if _transl then
line[i].attr.title = _transl
end
else msg:add("error", "Transliteration scheme '" .. _transl .. "' not recognised")
end
end
local _glossing = args["glossing" .. i]
if _glossing then
line[i].glossing = set_glossing_type(_glossing)
-- Do not treat default glossing settings as custom.
if not ((i == 1 and not yesno(_glossing)) or (i == 2 and yesno(_glossing))) then
line.HasCustomGlossing = true
end
end
local _ipa = args['ipa' .. i]
if yesno(_ipa) then
line[i].class = "IPA"
end
-- formatting classes that can be applied, like "smallcaps" or "bold"
local _class = args['class' .. i]
if _class then
line[i].class = _class
line[i].glossing = false
end
if line[i].class == "" then
line[i].class = nil
end
local _wrapper = args['wrapper' .. i]
if _wrapper and line[i].words then
for j=0,number_of_words do
line[i].words[j] = frame:expandTemplate{
title = _wrapper,
args = { line[i].words[j] }
}
end
end
end -- ends the first if-statement in the loop
end -- ends the FOR cycle
local line_count = #line
if line_count == 0 then
msg:add("error", template_name .. ": no lines supplied.")
return msg:print_errors()
elseif line_count == 1 then
msg:add("error", template_name .. ": only 1 line supplied.")
return msg:print_errors()
end
if line_count > 1 then
local _italics = args.italics
local n = tonumber(_italics)
if n and n > 0 then
set_italics(n)
elseif not (_italics and not yesno(_italics)) and not (args["italics1"] and not yesno(args["italics1"])) then
set_italics(1) -- by default, the first line will get italicised, unless italics=no or italics1=no
end
-- the last unnamed parameter is assumed to be the free translation:
free_translation = args[last_line]
if not is_empty(free_translation) then
line [line_count] = nil
end --... and is thus excluded from interlinearising
end
-- If glossing isn't specified for any line, then it's chosen by default to occur
-- in the second line, unless only a single line has been supplied, in which case
-- the assumption is that it is the one containing grammatical glosses
if yesno(args.glossing) == false then
line.HasCustomGlossing = true
end
if not line.HasCustomGlossing then
if line_count == 1 then
line[1].glossing = conf.GlossingType
elseif line[2] and line[2].class ~= "" then
line[2].glossing = conf.GlossingType
end
end
set_global_glossing_settings{
style = args['glossing-style'],
underline = args.underline,
small_caps = args['small-caps']
}
---------------------
-- Segment lines into words
---------------------
for i,v in ipairs(line) do
local ifglossing = false
if line[i].glossing then
ifglossing = true -- if true the parser will attempt to format gloss abbreviations in the current line
glossing_type = line[i].glossing -- neccessarily a global variable
end
local wc, n = 1, 1
line[i].words = {}
while n <= line[i].length do
buffer = ""
n = parse(line[i], n, 0, ifglossing)+2
line[i].words[wc] = buffer
wc = wc + 1
end
end
----Check for mismatches in number of words across lines----
local number_of_words, mismatch_found = 0, false
for i,v in ipairs(line) do -- find the maximum number of words in any line
local wc = #line[i].words
if wc ~= number_of_words then
if i ~= 1 and wc ~= 0 then
mismatch_found = true
end
if wc > number_of_words then
number_of_words = wc
end
end
end
----Deal with mismatches---
if mismatch_found then
local error_text = "Mismatch in the number of words between lines: "
for i,v in ipairs(line) do
local wc = #line[i].words
error_text = error_text .. wc .. " word(s) in line " .. i .. ", "
if wc ~= number_of_words then
for current_word = wc+1, number_of_words do
line[i].words[current_word] = " "
end
end
end
if string.sub(error_text, -2) == ", "
then error_text = string.sub(error_text, 1, #error_text - 2) .. " "
end
error_text = error_text .. help_link("mismatch")
UserMessages:add("error", error_text)
end
-- Wrap in first line of {{Fs interlinear}} in {{Script}}
if template_name == 'Template:Fs interlinear/sandbox'
and args.script and line[1].words then
for i=0,number_of_words do
if args.script then
line[1].words[i] = frame:expandTemplate{
title = 'Script',
args = { args.script, line[1].words[i] }
}
end
end
end
-- Build the HTML
local div = build_interlinear_html(args, number_of_words, line)
-- Add categories
local temp_track = ""
if last_line == 2
then temp_track = "[[Category:Pages with interlinear glosses using two unnamed parameters]]"
end
if last_line > 3 and template_name ~= 'Template:Fs interlinear'
then temp_track = "[[Category:Pages with interlinear glosses using more than three unnamed parameters]]"
end
return tostring(div) .. temp_track .. msg:print_warnings()
end
return p
Content Disclaimer
Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.
- The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
- There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
- It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
- Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
- Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.