@@ -24,12 +24,65 @@ namespace adoc {
2424
2525namespace {
2626
27+ std::string
28+ escapeAdoc (
29+ std::string_view str)
30+ {
31+ std::string result;
32+ result.reserve (str.size ());
33+ for (char ch : str)
34+ {
35+ switch (ch)
36+ {
37+ case ' &' :
38+ result.append (" &" );
39+ break ;
40+ case ' <' :
41+ result.append (" <" );
42+ break ;
43+ case ' >' :
44+ result.append (" >" );
45+ break ;
46+ case ' [' :
47+ result.append (" [" );
48+ break ;
49+ case ' ]' :
50+ result.append (" ]" );
51+ break ;
52+ case ' |' :
53+ result.append (" |" );
54+ break ;
55+ case ' =' :
56+ result.append (" =" );
57+ break ;
58+ case ' /' :
59+ result.append (" /" );
60+ break ;
61+ default :
62+ result.push_back (ch);
63+ break ;
64+ }
65+ }
66+ return result;
67+ }
68+
2769class DocVisitor
2870{
2971 const AdocCorpus& corpus_;
3072 std::string& dest_;
3173 std::back_insert_iterator<std::string> ins_;
3274
75+ template <typename Fn>
76+ bool
77+ write (
78+ const doc::Node& node,
79+ Fn&& fn)
80+ {
81+ const auto n_before = dest_.size ();
82+ doc::visit (node, std::forward<Fn>(fn));
83+ return dest_.size () != n_before;
84+ }
85+
3386public:
3487 DocVisitor (
3588 const AdocCorpus& corpus,
@@ -126,7 +179,7 @@ DocVisitor::
126179operator ()(
127180 doc::Heading const & I)
128181{
129- fmt::format_to (ins_, " \n === {}\n " , I.string );
182+ fmt::format_to (ins_, " \n === {}\n " , escapeAdoc ( I.string ) );
130183}
131184
132185// Also handles doc::Brief
@@ -135,22 +188,18 @@ DocVisitor::
135188operator ()(
136189 doc::Paragraph const & I)
137190{
138- for (auto const & it : RangeFor (I.children ))
191+ std::span children = I.children ;
192+ if (children.empty ())
193+ return ;
194+ dest_.append (" \n " );
195+ bool non_empty = write (*children.front (), *this );
196+ for (auto const & child : children.subspan (1 ))
139197 {
140- auto const n = dest_.size ();
141- doc::visit (*it.value , *this );
142- // detect empty text blocks
143- if (! it.last && dest_.size () > n)
144- {
145- // wrap past 80 cols
146- if (dest_.size () < 80 )
147- dest_.push_back (' ' );
148- else
149- dest_.append (" \n " );
150- }
198+ if (non_empty)
199+ dest_.push_back (' ' );
200+ non_empty = write (*child, *this );
151201 }
152202 dest_.push_back (' \n ' );
153- // dest_.push_back('\n');
154203}
155204
156205void
@@ -161,7 +210,7 @@ operator()(
161210 dest_.append (" link:" );
162211 dest_.append (I.href );
163212 dest_.push_back (' [' );
164- dest_.append (I.string );
213+ dest_.append (escapeAdoc ( I.string ) );
165214 dest_.push_back (' ]' );
166215}
167216
@@ -170,20 +219,16 @@ DocVisitor::
170219operator ()(
171220 doc::ListItem const & I)
172221{
222+ std::span children = I.children ;
223+ if (children.empty ())
224+ return ;
173225 dest_.append (" \n * " );
174- for (auto const & it : RangeFor (I.children ))
226+ bool non_empty = write (*children.front (), *this );
227+ for (auto const & child : children.subspan (1 ))
175228 {
176- auto const n = dest_.size ();
177- doc::visit (*it.value , *this );
178- // detect empty text blocks
179- if (! it.last && dest_.size () > n)
180- {
181- // wrap past 80 cols
182- if (dest_.size () < 80 )
183- dest_.push_back (' ' );
184- else
185- dest_.append (" \n " );
186- }
229+ if (non_empty)
230+ dest_.push_back (' ' );
231+ non_empty = write (*child, *this );
187232 }
188233 dest_.push_back (' \n ' );
189234}
@@ -220,7 +265,7 @@ operator()(doc::Text const& I)
220265 // Asciidoc text must not have leading
221266 // else they can be rendered up as code.
222267 std::string_view s = trim (I.string );
223- fmt::format_to ( std::back_inserter (dest_), " pass:v,q[{}] " , s );
268+ dest_. append ( escapeAdoc (s) );
224269}
225270
226271void
@@ -253,11 +298,10 @@ void
253298DocVisitor::
254299operator ()(doc::Reference const & I)
255300{
256- // dest_ += I.string;
257301 if (I.id == SymbolID::invalid)
258302 return (*this )(static_cast <const doc::Text&>(I));
259303 fmt::format_to (std::back_inserter (dest_), " xref:{}[{}]" ,
260- corpus_.getXref (corpus_->get (I.id )), I.string );
304+ corpus_.getXref (corpus_->get (I.id )), escapeAdoc ( I.string ) );
261305}
262306
263307std::size_t
0 commit comments