After some attempts to build crosswords puzzles with context, I found this approach: 1) Create the puzzle with genxword https://github.com/riverrun/genxword 2) Edit the output table and change all {} to * 3) Save the table in a file (p.e. crosswords.txt) 3) In context use this script (Revised By Wolfgang Schuster) \startluacode context.startmidaligned() context.bTABLE( { rulethickness = ".25pt", width = ".8cm", height = ".8cm", align = "{lohi, middle}" } ) for line in io.lines("crosswords.txt") do for w in (line .. "|"):gmatch("([^|]*)|") do -- print (w) if w == ' ' then context.bTR() elseif w == '.' then context.eTR() else if w == '* ' then context.bTD( { frame = "off" } ) context.eTD() else ww = string.match (w, "%d+") print (ww) if ww then context.bTD( { foregroundstyle = "\\bfxx" } ) context("%s",ww) context.eTD() else context.bTD() -- context("%s",w) context.eTD() end end end end end context.eTABLE() context.stopmidaligned() \stopluacode Files: crossword.txt file: |* |* |[2]T|* |* |* |* |* |* |* |* |* |* |* |* |* |. |[1]A|D|R|I|A|N|O|* |* |* |* |* |* |* |* |* |. |* |* |A|* |* |* |* |* |* |* |* |* |* |* |* |* |. |[6]H|* |J|* |* |* |[4]T|* |* |* |* |* |* |* |* |* |. |[3]I|T|A|L|I|C|A|* |* |* |* |* |* |* |* |* |. |S|* |N|* |* |* |R|* |* |* |* |* |* |* |* |* |. |P|* |O|* |* |* |G|* |[10]S|* |* |[7]P|* |* |* |* |. |A|* |* |* |[5]G|U|A|D|A|L|Q|U|I|[9]V|I|[8]R|. |L|* |* |* |* |* |R|* |N|* |* |B|* |E|* |O|. |I|* |* |* |* |* |Y|* |T|* |* |L|* |N|* |M|. |S|* |* |* |* |* |E|* |I|* |* |I|* |U|* |A|. |* |* |* |* |* |* |N|* |P|* |* |O|* |S|* |N|. |* |* |* |* |* |* |* |* |O|* |* |* |* |* |* |O|. |* |* |* |* |* |* |* |* |N|* |* |* |* |* |* |S|. |* |* |* |* |* |* |* |* |C|* |* |* |* |* |* |* |. |* |* |* |[11]A|N|F|I|T|E|A|T|R|O|* |* |* |. Output