if not modules then modules = { } end modules ['typo-wrp'] = {
    version   = 1.001,
    comment   = "companion to typo-wrp.mkiv",
    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files"
}

-- begin/end par wrapping stuff ... more to come

local boundary_code     <const> = nodes.nodecodes.boundary
local glyph_code        <const> = nodes.nodecodes.glyph
local wordboundary_code <const> = nodes.boundarycodes.word
local userboundary_code <const> = nodes.boundarycodes.user

local nuts              = nodes.nuts

local findtail          = nuts.tail
local getprev           = nuts.getprev
local setnext           = nuts.setnext
local getdata           = nuts.getdata
local isglyph           = nuts.isglyph
local hasidsubtype      = nuts.hasidsubtype
local getattr           = nuts.getattr
local flushnodelist     = nuts.flushlist
local traverse_boundary = nuts.traversers.boundary
local insertnodebefore  = nuts.insertbefore
local newkern           = nuts.pool.kern

local fontdata          = fonts.hashes.identifiers

local enableaction      = nodes.tasks.enableaction

local implement         = interfaces.implement

local wrappers          = { }
typesetters.wrappers    = wrappers

local trace_wrappers      trackers.register("typesetters.wrappers",function(v) trace_wrappers = v end)
local report            = logs.reporter("paragraphs","wrappers")

-- In luametatex we don't have the parfilskip attached yet but we can have final glue
-- anyway. This check is very bound to the \crlf definition where we get:
--
-- ... boundary [strut: hlist] [break: glue penalty] boundary

local a_crlf <const> = attributes.private("crlf")

local function remove_dangling_crlf(head,tail)
    if head and tail then
        if hasidsubtype(tail,boundary_code,wordboundary_code) then
            -- findnode could run backwards
            if getattr(tail,a_crlf) then
                local t = tail
                while t do
                    t = getprev(t)
                    if not t then
                        break
                    elseif hasidsubtype(t,boundary_code,wordboundary_code) then
                        if t ~= head then
                            if trace_wrappers then
                                report("removing a probably unwanted end-of-par break in line %s (guess)",tex.inputlineno)
                            end
                            tail = getprev(t)
                            setnext(tail)
                            flushnodelist(t)
                        end
                        break
                    end
                end
            end
        end
    end
    return head, tail
end

implement {
    name     = "enablecrlf",
    onlyonce = true,
    actions  = function()
        enableaction("processors","typesetters.wrappers.handler")
    end
}

-- Here's a solution for a trivial challenge by MS who got it from the internet
-- (SE). If needed we can make it a bit more granular.

local tighten       = { }
typesetters.tighten = tighten

local trace_tighten   trackers.register("typesetters.tighten",function(v) trace_tighten = v end)
local report        = logs.reporter("typesetters","tighten")

local a_tightfit_boundary <const> = tex.boundaries.system("c_tightfit_boundary") -- private, not defined with \defineboundary

local function bbcompensation(font,char)
    local tfmdata   = fontdata[font]
    local character = tfmdata.characters[char]
    if character then
        local compensation = character.compensation
        if not compensation then
            local description = tfmdata.descriptions[char]
            if description then
                local boundingbox  = description.boundingbox
                return boundingbox and (boundingbox[3] - (description.width or 0)) * tfmdata.parameters.hfactor
            end
            character.compensation = compensation
        end
    end
    return 0
end

function tighten.handler(head)
    for n, subtype in traverse_boundary, head do
        if subtype == userboundary_code and getdata(n) == a_tightfit_boundary then
            local prev = getprev(n)
            if prev then
                local char, font = isglyph(prev)
                if char then
                    local compensation = bbcompensation(font,char)
                    if compensation > 0 then
                        if trace_tighten then
                            report("compensating %p after %C",compensation,char)
                        end
                        insertnodebefore(head,n,newkern(compensation))
                    end
                end
            end
        end
    end
    return head
end

implement {
    name     = "enabletighten",
    onlyonce = true,
    actions  = function()
        enableaction("processors","typesetters.tighten.handler")
    end
}

local dimension_value <const> = tokens.values.dimension
local texgetnest      = tex.getnest

implement {
    name      = "tightfitcompensation",
    public    = true,
    protected = true,
    usage     = "value",
    actions   = function()
        local list = texgetnest()
        if list then
            list = list.tail
        end
        return
            dimension_value,
            list and list.id == glyph_code and bbcompensation(list.font,list.char) or 0
    end,
}
