if not modules then modules = { } end modules ['font-san'] = {
    version   = 1.001,
    comment   = "companion to font-ini.mkiv",
    author    = "Hans Hagen, PRAGMA ADE & śrīrāma",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files"
}

--     \definefontfeature[demo][sanitizer=demo]
--     \definedfont[Serif*default,demo] test context test
--     \definedfont[Serif*default]      test context test

local keys, insert, copytable = table.keys, table.insert, table.copy
local utfvalues, utfbyte = utf.values, utf.byte

local sanitizers = { }

local trace  = false
local report = logs.reporter("fonts", "sanitizers")

trackers.register("fonts.sanitizers", function(v) trace = v end)

function fonts.registersanitizer(name,vector)
    sanitizers[name] = vector
end

local function split(s)
    local t = { }
    for value in utfvalues(s) do
        t[#t+1] = value
    end
    return t
end

local function wrap(t)
    for i=1,#t do
        t[i] = { t[i] }
    end
    return t
end

local function initializesanitizer(tfmdata,value)
    local resources = tfmdata.resources
    local sanitized = resources.sanitized
    if not sanitized then
        local sanitizer = false
        local goodies   = tfmdata.goodies
        if goodies then
            for i=1,#goodies do
                local goodie = goodies[i]
                local sanitizers = goodie.sanitizers
                sanitizer = sanitizers and sanitizers[value]
                if sanitizer then
                    report("using sanitizer %a from goodie file",value)
                    break
                end
            end
        end
        if not sanitizer then
            sanitizer = sanitizers[value]
            if sanitizer then
                report("using sanitizer %a",value)
            end
        end
        resources.sanitized = true
        if sanitizer then
            local mapping = sanitizer.mapping
            if mapping then
                local keys = keys(mapping)
                local maps = { }
                table.sort(keys, function(a,b) return a > b end)
                for i = 1,#keys do
                    local k = keys[i]
                    keys[i] = split(k)
                    maps[i] = split(mapping[k])
                end
                for i=1,#maps do
                    local k = keys[i]
                    local m = maps[i]
                    if trace then
                     -- m = copytable(m)
                     -- insert(m,1,utfbyte("["))
                     -- insert(m,  utfbyte("]"))
                        local t = { utfbyte("[") }
                        t[#t+1] = 0x200D -- zwnj
                        for i=1,#m do
                            t[#t+1] = m[i]
                            t[#t+1] = 0x200D -- zwnj
                        end
                        t[#t+1] = utfbyte("]")
                    end
                    maps[i] = { type = "multiple", data = { [k[1]] = m } }
                    keys[i] = { current = wrap(k) , lookups = { i } }
                end
                local specification = {
                    name    = "sanitizer",
                    type    = "chainsubstitution",
                    prepend = 1,
                    nocheck = true,
                    default = true,
                    lookups = maps,
                    data    = { rules = keys },
                }
                local s = fonts.handlers.otf.enhancers.addfeature(
                    tfmdata,"sanitizer",specification, true
                )
                insert(resources.sequences,1,s)
            end
        end
    end
end

-- has to come *after* devanagari because we need to push it in front
-- ... it could be a built-in

fonts.constructors.features.otf.register {
    name         = "sanitizer",
    description  = "inject sanitizer features",
    initializers = {
        node = initializesanitizer,
    },
}

local dev2rkrf = {
    ["के्र"] = "क्रे",
    ["कै्र"] = "क्रै",
    ["खे्र"] = "ख्रे",
    ["खै्र"] = "ख्रै",
    ["गे्र"] = "ग्रे",
    ["गै्र"] = "ग्रै",
    ["घे्र"] = "घ्रे",
    ["घै्र"] = "घ्रै",
 -- not required: placed here just to show how bad some fonts are :(
 -- ["ङे्र"] = "ङ्रे",
 -- ["ङै्र"] = "ङ्रै",
    ["चे्र"] = "च्रे",
    ["चै्र"] = "च्रै",
    ["छे्र"] = "छ्रे",
    ["छै्र"] = "छ्रै",
    ["जे्र"] = "ज्रे",
    ["जै्र"] = "ज्रै",
    ["झे्र"] = "झ्रे",
    ["झै्र"] = "झ्रै",
    ["ञे्र"] = "ञ्रे",
    ["ञै्र"] = "ञ्रै",
    ["णे्र"] = "ण्रे",
    ["णै्र"] = "ण्रै",
    ["ते्र"] = "त्रे",
    ["तै्र"] = "त्रै",
    ["थे्र"] = "थ्रे",
    ["थै्र"] = "थ्रै",
    ["दे्र"] = "द्रे",
    ["दै्र"] = "द्रै",
    ["धे्र"] = "ध्रे",
    ["धै्र"] = "ध्रै",
    ["ने्र"] = "न्रे",
    ["नै्र"] = "न्रै",
    ["पे्र"] = "प्रे",
    ["पै्र"] = "प्रै",
    ["फे्र"] = "फ्रे",
    ["फै्र"] = "फ्रै",
    ["बे्र"] = "ब्रे",
    ["बै्र"] = "ब्रै",
    ["भे्र"] = "भ्रे",
    ["भै्र"] = "भ्रै",
    ["मे्र"] = "म्रे",
    ["मै्र"] = "म्रै",
    ["ये्र"] = "य्रे",
    ["यै्र"] = "य्रै",
 -- some fonts might need this, some might not: weird
 -- for example: Shobhika does not need it but Noto Serif does :(
 -- ["ले्र"] = "ल्रे",
 -- ["लै्र"] = "ल्रै",
    ["वे्र"] = "व्रे",
    ["वै्र"] = "व्रै",
    ["से्र"] = "स्रे",
    ["सै्र"] = "स्रै",
    ["शे्र"] = "श्रे",
    ["शै्र"] = "श्रै",
    ["षे्र"] = "ष्रे",
    ["षै्र"] = "ष्रै",
    ["हे्र"] = "ह्रे",
    ["है्र"] = "ह्रै",
 -- some fonts might need this, some might not: weird
 -- ["ळे्र"] = "ळ्रे",
 -- ["ळै्र"] = "ळ्रै",
}

local demomapping = {
    luatex   = "LuaTeX",
    metapost = "MetaPost",
    context  = "ConTeXt",
    metafun  = "MetaFun",
}

fonts.registersanitizer("dev2rkrf", { mapping = dev2rkrf })
fonts.registersanitizer("demo",     { mapping = demomapping })
