Background
Looking to perform a text substitution on arbitrary strings. In the code snippet, the value #a.m. #p.m. value comes from a document. More specifically, the input is an XML document generated from Markdown. The XML document resembles:
<p>See <a class="href" data-type="tbl" href="#ref"/> for details.</p>
The #ref is proving to be problematic.
System
ConTeXt version: 2023.09.26 18:19
Code
Minimal example to show the problem:
\startluacode
userdata = userdata or {}
userdata.TextReplacements = {}
local function TextReplacement( text )
text = string.gsub( text, "#", "\#" )
local replaced = lpeg.replacer( userdata.TextReplacements ):match( text )
context( replaced )
end
interfaces.implement {
name = "TextReplacement",
arguments = { "string" },
public = true,
actions = TextReplacement,
}
\stopluacode
\startluacode
userdata = userdata or {}
userdata.TextReplacements = {
[1] = { "a.m.", "\cap{am}" },
[2] = { "p.m.", "\cap{pm}" },
}
\stopluacode
\starttext
\TextReplacement{#a.m. #p.m.}
\stoptext
Details
An additional detail is that the #ref value is being read into ConTeXt from the anchor's link and looked up as follows:
\startxmlsetups xml:xhtml
\xmlsetsetup{\xmldocument}{a[@class='href']}{xml:anchorhref}
\stopxmlsetups
\startxmlsetups xml:anchorhref
Xref = \xmlatt{#1}{data-type}-\xmlatt{#1}{href}
\stopxmlsetups
The anchorhref is executed from inside an xml:p setup, shown here:
\startxmlsetups xml:p
\xmldoifnotselfempty{#1}{%
\ignorespaces
\expandafter\TextReplacement{\xmlflush{#1}}
\removeunwantedspaces
}
\par
\stopxmlsetups
That call to \TextReplacement doesn't work because of the # symbol.
Problem
The wiki suggests using lpeg.replacer( ... ):match( ... ), but that produces a compile error.
By adding a call to string.gsub, the compile error goes away, but the output produces double hash symbols:
##AM ##PM
Question
How do you escape the hash symbol and any others that may cause a failure with the string replacement such that no double-hashes are output?

