2

I am trying to figure out how to move some context commands inside a Lua environment. (I am trying to create a document where most of the content is created dynamically from data pulled from an external source)

I have created this very simple MWE in normal context that works as expected

\defineexternalfigure
    [svgframe][method=svg, conversion=mp, width=10cm, height=10cm]
\defineoverlay
    [boxframe][{\externalfigure[frame.svg][svgframe][width=10cm,height=10cm]}]
    
\defineframed
    [CARDFRAME][height=10cm, width=10cm, frame=off, align=inner, background=boxframe]
\starttext
\CARDFRAME{\blank\blank Hello World!}
\stoptext

I'm using an arbitrary CC0 svg frame for the MWE from here

In attempting to convert the ordinary conText code. I created this:


\startluacode

context.defineexternalfigure({ "svgframe" }, {method = "svg", conversion = "mp", width = "10cm" , height = "10cm" })
context.defineoverlay({ "boxframe" }, context.externalfigure( { "frame.svg" }, { "svgframe" } ) )
context.defineframed({ "CARDFRAME" }, {height = "10cm", width = "10cm", frame = "off", align = "inner", background = boxframe})
context.starttext()

context.CARDFRAME( context("Hello World") )

context.stoptext()
\stopluacode

There are at least two problems with this code that I can't figure out.

  1. as it is written, I get the error: tex error > tex error on line 1 in file : You can't use '\end' in internal vertical mode during compilation
  2. If I remove the context.CARDFRAME( and the matching closing bracket, then the compilation is successful, but the image seems to be typeset at the time of the defineoverlay.

on page 29 of ConTEXt Lua Documents a situation is discussed that I think is similar, and adapting the solution given there, I think I would write the defineoverlay command as:

context.defineoverlay({ "boxframe" }, function() context.externalfigure( { "frame.svg" }, { "svgframe" } ) end )

but even when I do that, the image still seems to be typeset at the time of the defineoverlay command.

Is anyone able to point me in the right direction in solving these issues?

Thanks

1
  • Welcome to TeX.SE!
    – Mensch
    Nov 8, 2023 at 16:35

1 Answer 1

2
  1. As it is written, I get the error:
    tex error > tex error on line 1 in file : You can't use '\end' in internal vertical mode
    
    during compilation

context.stoptext() ends the entire compilation run, but at that point the luacode environment is still open, so this won't work.

One option is to place the \starttext/\stoptext around the \startluacode/\stopluacode:

% test.tex
\starttext
\startluacode
    context("Hello World")
\stopluacode
\stoptext

but a better option is to place the contents of \startluacode/\stopluacode into a .cld file, which ConTeXt will process as Lua directly:

-- test.tex
context.starttext()
context("Hello World")
context.stoptext()
  1. If I remove the context.CARDFRAME( and the matching closing bracket, then the compilation is successful, but the image seems to be typeset at the time of the \defineoverlay.

    On page 29 of ConTEXt Lua Documents a situation is discussed that I think is similar, and adapting the solution given there, I think I would write the defineoverlay command as:

    context.defineoverlay({ "boxframe" }, function() context.externalfigure( { "frame.svg" }, { "svgframe" } ) end )
    

    but even when I do that, the image still seems to be typeset at the time of the defineoverlay command.

You're writing context.defineoverlay({"first"}, "second"), which is serialized as \defineoverlay[first]{second}, which ConTeXt ultimately processes as \defineoverlay[first] (a command with one argument) followed by second (the raw text).

To make this work, you need to wrap the function in {braces}:

context.defineexternalfigure(
    { "svgframe" },
    {
        method = "svg",
        conversion = "mp",
        width =
        "10cm",
        height = "10cm",
    }
)

context.defineoverlay(
    { "boxframe" },
    { -- Braces needed here since it's `\defineoverlay[...][...]`, not `\defineoverlay[...]{...}`.
        function ()  -- Wrap with a function here as you suggested
            context.externalfigure({ "frame.svg" }, { "svgframe" })
            return true  -- We need to return `true` here for weird caching reasons that only apply to this specific macro (and a few other rare cases that you probably won't run into).
        end
    }
)

context.defineframed(
    { "CARDFRAME" },
    {
        height = "10cm",
        width = "10cm",
        frame = "off",
        align = "inner",
        background = "boxframe", -- Quotes needed here since `boxframe` refers to the Lua variable which is undefined and therefore `nil`.
    }
)
context.startTEXpage()
context.CARDFRAME(function() -- Use a function so we can add the `\blank`s from the original example.
    context.blank()
    context.blank()
    context("Hello World")
end)
context.stopTEXpage()

sample output

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .