Ugrás a tartalomhoz

„Modul:Cultivarbox” változatai közötti eltérés

Innen: MKOE wiki
Nincs szerkesztési összefoglaló
Nincs szerkesztési összefoglaló
 
(8 közbenső módosítás ugyanattól a felhasználótól nincs mutatva)
5. sor: 5. sor:
local p = {}
local p = {}


-- Betölti a taxonboxmodult.
-- Betölti a központi taxonbox modult és a nyers adatokat
local TaxonBox = require('Modul:Taxonbox2')
local TaxonBox = require('Modul:Taxonbox2')
local TaxonData = require('Modul:TaxonokData')
----------------------------------------------------------------------------------------------------------------
-- Segédfüggvény: Kultivárnév pontos MediaWiki aposztróf-formázása
local function parse_and_format_cultivar(full_name)
    if not full_name or full_name == "" then return "", "", "" end
    -- Megtisztítjuk az esetleges korábbi wiki tagektől
    local clean = full_name:gsub("'''''", ""):gsub("''''", ""):gsub("'''", ""):gsub("''", ""):match("^%s*(.-)%s*$")
    -- Különválasztjuk a nemzetséget (akár hibridjellel) a kultivár résztől
    local genus, cv_part = clean:match("^(.-)%s+(['\"].+['\"])$")
    if not genus or not cv_part then
        local formatted_plain = "'''" .. clean .. "'''"
        return formatted_plain, formatted_plain, clean
    end
    -- Kicseréljük a cv_part záró aposztrófját '-re, hogy a MediaWiki parser ne nyelje el a 4x ' találkozásánál
    local cv_inner = cv_part:sub(1, -2) .. "'"
    -- 1. Infobox fejléc & Besorolás sor: '''''Genus'' 'Cultivar'''' (a genus tartalmazza a × jelet is)
    local header_formatted = "'''''" .. genus .. "'' " .. cv_inner .. "'''"
    -- 2. Tudományos név szakasz: '''''Genus'' 'Cultivar'''
    local scientific_formatted = "'''''" .. genus .. "'' " .. cv_part .. "'''"
    -- 3. Tiszta név
    local plain_name = genus .. " " .. cv_part
    return header_formatted, scientific_formatted, plain_name
end


----------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------
12. sor: 44. sor:
     local args = frame:getParent().args
     local args = frame:getParent().args


    -- Miért nem elég a sima local cultivarName = args.accepted?
    -- A MediaWiki sablonoknál ha a szerkesztő ezt írja: | accepted = , az a Lua számára egy üres karakterlánc (""), nem pedig "semmi".
    -- A sima args.accepted esetén a programod azt hinné, van ott valami, és megpróbálná formázni az ürességet, ami hibához vezetne.
    -- Ezzel a logikával viszont eléred, hogy ha üres a mező, a program úgy kezelje, mintha ott se lenne (nil).
     local cultivarName  = (args.cultivar  ~= '' and args.cultivar) or nil
     local cultivarName  = (args.cultivar  ~= '' and args.cultivar) or nil
     local synonymName    = (args.synonym    ~= '' and args.synonym) or nil
     local synonymName    = (args.synonym    ~= '' and args.synonym) or nil
     local hybridName    = (args.hybrid    ~= '' and args.hybrid) or nil
     local hybridName    = (args.hybrid    ~= '' and args.hybrid) or nil
     local parentName1    = (args.parent1    ~= '' and args.parent1) or nil
     local parentName     = (args.parent     ~= '' and args.parent) or nil
    local parentName2    = (args.parent2    ~= '' and args.parent2) or nil
    local parentName3    = (args.parent3    ~= '' and args.parent3) or nil
    local parentName4    = (args.parent4    ~= '' and args.parent4) or nil
     local origin        = (args.origin     ~= '' and args.origin) or nil
     local taxonImage    = args.image or ''
     local taxonImage    = args.image or ''
     local imageTitle    = args.imageTitle or ''
     local imageTitle    = args.imageTitle or ''
    -- local synHomoBoo    = false
    -- -- Végignézzük az összes paramétert
    -- for k, v in pairs(args) do
    --    -- 1. Csak a szöveges értékeket nézzük (v)
    --    -- 2. Megtisztítjuk az esetleges szóközöktől és újsoroktól
    --    if type(v) == "string" then
    --        local cleanV = v:match("^%s*(.-)%s*$")
    --        if cleanV == 'synhomo' then
    --            synHomoBoo = true
    --            break
    --        elseif cleanV == 'synhetero' then
    --            synHomoBoo = false
    --            break
    --        end
    --    end
    -- end


     local output = ""
     local output = ""
    local clean_formatted_cultivarName = ""
    local clean_plain_cultivarName = ""


     -- cultivarName ----------------------------------
     -- cultivarName ----------------------------------
52. sor: 57. sor:
         local hierarchy = {}
         local hierarchy = {}
         local taxonName = cultivarName
         local taxonName = cultivarName
         -- local parentOverride = args.parent
         local overrideParent = parentName
        local parentOverride = parentName


         while taxonName and taxonName ~= "" and taxonName ~= "nil" do
         while taxonName and taxonName ~= "" and taxonName ~= "nil" do
             local _, cleanNameForLookup = TaxonBox.format_taxon_clean(taxonName)
             local _, lookupName = TaxonBox.format_taxon_clean(taxonName)
             local data = TaxonBox[cleanNameForLookup]
             local data = TaxonData[lookupName] or TaxonData[taxonName]


             if data then
             if data then
                 table.insert(hierarchy, { rank = data.rank, name = taxonName })
                 table.insert(hierarchy, { rank = data.rank, name = lookupName })
                 taxonName = data.parent
                 taxonName = data.parent
                overrideParent = nil
             else
             else
                 -- KULTIVÁR/FAJ FELISMERÉS:
                 -- Ha a taxon nincs az adatbázisban (összetett név, pl. kultivár)
                -- Keressük a nemzetséget (első szó) és a többit
                 local genus_part, rest_part = taxonName:match("^([%a%-%×%s%.]+)%s+(.+)$")
                 local genus_part, rest_part = taxonName:match("^([%a%-]+)%s+(.+)$")


                 if genus_part and rest_part then
                 if genus_part and rest_part then
                     -- Ha a maradék idézőjelben van (kultivár) vagy kisbetűvel kezdődik (faj)
                     local current_rank = rest_part:match("^['\"].+['\"]") and "Kultivár" or "Faj"
                    if rest_part:match("^['\"].+['\"]") or rest_part:match("^[a-z×]") then
                    table.insert(hierarchy, { rank = current_rank, name = taxonName })
                        local actual_parent = (parentOverride ~= '' and parentOverride) or genus_part


                        -- Meghatározzuk a rangot: ha van idézőjel, akkor Kultivár, egyébként Faj
                    -- Megnézzük, hogy maga a nemzetség / hibridnemzetség benne van-e a TaxonData-ban
                        local current_rank = rest_part:match("^['\"].+['\"]") and "Kultivár" or "Faj"
                    local _, genusLookup = TaxonBox.format_taxon_clean(genus_part)
                    local genusData = TaxonData[genusLookup] or TaxonData[genus_part]


                        table.insert(hierarchy, { rank = current_rank, name = taxonName })
                    if genusData then
                         taxonName = actual_parent
                         taxonName = genusLookup
                     else
                     else
                         break -- Nem faj, nem kultivár, és nincs az adatbázisban
                         -- Ha a nemzetség sincs a TaxonData-ban, manuálisan beszúrjuk a Nothogenus / Nemzetség sort
                        local genus_rank = (genus_part:sub(1, 2) == "×" or genus_part:sub(1, 1) == "x") and "Nothogenus" or "Nemzetség"
                        table.insert(hierarchy, { rank = genus_rank, name = genus_part })
 
                        if overrideParent and overrideParent ~= '' then
                            taxonName = overrideParent
                            overrideParent = nil
                        else
                            break
                        end
                     end
                     end
                 else
                 else
                     break
                     -- Egytagú név, ami hiányzik a TaxonData-ból
                    if overrideParent and overrideParent ~= '' then
                        taxonName = overrideParent
                        overrideParent = nil
                    else
                        break
                    end
                 end
                 end
             end
             end
90. sor: 109. sor:
         end
         end


         -- Itt kapja meg a két értéket
         local header_cv, _, plain_cv = parse_and_format_cultivar(cultivarName)


        -- "if cultivarName then" blokkon kívűl deklarálva, hogy a többi if blokkban is elérhető legyen
         output = output .. '{| class="infobox biota cv"\n'
        clean_formatted_cultivarName, clean_plain_cultivarName = TaxonBox.format_taxon_clean(cultivarName)
 
         output = output ..'{| class="infobox biota cv"\n'
         output = output .. "|-\n"
         output = output .. "|-\n"
         output = output .. '! class="taxonnev" colspan="2" | ' .. clean_formatted_cultivarName .. "\n"
         output = output .. '! class="taxonnev" colspan="2" | ' .. header_cv .. "\n"


         output = output .. "|-\n"
         output = output .. "|-\n"
         output = output .. '! class="suha-svg" colspan="2"|[[Fájl:cv.svg|x160px|link=]]<br>Kultivár, termesztett változat.\n'
         output = output .. '! class="suha-svg" colspan="2"|[[Fájl:cv2.png|x160px|link=]]<br>Kultivár, termesztett változat.\n'


         if taxonImage ~= '' then
         if taxonImage ~= '' then
112. sor: 128. sor:
         for i = #hierarchy, 1, -1 do
         for i = #hierarchy, 1, -1 do
             local item = hierarchy[i]
             local item = hierarchy[i]
             local rank_display = item.rank
             local rank_display = item.rank or "Taxon"
 
            -- Itt kapja meg a két értéket
            local clean_formatted, clean_plain = TaxonBox.format_taxon_clean(item.name)
 
             local name_display = ""
             local name_display = ""


             -- Kategória hivatkozás tisztított névvel
             if item.rank == "Kultivár" then
             if item.rank == "Faj" then
                local cv_header = parse_and_format_cultivar(item.name)
                 name_display = clean_formatted
                name_display = cv_header
             elseif item.rank == "Faj" then
                local clean_formatted, clean_plain = TaxonBox.format_taxon_clean(item.name)
                 name_display = "[[" .. clean_plain .. "|" .. clean_formatted .. "]]"
            elseif item.rank == "Nemzetség" then
                local _, clean_plain = TaxonBox.format_taxon_clean(item.name)
                name_display = "[[:Kategória:" .. clean_plain .. "|''" .. clean_plain .. "'']]"
            elseif item.rank == "Nothogenus" or item.rank == "Hibridnemzetség" then
                rank_display = "Hibridnemzetség"
                local _, clean_plain = TaxonBox.format_taxon_clean(item.name)
                name_display = "[[:Kategória:" .. clean_plain .. "|''" .. clean_plain .. "'']]"
             else
             else
                -- Megkeressük az alapnevet a kategória linkhez (szerzők nélkül)
                 local _, clean_plain = TaxonBox.format_taxon_clean(item.name)
                 local category_target = item.name:match("^([%a%-%.%s×]+)") or item.name -- ide nem biztos, hogy kell a × jel
                 name_display = "[[:Kategória:" .. clean_plain .. "|" .. clean_plain .. "]]"
                if item.rank == "Nemzetség" then
                    -- A nemzetség kategória linkhez a clean_formatted változót használjuk
                    name_display = "[[:Kategória:" .. clean_plain .. "|" .. clean_formatted .. "]]"
                 else
                    -- A kategória linkhez a plain (formázás mentes) változót használjuk
                    name_display = "[[:Kategória:" .. clean_plain .. "|" .. clean_plain .. "]]"
                end
             end
             end


             if rank_display == "Nemzetségcsoport" then rank_display = "Nemzetség-<br>csoport" end
             if rank_display == "Nemzetségcsoport" then rank_display = "Nemzetség-<br>csoport" end
             if rank_display == "Alnemzetségcsoport" then rank_display = "Alnemzetség-<br>csoport" end
             if rank_display == "Alnemzetség-csoport" or rank_display == "Alnemzetségcsoport" then
                rank_display = "Alnemzetség-<br>csoport"
            end


             output = output .. '|-\n'
             output = output .. '|-\n'
142. sor: 159. sor:
         end
         end


         if hierarchy[1] and hierarchy[1].rank == "Faj" then
         if hierarchy[1] and (hierarchy[1].rank == "Faj" or hierarchy[1].rank == "Kultivár") then
            local encodedTerm = mw.uri.encode(clean_plain_cultivarName)
             local encodedTerm = mw.uri.encode(plain_cv)
             -- local encodedTerm = mw.uri.encode(clean_plain)
             output = output .. '|-\n'
             output = output .. '|-\n'
             output = output .. '!colspan="2" class="taxobox-icons" |'
             output = output .. '!colspan="2" class="taxobox-icons" |'
157. sor: 173. sor:
     if synonymName then
     if synonymName then
         local syn_hierarchy = {}
         local syn_hierarchy = {}
        local taxonName2 = synonymName
         table.insert(syn_hierarchy, { rank = "Kultivár", name = synonymName })
         table.insert(syn_hierarchy, { rank = "Faj", name = taxonName2 })


         if #syn_hierarchy == 0 then
         local header_syn, _, _ = parse_and_format_cultivar(synonymName)
            return '<div style="color:red;">Cultivarbox hiba: Nem található adat a "' .. tostring(synonymName) .. '" taxonhoz.</div>'
        end


        -- 1. Kinyerjük a faji jelzőket (pl. "leucanthum" és "leucantha")
        local _, accEpithetFull = cultivarName:match("^([%a%-]+)%s+([%a%-]+)")
        local _, synEpithetFull = synonymName:match("^([%a%-]+)%s+([%a%-]+)")
        local synType = "Taxonómiai (heterotipikus)"  -- Alapértelmezett
        local synHeteroBoo = true                    -- Alapértelmezett
        if accEpithetFull and synEpithetFull then
            -- 2. Levágjuk a végződéseket (szótő kinyerése: pl. "leucanth")
            -- A minta levágja az -um, -a, -us, -is végződéseket
            local accStem = accEpithetFull:gsub("[uais][ms%a]*$", "")
            local synStem = synEpithetFull:gsub("[uais][ms%a]*$", "")
            -- 3. Ha a szótövek egyeznek, akkor nomenklatúrális
            if accStem == synStem then
                synType        = "Nomenklatúrális (homotipikus)"
                synHeteroBoo    = false
            end
            if synHomoBoo then
                synType        = "Nomenklatúrális (homotipikus)"
                synHeteroBoo    = false
            else -- synHomoBoo == false
                synType = "Taxonómiai (heterotipikus)"
                synHeteroBoo = true
            end
        end
        -- Itt kapja meg a két értéket
        local clean_formatted_synonymName, clean_plain_synonymName = TaxonBox.format_taxon_clean(synonymName)
        -- Folytatjuk az cultivarName output-ot
         output = output .. '{| class="infobox biota syn"\n'
         output = output .. '{| class="infobox biota syn"\n'
         output = output .. "|-\n"
         output = output .. "|-\n"
         output = output .. '! class="taxonnev" colspan="2" | ' .. clean_formatted_synonymName .. "\n"
         output = output .. '! class="taxonnev" colspan="2" | ' .. header_syn .. "\n"
 
         output = output .. "|-\n"
         output = output .. "|-\n"
         if synHeteroBoo then
         output = output .. '! class="suha-svg" colspan="2"|[[Fájl:syn.svg|x160px|link=]]<br>Szinonima név\n'
            output = output .. '! class="suha-svg" colspan="2"|[[Fájl:syn.svg|x160px|link=]]<br>' .. synType .. ' szinonima.<br>Az érvényes leírást lásd itt:<br>[[' .. clean_plain_cultivarName .. '|' .. clean_formatted_cultivarName .. ']]\n'
        else
            output = output .. '! class="suha-svg" colspan="2"|[[Fájl:syn.svg|x160px|link=]]<br>' .. synType .. ' szinonima\n'
        end
 
        output = output .. '|-\n'
        output = output .. '! class="besorolas" colspan="2"|Rendszertani besorolás\n'


         for i = #syn_hierarchy, 1, -1 do
         for i = #syn_hierarchy, 1, -1 do
             local item = syn_hierarchy[i]
             local item = syn_hierarchy[i]
             local rank_display = item.rank
             local syn_disp = parse_and_format_cultivar(item.name)
 
             output = output .. '|-\n'
            -- Itt kapja meg a két értéket
            output = output .. '| class = "left" | Szinonim kultivárnév\n'
            local clean_formatted, clean_plain = TaxonBox.format_taxon_clean(item.name)
            output = output .. '| class = "right" | ' .. syn_disp .. '\n'
 
            local name_display = ""
 
             -- Kategória hivatkozás tisztított névvel
            if item.rank == "Faj" then
                name_display = clean_formatted
                output = output .. '|-\n'
                output = output .. '| class = "left" | ' .. rank_display .. '\n'
                output = output .. '| class = "right" | ' .. name_display .. '\n'
            end
         end
         end
        -- if syn_hierarchy[1] and syn_hierarchy[1].rank == "Faj" then
        --    local encodedTerm = mw.uri.encode(synonymName)
        --    output = output .. '|-\n'
        --    output = output .. '!colspan="2" class="taxobox-icons" |'
        --    output = output .. '[[Fájl:Google logo gyz.svg|x30px|link=http://images.google.com/search?tbm=isch&q=' .. encodedTerm .. '|Google képek]] '
        --    output = output .. '[[Fájl:Bing fluent logo gyz.svg|x30px|link=https://www.bing.com/images/search?q=' .. encodedTerm .. '|Bing képek]]\n'
        -- end


         output = output .. '|}\n'
         output = output .. '|}\n'
246. sor: 201. sor:
     local args = frame:getParent().args
     local args = frame:getParent().args
     local names = {
     local names = {
         { val = args.cultivar,  class = "tnb tnb-cv",      class2 = "tns tns-cv",      txt= "kultivár"},
         { val = args.cultivar,  class = "tnb tnb-cv",      class2 = "tns tns-cv",      txt = "kultivár"},
         { val = args.synonym,    class = "tnb tnb-syn",    class2 = "tns tns-syn",    txt= "szinonima név"},
         { val = args.synonym,    class = "tnb tnb-syn",    class2 = "tns tns-syn",    txt = "szinonima név"},
         { val = args.hybrid,    class = "tnb tnb-hyb",    class2 = "tns tns-hyb",    txt= "hibrid név"}
         { val = args.hybrid,    class = "tnb tnb-hyb",    class2 = "tns tns-hyb",    txt = "hibrid név"}
     }
     }


     local output = '== Tudományos név ==\n'
     local output = '== Kultivárnév (fajta-, hibridnév) ==\n'
     output = output .. '<div class="tn">\n'
     output = output .. '<div class="tn">\n'
     for _, n in ipairs(names) do
     for _, n in ipairs(names) do
         if n.val and n.val ~= '' then
         if n.val and n.val ~= '' then
             output = output .. '* <span class="' .. n.class .. '">' .. TaxonBox.format_taxon_full(n.val) .. '</span><br><span class="' .. n.class2 .. '">' .. (n.txt) .. '</span>\n'
            local _, sci_formatted, _ = parse_and_format_cultivar(n.val)
             output = output .. '* <span class="' .. n.class .. '">' .. sci_formatted .. '</span><br><span class="' .. n.class2 .. '">' .. (n.txt) .. '</span>\n'
         end
         end
     end
     end
     output = output .. '</div>\n'
     output = output .. '</div>'
     return output
     return output
end
end
271. sor: 227. sor:
             return {
             return {
                 args = {
                 args = {
                     cultivar    = arg[1] or "Dracaena 'Sammurai'",
                     cultivar    = arg[1] or "×Graptoveria 'Lovely Rose'",
                     synonym    = arg[1] or "Sanseviera 'Sammurai'",
                     parent      = arg[2] or "Sedinae",
                    -- "synhomo",
                     image      = "test.jpg",
                    -- "synhetero",
                     imageTitle  = "Teszt kép"
                     -- image      = "test.jpg",
                     -- imageTitle  = "Teszt kép"
                 }
                 }
             }
             }
292. sor: 246. sor:


-- ==========================================================
-- ==========================================================
-- ONLINE HASZNÁLAT
-- ONLINE
-- ==========================================================
-- ==========================================================
-- {{Cultivarbox
-- {{Cultivarbox
-- | accepted = Astrophytum coahuilense
-- | cultivar  = ×Graptoveria 'Lovely Rose'
-- | synonym = Astrophytum myriostigma var. coahuilense
-- | synonym   = Graptopetalum 'Lovely Rose'
-- | synhomo v. synhetero
-- | parent    = Sedinae
-- | image = test.jpg
-- | image     = test_image.jpg
-- | imageTitle = "Teszt kép"
-- | imageTitle = ×Graptoveria 'Lovely Rose'
-- }}
-- }}


return p
return p

A lap jelenlegi, 2026. szeptember 13., 19:29-kori változata

A modult a Modul:Cultivarbox/doc lapon tudod dokumentálni

-- =======================================================================================
-- TaxonokRawData.lua > TaxonokRawDataConvert.lua > Taxonbox2.lua > buildCultivarbox.lua
-- =======================================================================================

local p = {}

-- Betölti a központi taxonbox modult és a nyers adatokat
local TaxonBox = require('Modul:Taxonbox2')
local TaxonData = require('Modul:TaxonokData')

----------------------------------------------------------------------------------------------------------------
-- Segédfüggvény: Kultivárnév pontos MediaWiki aposztróf-formázása
local function parse_and_format_cultivar(full_name)
    if not full_name or full_name == "" then return "", "", "" end

    -- Megtisztítjuk az esetleges korábbi wiki tagektől
    local clean = full_name:gsub("'''''", ""):gsub("''''", ""):gsub("'''", ""):gsub("''", ""):match("^%s*(.-)%s*$")

    -- Különválasztjuk a nemzetséget (akár hibridjellel) a kultivár résztől
    local genus, cv_part = clean:match("^(.-)%s+(['\"].+['\"])$")

    if not genus or not cv_part then
        local formatted_plain = "'''" .. clean .. "'''"
        return formatted_plain, formatted_plain, clean
    end

    -- Kicseréljük a cv_part záró aposztrófját &#39;-re, hogy a MediaWiki parser ne nyelje el a 4x ' találkozásánál
    local cv_inner = cv_part:sub(1, -2) .. "&#39;"

    -- 1. Infobox fejléc & Besorolás sor: '''''Genus'' 'Cultivar&#39;''' (a genus tartalmazza a × jelet is)
    local header_formatted = "'''''" .. genus .. "'' " .. cv_inner .. "'''"

    -- 2. Tudományos név szakasz: '''''Genus'' 'Cultivar'''
    local scientific_formatted = "'''''" .. genus .. "'' " .. cv_part .. "'''"

    -- 3. Tiszta név
    local plain_name = genus .. " " .. cv_part

    return header_formatted, scientific_formatted, plain_name
end

----------------------------------------------------------------------------------------------------------------
function p.buildCultivarbox(frame)
    local args = frame:getParent().args

    local cultivarName   = (args.cultivar   ~= '' and args.cultivar) or nil
    local synonymName    = (args.synonym    ~= '' and args.synonym) or nil
    local hybridName     = (args.hybrid     ~= '' and args.hybrid) or nil
    local parentName     = (args.parent     ~= '' and args.parent) or nil
    local taxonImage     = args.image or ''
    local imageTitle     = args.imageTitle or ''

    local output = ""

    -- cultivarName ----------------------------------
    if cultivarName then
        local hierarchy = {}
        local taxonName = cultivarName
        local overrideParent = parentName

        while taxonName and taxonName ~= "" and taxonName ~= "nil" do
            local _, lookupName = TaxonBox.format_taxon_clean(taxonName)
            local data = TaxonData[lookupName] or TaxonData[taxonName]

            if data then
                table.insert(hierarchy, { rank = data.rank, name = lookupName })
                taxonName = data.parent
                overrideParent = nil
            else
                -- Ha a taxon nincs az adatbázisban (összetett név, pl. kultivár)
                local genus_part, rest_part = taxonName:match("^([%a%-%×%s%.]+)%s+(.+)$")

                if genus_part and rest_part then
                    local current_rank = rest_part:match("^['\"].+['\"]") and "Kultivár" or "Faj"
                    table.insert(hierarchy, { rank = current_rank, name = taxonName })

                    -- Megnézzük, hogy maga a nemzetség / hibridnemzetség benne van-e a TaxonData-ban
                    local _, genusLookup = TaxonBox.format_taxon_clean(genus_part)
                    local genusData = TaxonData[genusLookup] or TaxonData[genus_part]

                    if genusData then
                        taxonName = genusLookup
                    else
                        -- Ha a nemzetség sincs a TaxonData-ban, manuálisan beszúrjuk a Nothogenus / Nemzetség sort
                        local genus_rank = (genus_part:sub(1, 2) == "×" or genus_part:sub(1, 1) == "x") and "Nothogenus" or "Nemzetség"
                        table.insert(hierarchy, { rank = genus_rank, name = genus_part })

                        if overrideParent and overrideParent ~= '' then
                            taxonName = overrideParent
                            overrideParent = nil
                        else
                            break
                        end
                    end
                else
                    -- Egytagú név, ami hiányzik a TaxonData-ból
                    if overrideParent and overrideParent ~= '' then
                        taxonName = overrideParent
                        overrideParent = nil
                    else
                        break
                    end
                end
            end
        end

        if #hierarchy == 0 then
            return '<div style="color:red;">Cultivarbox hiba: Nem található adat a "' .. tostring(cultivarName) .. '" taxonhoz.</div>'
        end

        local header_cv, _, plain_cv = parse_and_format_cultivar(cultivarName)

        output = output .. '{| class="infobox biota cv"\n'
        output = output .. "|-\n"
        output = output .. '! class="taxonnev" colspan="2" | ' .. header_cv .. "\n"

        output = output .. "|-\n"
        output = output .. '! class="suha-svg" colspan="2"|[[Fájl:cv2.png|x160px|link=]]<br>Kultivár, termesztett változat.\n'

        if taxonImage ~= '' then
            output = output .. '|-\n'
            output = output .. '! class="suha-svg" colspan="2"|[[Fájl:' .. taxonImage .. '|340px|' .. imageTitle .. ']]\n'
        end

        output = output .. '|-\n'
        output = output .. '! class="besorolas" colspan="2"|Rendszertani besorolás\n'

        for i = #hierarchy, 1, -1 do
            local item = hierarchy[i]
            local rank_display = item.rank or "Taxon"
            local name_display = ""

            if item.rank == "Kultivár" then
                local cv_header = parse_and_format_cultivar(item.name)
                name_display = cv_header
            elseif item.rank == "Faj" then
                local clean_formatted, clean_plain = TaxonBox.format_taxon_clean(item.name)
                name_display = "[[" .. clean_plain .. "|" .. clean_formatted .. "]]"
            elseif item.rank == "Nemzetség" then
                local _, clean_plain = TaxonBox.format_taxon_clean(item.name)
                name_display = "[[:Kategória:" .. clean_plain .. "|''" .. clean_plain .. "'']]"
            elseif item.rank == "Nothogenus" or item.rank == "Hibridnemzetség" then
                rank_display = "Hibridnemzetség"
                local _, clean_plain = TaxonBox.format_taxon_clean(item.name)
                name_display = "[[:Kategória:" .. clean_plain .. "|''" .. clean_plain .. "'']]"
            else
                local _, clean_plain = TaxonBox.format_taxon_clean(item.name)
                name_display = "[[:Kategória:" .. clean_plain .. "|" .. clean_plain .. "]]"
            end

            if rank_display == "Nemzetségcsoport" then rank_display = "Nemzetség-<br>csoport" end
            if rank_display == "Alnemzetség-csoport" or rank_display == "Alnemzetségcsoport" then
                rank_display = "Alnemzetség-<br>csoport"
            end

            output = output .. '|-\n'
            output = output .. '| class = "left" | ' .. rank_display .. '\n'
            output = output .. '| class = "right" | ' .. name_display .. '\n'
        end

        if hierarchy[1] and (hierarchy[1].rank == "Faj" or hierarchy[1].rank == "Kultivár") then
            local encodedTerm = mw.uri.encode(plain_cv)
            output = output .. '|-\n'
            output = output .. '!colspan="2" class="taxobox-icons" |'
            output = output .. '[[Fájl:Google logo gyz.svg|x30px|link=http://images.google.com/search?tbm=isch&q=' .. encodedTerm .. '|Google képek]] '
            output = output .. '[[Fájl:Bing fluent logo gyz.svg|x30px|link=https://www.bing.com/images/search?q=' .. encodedTerm .. '|Bing képek]]\n'
        end

        output = output .. '|}\n'
    end

    -- synonymName ----------------------------------
    if synonymName then
        local syn_hierarchy = {}
        table.insert(syn_hierarchy, { rank = "Kultivár", name = synonymName })

        local header_syn, _, _ = parse_and_format_cultivar(synonymName)

        output = output .. '{| class="infobox biota syn"\n'
        output = output .. "|-\n"
        output = output .. '! class="taxonnev" colspan="2" | ' .. header_syn .. "\n"
        output = output .. "|-\n"
        output = output .. '! class="suha-svg" colspan="2"|[[Fájl:syn.svg|x160px|link=]]<br>Szinonima név\n'

        for i = #syn_hierarchy, 1, -1 do
            local item = syn_hierarchy[i]
            local syn_disp = parse_and_format_cultivar(item.name)
            output = output .. '|-\n'
            output = output .. '| class = "left" | Szinonim kultivárnév\n'
            output = output .. '| class = "right" | ' .. syn_disp .. '\n'
        end

        output = output .. '|}\n'
    end

    return output
end

----------------------------------------------------------------------------------------------------------------
function p.format_tudomanyos_nev(frame)
    local args = frame:getParent().args
    local names = {
        { val = args.cultivar,   class = "tnb tnb-cv",      class2 = "tns tns-cv",      txt = "kultivár"},
        { val = args.synonym,    class = "tnb tnb-syn",     class2 = "tns tns-syn",     txt = "szinonima név"},
        { val = args.hybrid,     class = "tnb tnb-hyb",     class2 = "tns tns-hyb",     txt = "hibrid név"}
    }

    local output = '== Kultivárnév (fajta-, hibridnév) ==\n'
    output = output .. '<div class="tn">\n'
    for _, n in ipairs(names) do
        if n.val and n.val ~= '' then
            local _, sci_formatted, _ = parse_and_format_cultivar(n.val)
            output = output .. '* <span class="' .. n.class .. '">' .. sci_formatted .. '</span><br><span class="' .. n.class2 .. '">' .. (n.txt) .. '</span>\n'
        end
    end
    output = output .. '</div>'
    return output
end

-- ==========================================================
-- OFFLINE TESZTELŐ SZAKASZ
-- ==========================================================
if arg then
    mw = { uri = { encode = function(s) return s:gsub(" ", "%%20") end } }
    local mock_frame = {
        getParent = function()
            return {
                args = {
                    cultivar    = arg[1] or "×Graptoveria 'Lovely Rose'",
                    parent      = arg[2] or "Sedinae",
                    image       = "test.jpg",
                    imageTitle  = "Teszt kép"
                }
            }
        end
    }

    print("\n--- Cultivarbox GENERÁLT WIKITEXT ---")
    local success, result = pcall(p.buildCultivarbox, mock_frame)
    print(success and result or "HIBA: " .. result)

    print("\n--- TUDOMÁNYOS NÉV SZAKASZ ---")
    local success2, result2 = pcall(p.format_tudomanyos_nev, mock_frame)
    print(success2 and result2 or "HIBA: " .. result2)
end

-- ==========================================================
-- ONLINE
-- ==========================================================
-- {{Cultivarbox
-- | cultivar   = ×Graptoveria 'Lovely Rose'
-- | synonym    = Graptopetalum 'Lovely Rose'
-- | parent     = Sedinae
-- | image      = test_image.jpg
-- | imageTitle = ×Graptoveria 'Lovely Rose'
-- }}

return p