Strange interaction between fontspec and lua

fontspeclualuacodeluatex

I noticed a strange interaction between the fontspec package and lua code.
I have been using for some time a lua code found on this site that prevents words composed of a single letter ("a", "à" and "y" in French) from being found "alone" at the end of a line.

Surprisingly, if I load a font with fontspec, use this lua code, and one of the chapters starts with one of these one-letter words, the running title in the header is not composed in small caps as it should be.

If I do not load a new font or activate the lua code, the problem does not appear.
The problem only appears in the header, if I type for example simply \textsc{A ...}, there is no problem.

This is very strange, I don't understand what is going on at all. Do you have any idea?

Example: on the left a header with a chapter name beginning with "a" which is not small-capitalized; on the right a normal header:
enter image description here
enter image description here

\documentclass{book}
\usepackage{lipsum, luacode, fontspec}
\setmainfont{LibertinusSerif}

\begin{luacode}
local GLYPH = node.id("glyph")
local GLUE = node.id("glue")
local prevent_single_letter = function (head)
    while head do
        if (head.id == GLYPH) then
            if unicode.utf8.match(unicode.utf8.char(head.char), "[aAàÀyY]") then
                if ((head.prev.id == GLUE
                    or (head.prev.id == GLYPH
                        and unicode.utf8.match(unicode.utf8.char(head.prev.char), "[%[%]()%{%}]")))
                        and head.next.id == GLUE) then
                    local p = node.new("penalty")
                    p.penalty = 10000
                    node.insert_after(head, head, p)
                end
            end
        end
        head = head.next
    end
    return true
end
function single_letter_enable ()
    luatexbase.add_to_callback("pre_shaping_filter", prevent_single_letter, "singleletter")
end
\end{luacode}
\directlua{single_letter_enable()}

\makeatletter
\def\ps@headings{
    \def\@evenhead{{\scshape\rightmark}\hfil}
    \def\chaptermark##1{\markright{##1}}
}
\makeatother
\pagestyle{headings}

\begin{document}
\chapter*{A test}\chaptermark{A test}
\lipsum[1-7]

\chapter*{Test}\chaptermark{Test}
\lipsum[1-7]

\textsc{A test}
\end{document}

Edit

On the proposal of user187802, the lua code has been modified.

\documentclass{book}

\usepackage{lipsum, luacode, fontspec}
\setmainfont{LibertinusSerif}

\begin{luacode}
local GLYPH = node.id("glyph")
local GLUE = node.id("glue")
local prevent_single_letter = function (head)
    while head do
        if (head.id == GLYPH) then
          if head.prev then.    --  !!!!!!!
            if unicode.utf8.match(unicode.utf8.char(head.char), "[aAàÀyY]") then -- and head.prev.id ~= GLUE  then
                if ((head.prev.id == GLUE
                        or (head.prev.id == GLYPH
                            and unicode.utf8.match(unicode.utf8.char(head.prev.char), "[%[%]()%{%}]")))
                            and head.next.id == GLUE) then
                        local p = node.new("penalty")
                        p.penalty = 10000
                        node.insert_after(head, head, p)
                    end
                end
            end
        end
        head = head.next
    end
    return true
end
function single_letter_enable ()
    luatexbase.add_to_callback("pre_shaping_filter", prevent_single_letter, "singleletter")
end
\end{luacode}

\directlua{single_letter_enable()}

\makeatletter
\def\ps@headings{
    \def\@evenhead{{\scshape\rightmark}\hfil}
    \def\chaptermark##1{\markright{##1}}
}
\makeatother
\pagestyle{headings}

\begin{document}
Le titre courant est un rappel du titre de l’ouvrage, du chapitre, parfois abrégé, a % "a" should not be alone at the end of the line, but should be sent to the next line
placé dans la marge supérieure ou inférieure d’une page.

\chapter*{A test}\chaptermark{A test}
\lipsum[1-7]

\chapter*{Test}\chaptermark{Test}
\lipsum[1-7]
\end{document}

However the code does not seem to do what it was created for anymore. For example in the text below, the word "a" should not be alone at the end of the line, it should be pushed to the beginning of the next line.

enter image description here

Best Answer

Check if it is not the first letter:

local prevent_single_letter = function (head)
    while head do
        if (head.id == GLYPH) then
          if head.prev then    --  !!!!!!!
            if unicode.utf8.match(unicode.utf8.char(head.char), "[aAàÀyY]") then 
                if ((head.prev.id == GLUE
[...]
Related Question