Difference between revisions of "Module:TaxonItalics"

From blackwiki
Jump to navigation Jump to search
blackwiki>Peter coxhead
(updated to tested sandbox version)
blackwiki>Peter coxhead
(updated to tested sandbox version)
Line 14: Line 14:
 
  The module also:
 
  The module also:
 
  * Ensures that the hybrid symbol, ×, is not italicized
 
  * Ensures that the hybrid symbol, ×, is not italicized
  * Has an option to abbreviate taxon names other than the last part of the name
+
  * Has an option to abbreviate parts of taxon names other than the last
 
   to the first letter (e.g. "Pinus sylvestris var. sylvestris" becomes
 
   to the first letter (e.g. "Pinus sylvestris var. sylvestris" becomes
 
   "P. s. var. sylvestris").
 
   "P. s. var. sylvestris").
Line 23: Line 23:
  
 
local cTerms3 = {
 
local cTerms3 = {
 +
    --subsp.
 
     subspecies = "subsp.",
 
     subspecies = "subsp.",
 
     ["subsp."] = "subsp.",
 
     ["subsp."] = "subsp.",
Line 28: Line 29:
 
     ["ssp."] = "subsp.",
 
     ["ssp."] = "subsp.",
 
     ssp = "subsp.",
 
     ssp = "subsp.",
 +
    --var.
 
     varietas = "var.",
 
     varietas = "var.",
 
     ["var."] = "var.",
 
     ["var."] = "var.",
 
     var = "var.",
 
     var = "var.",
 +
    --subvar.
 
     subvarietas = "subvar.",
 
     subvarietas = "subvar.",
 
     ["subvar."] = "subvar.",
 
     ["subvar."] = "subvar.",
 
     subvar = "subvar.",
 
     subvar = "subvar.",
 +
    --f.
 
     forma = "f.",
 
     forma = "f.",
 
     ["f."] = "f.",
 
     ["f."] = "f.",
 
     f = "f.",
 
     f = "f.",
 +
    --subf.
 
     subforma = "subf.",
 
     subforma = "subf.",
 
     ["subf."] = "subf.",
 
     ["subf."] = "subf.",
Line 42: Line 47:
 
     }
 
     }
 
local cTerms2 = {
 
local cTerms2 = {
 +
    --subg.
 
     subgenus = "subg.",
 
     subgenus = "subg.",
 
     ["subg."] = "subg.",
 
     ["subg."] = "subg.",
 
     subg = "subg.",
 
     subg = "subg.",
 +
    --sect.
 
     section = "sect.",
 
     section = "sect.",
 
     ["sect."] = "sect.",
 
     ["sect."] = "sect.",
 +
    sect = "sect.",
 +
    --subsect.
 
     subsection = "subsect.",
 
     subsection = "subsect.",
 +
    ["subsect."] = "subsect.",
 
     subsect = "subsect.",
 
     subsect = "subsect.",
     ["subsect."] = "subsect.",
+
     --ser.
 
     series = "ser.",
 
     series = "ser.",
 +
    ["ser."] = "ser.",
 
     ser = "ser.",
 
     ser = "ser.",
     ["ser."] = "ser.",
+
     --subser.
 
     subseries = "subser.",
 
     subseries = "subser.",
 +
    ["subser."] = "subser.",
 
     subser = "subser.",
 
     subser = "subser.",
     ["subser."] = "subser.",
+
     --cf.
 +
    cf = "cf.",
 
     ["cf."] = "cf.",
 
     ["cf."] = "cf.",
    cf = "cf.",
 
 
     ["c.f."] = "cf."
 
     ["c.f."] = "cf."
 
     }
 
     }
Line 72: Line 84:
  
 
--[[=========================================================================
 
--[[=========================================================================
Utility function to abbreviate taxon names other than the last part of the
+
Utility function to abbreviate an input string to its first character
name to the first letter.
+
followed by ".".
It is assumed that "×" will not occur as an input by itself. Both "×" and any
+
Both "×" and an HTML entity at the start of the string are skipped over in
HTML entity are ignored.
+
determining first character.
 
=============================================================================]]
 
=============================================================================]]
 
function p.abbreviate(str)
 
function p.abbreviate(str)
 
     local result = ""
 
     local result = ""
     if mw.ustring.len(str) > 1 then
+
     if mw.ustring.len(str) < 2 then
         --deal with the hybrid symbol that could be present at the start of the string
+
         --single character strings are left unchanged
 +
        result = str
 +
    else
 +
        --skip over a hybrid symbol that could be present at the start of the string
 
         if mw.ustring.sub(str,1,1) == "×" then
 
         if mw.ustring.sub(str,1,1) == "×" then
 
             result = "×"
 
             result = "×"
             str = mw.ustring.sub(str,2,#str)
+
             str = mw.ustring.sub(str,2,mw.ustring.len(str))
         end;
+
         end
         --deal with the HTML entity that could be present at the start of the string
+
         --skip over an HTML entity that could be present at the start of the string
 
         if mw.ustring.sub(str,1,1) == "&" then
 
         if mw.ustring.sub(str,1,1) == "&" then
 
             local i,dummy = mw.ustring.find(str,";",2,plain)
 
             local i,dummy = mw.ustring.find(str,";",2,plain)
             result = result .. mw.ustring.sub(str,1,i) .. mw.ustring.sub(str,i+1,i+1) .. "."
+
             result = result .. mw.ustring.sub(str,1,i)
         else
+
            str = mw.ustring.sub(str,i+1,mw.ustring.len(str))
 +
        end
 +
        --if there's anything left, reduce it to its first character plus "."
 +
         if str ~= "" then
 
             result = result .. mw.ustring.sub(str,1,1) .. "."
 
             result = result .. mw.ustring.sub(str,1,1) .. "."
 
         end
 
         end
    else
 
        result = str
 
 
     end
 
     end
 
     return result
 
     return result
Line 109: Line 125:
 
     name = string.gsub(mw.text.trim(name), "</?i>", italMarker)
 
     name = string.gsub(mw.text.trim(name), "</?i>", italMarker)
 
     name = string.gsub(string.gsub(name, "&#215;", "×"), "&times;", "×")
 
     name = string.gsub(string.gsub(name, "&#215;", "×"), "&times;", "×")
 +
    name = string.gsub(name, "</?span.->", "") -- remove any span markup
 
     name = string.gsub(name, "× ", "×&#32;")
 
     name = string.gsub(name, "× ", "×&#32;")
 
     -- now italicize and abbreviate if required
 
     -- now italicize and abbreviate if required

Revision as of 14:47, 23 August 2018

Module:TaxonItalics Template:Toolbar

Purpose

The module supports the correct italicization of scientific names. Botanical (ICNafp) names may contain "connecting terms"; these must not be italicized. The hybrid symbol, ×, should also not be italicized. The module optionally wikilinks and abbreviates italicized names.

For non-virus taxa, italics are used at the rank of genus or below. The module does not decide whether a scientific name should be italicized. Use {{Is italic taxon}} for this purpose.

Usage

  • {{#invoke:TaxonItalics|main|TAXON_NAME}} – italicizes a taxon name
  • {{#invoke:TaxonItalics|main|TAXON_NAME|linked=yes}} – italicizes a taxon name, wikilinking the italicized output to the unchanged input
  • {{#invoke:TaxonItalics|main|TAXON_NAME|abbreviated=yes}} – italicizes a taxon name, abbreviating all but the last part to the first letter

It can also be used via {{Taxon italics}}.

Examples

Just italicized

Connecting terms
  • Pinus subg. Pinus → Pinus subg. Pinus
  • P. subgenus Pinus → P. subg. Pinus
  • P. subsect. Pinaster → P. subsect. Pinaster
  • Acer tataricum subsp. ginnala → Acer tataricum subsp. ginnala
  • Aster ericoides var. ericoides → Aster ericoides var. ericoides
  • A. ericoides varietas ericoides → A. ericoides var. ericoides
  • A. e. subvar. ericoides → A. e. subvar. ericoides

Botanical names may contain only one infraspecific epithet; a string like "Fragaria vesca subsp. vesca f. semperflorens" is a classification, not a name, and is not handled by the module.

Hybrid symbols
  • Elaeagnus × submacrophylla → Elaeagnus × submacrophylla
  • ×Beallara → ×Beallara
  • &times; Beallara → × Beallara
  • {{hybrid}}Beallara → ×Beallara

Linked

Using |linked=yes

Abbreviated

Using |abbreviated=yes

  • Populus sect. Aigeiros → P. sect. Aigeiros
  • Acer tataricum subsp. ginnala → A. t. subsp. ginnala
  • [also linked] × Sorbaronia mitschurinii → × S. mitschurinii
  • [also linked] Elaeagnus × submacrophylla → E. × submacrophylla
  • Elaeagnus ×submacrophylla → E. ×submacrophylla
  • Elaeagnus {{hybrid}} submacrophylla → E. × submacrophylla

For even more examples, see the testcases.



--[[=========================================================================
Italicize a taxon name appropriately by invoking italicizeTaxonName.
The algorithm used is:
* If the name has italic markup at the start or the end, do nothing.
* Else
  * Remove (internal) italic markup.
  * If the name is made up of four words and the third word is a
    botanical connecting term, de-italicize the connecting term and add italic
    markup to the outside of the name.
  * Else if the name is made up of three words and the second word is a
    botanical connecting term or a variant of "cf.", de-italicize the
    connecting term and add italic markup to the outside of the name.
  * Else just add italic markup to the outside of the name.
 The module also:
 * Ensures that the hybrid symbol, ×, is not italicized
 * Has an option to abbreviate parts of taxon names other than the last
   to the first letter (e.g. "Pinus sylvestris var. sylvestris" becomes
   "P. s. var. sylvestris").
 * Has an option to wikilink the italicized name to the input name.
=============================================================================]]

local p = {}

local cTerms3 = {
    --subsp.
    subspecies = "subsp.",
    ["subsp."] = "subsp.",
    subsp = "subsp.",
    ["ssp."] = "subsp.",
    ssp = "subsp.",
    --var.
    varietas = "var.",
    ["var."] = "var.",
    var = "var.",
    --subvar.
    subvarietas = "subvar.",
    ["subvar."] = "subvar.",
    subvar = "subvar.",
    --f.
    forma = "f.",
    ["f."] = "f.",
    f = "f.",
    --subf.
    subforma = "subf.",
    ["subf."] = "subf.",
    subf = "subf."
    }
local cTerms2 = {
    --subg.
    subgenus = "subg.",
    ["subg."] = "subg.",
    subg = "subg.",
    --sect.
    section = "sect.",
    ["sect."] = "sect.",
    sect = "sect.",
    --subsect.
    subsection = "subsect.",
    ["subsect."] = "subsect.",
    subsect = "subsect.",
    --ser.
    series = "ser.",
    ["ser."] = "ser.",
    ser = "ser.",
    --subser.
    subseries = "subser.",
    ["subser."] = "subser.",
    subser = "subser.",
    --cf.
    cf = "cf.",
    ["cf."] = "cf.",
    ["c.f."] = "cf."
    }

--[[=========================================================================
Italicize a taxon name appropriately.
=============================================================================]]
function p.main(frame)
    local name = frame.args[1] or ''
    local linked = frame.args['linked'] == 'yes'
    local abbreviated = frame.args['abbreviated'] == 'yes'
    return p.italicizeTaxonName(name, linked, abbreviated)
end

--[[=========================================================================
Utility function to abbreviate an input string to its first character
followed by ".".
Both "×" and an HTML entity at the start of the string are skipped over in
determining first character.
=============================================================================]]
function p.abbreviate(str)
    local result = ""
    if mw.ustring.len(str) < 2 then
        --single character strings are left unchanged
        result = str
    else
        --skip over a hybrid symbol that could be present at the start of the string
        if mw.ustring.sub(str,1,1) == "×" then
            result = "×"
            str = mw.ustring.sub(str,2,mw.ustring.len(str))
        end
        --skip over an HTML entity that could be present at the start of the string
        if mw.ustring.sub(str,1,1) == "&" then
            local i,dummy = mw.ustring.find(str,";",2,plain)
            result = result .. mw.ustring.sub(str,1,i)
            str = mw.ustring.sub(str,i+1,mw.ustring.len(str))
        end
        --if there's anything left, reduce it to its first character plus "."
        if str ~= "" then
            result = result .. mw.ustring.sub(str,1,1) .. "."
        end
    end
    return result
end

--[[=========================================================================
Function which does the italicization.
=============================================================================]]
function p.italicizeTaxonName(name, linked, abbreviated)
    local italMarker = "''"
    -- begin by tidying the input name: trim; replace any use of the HTML
    -- italic tags by Wikimedia markup; replace any alternatives to the hybrid
    -- symbol by the symbol itself; prevent the hybrid symbol being treated as
    -- a 'word'
    name = string.gsub(mw.text.trim(name), "</?i>", italMarker)
    name = string.gsub(string.gsub(name, "&#215;", "×"), "&times;", "×")
    name = string.gsub(name, "</?span.->", "") -- remove any span markup
    name = string.gsub(name, "× ", "×&#32;")
    -- now italicize and abbreviate if required
    local result = name
    if name ~= '' then
        if string.sub(name,1,2) == "''" or string.sub(name,-2) == "''" then
            -- do nothing if the name already has italic markers at the start or end
        else
            name = string.gsub(name, "''", "") -- first remove any internal italics
            local words = mw.text.split(name, " ", true)
            if #words == 4 and cTerms3[words[3]] then
                -- the third word of a four word name is a connecting term
                -- ensure the connecting term isn't italicized
                words[3] = '<span style="font-style:normal;">' .. cTerms3[words[3]] .. '</span>'
                if abbreviated then
                    words[1] = p.abbreviate(words[1])
                    words[2] = p.abbreviate(words[2])
                end
                result = words[1] .. " " .. words[2] .. " " .. words[3] .. " " .. words[4]
            elseif #words == 3 and cTerms2[words[2]] then
                -- the second word of a three word name is a connecting term
                -- ensure the connecting term isn't italicized
                words[2] = '<span style="font-style:normal;">' .. cTerms2[words[2]] .. '</span>'
                if abbreviated then
                    words[1] = p.abbreviate(words[1])
                end
                result = words[1] .. " " .. words[2] .. " " .. words[3]
            else
                -- not a name as above; only deal with abbreviation
                if abbreviated then
                    if #words > 1 then
                        result = p.abbreviate(words[1])
                        for i = 2, #words-1, 1 do
                            result = result .. " " .. p.abbreviate(words[i])
                        end
                        result = result .. " " .. words[#words]
                    end
                else
                    result = name
                end
            end
            -- deal with any hybrid symbol as it should not be italicized
            result = string.gsub(result, "×", '<span style="font-style:normal;">×</span>')
            -- add outside markup
            if linked then
                if result ~= name then
                    result = "[[" .. name .. "|" .. italMarker .. result .. italMarker .. "]]"
                else
                    result = italMarker .. "[[" .. name .. "]]" .. italMarker
                end
            else
                result = italMarker .. result .. italMarker
            end
        end
    end
    return result
end

return p