3

Background

Markdown, having been converted to XHTML, is to have certain words stylized using ConTeXt. Consider:

1. Say, "ConTeXt is good."
1. Tap [Space]{.kbd} to continue (or quit with [Q]{.kbd}).

This is converted to:

<ol>
<li>Say, "ConTeXt is good."</li>
<li>Tap <span class="kbd">Space</span> to continue (or quit with <span class="kbd">Q</span>).</li>
</ol>

Problem

Space invaders have gobbled up spaces after the first kbd span:

space invaders

Code

\startbuffer[test]
<?xml version="1.0"?>
<document>
<ol>
<li>Say, "ConTeXt is good."</li>
<li>Tap <span class="kbd">Space</span> to continue (or quit with <span class="kbd">Q</span>).</li>
</ol>
</document>
\stopbuffer

\startxmlsetups xml:setup
  \xmlsetsetup{\xmldocument}{*}{-}
  \xmlsetsetup{\xmldocument}{document}{xml:*}
  \xmlsetsetup{\xmldocument}{ol|li|span}{xml:*}
\stopxmlsetups

\startxmlsetups xml:document
  \startdocument \expandafter{\TextReplacement{\xmlflush{#1}}} \stopdocument
\stopxmlsetups

\startxmlsetups xml:ol
  \startOrderedList \xmlflush{#1} \stopOrderedList
\stopxmlsetups

\startxmlsetups xml:li
  \startitem \xmlflush{#1} \stopitem
\stopxmlsetups

\startxmlsetups xml:span
  \setvariable{span}{\xmlatt{#1}{class}}{#1}
  \start[\xmlatt{#1}{class}]{\xmlflush{#1}}\stop
\stopxmlsetups

\xmlregistersetup{xml:setup}

\defineitemgroup[OrderedList]
\setupitemgroup[OrderedList][1][packed, ListConversion1]

\definestartstop[kbd][
  before={\inframed[]\bgroup},
  after={\egroup},
]

\startluacode
userdata = userdata or {}

userdata.TextReplacements = {}

local function TextReplacement( text )
  -- Escape hash symbols to avoid compile errors when using cross-references.
  local s = string.gsub( text, "#", "#H" )
  context( lpeg.replacer( userdata.TextReplacements ):match( s ) )
end

interfaces.implement {
  name      = "TextReplacement",
  arguments = { "string" },
  public    = true,
  actions   = TextReplacement,
}
\stopluacode

\startluacode
userdata = userdata or {}

userdata.TextReplacements = {
  [1] = { "TeX", "\\TeX{}" },
}
\stopluacode

\starttext
  \xmlprocessbuffer{main}{test}{}
\stoptext

Question

How would you ensure that the space (after Space) isn't gobbled?

Ideas

I've tried a few approaches, including shifting the \TextReplacement call into the span (but that's not good because it means having to call \TextReplacement on every XHTML element containing text) and using \autoinsertnextspace. I could not get it to work, either.

3
  • 2
    Does it help if you add empty braces after \stop in your xml:span setup? I think Hans will look into this, because he is, as far as I understand, not so fond of empty braces solutions. Commented Aug 31 at 12:23
  • 1
    You can try \autoinsertedspace after the \stop command, which gives better results than \autoinsertnextspace. Commented Aug 31 at 12:32
  • Yes, @mickep, the braces fixes the issue. Thank you. Commented Aug 31 at 18:37

1 Answer 1

2

We can reduce your example to the following:

\startbuffer[test]
    <?xml version="1.0"?>
    <document>
        Please tap <kbd>Space</kbd> to continue.
    </document>
\stopbuffer

\startxmlsetups xml:document
    \startTEXpage[offset=1ex, align=middle]
        \TextReplacement{\xmlflush{#1}}
    \stopTEXpage
\stopxmlsetups

\startxmlsetups xml:kbd
    \start[framed][location=low]
        \xmlflush{#1}
    \stop
\stopxmlsetups

\startxmlsetups xml:setup
    \xmlsetsetup{\xmldocument}{document|kbd}{xml:*}
\stopxmlsetups

\xmlregistersetup{xml:setup}

\startluacode
    interfaces.implement {
        name      = "TextReplacement",
        arguments = { "string" },
        public    = true,
        actions   = function(s)
            context(s)
            context.par()
            context.type({ style = "ttxx" }, s)
        end,
    }
\stopluacode

\starttext
    \xmlprocessbuffer{main}{test}{}
\stoptext

output

If we copy-and-paste the verbatim text into a new document, we get the exact same problem:

\startTEXpage[offset=1ex]
    Please tap \start[framed][location=low]Space\stop to continue.
\stopTEXpage

output

The easiest solution is to add a pair of braces after \stop

\startbuffer[test]
    <?xml version="1.0"?>
    <document>
        Please tap <kbd>Space</kbd> to continue.
    </document>
\stopbuffer

\startxmlsetups xml:document
    \startTEXpage[offset=1ex, align=middle]
        \TextReplacement{\xmlflush{#1}}
    \stopTEXpage
\stopxmlsetups

\startxmlsetups xml:kbd
    \start[framed][location=low]
        \xmlflush{#1}
    \stop{}
\stopxmlsetups

\startxmlsetups xml:setup
    \xmlsetsetup{\xmldocument}{document|kbd}{xml:*}
\stopxmlsetups

\xmlregistersetup{xml:setup}

\startluacode
    interfaces.implement {
        name      = "TextReplacement",
        arguments = { "string" },
        public    = true,
        actions   = function(s)
            context(s)
            context.par()
            context.type({ style = "ttxx" }, s)
        end,
    }
\stopluacode

\starttext
    \xmlprocessbuffer{main}{test}{}
\stoptext

output

1
  • 1
    I've kept the style separate from the parsing, so I do need the start/stop environment because different themes will style the kbd span differently (and they aren't allowed to know about xml setups). Using the braces solved the issue. Although I suppose it could be a named framed[] environment as well, but that lead to an inconsistency with respect to all the other start/stop setups. Commented Aug 31 at 18:44

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.