@@ -24,12 +24,65 @@ namespace adoc {
24
24
25
25
namespace {
26
26
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
+
27
69
class DocVisitor
28
70
{
29
71
const AdocCorpus& corpus_;
30
72
std::string& dest_;
31
73
std::back_insert_iterator<std::string> ins_;
32
74
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
+
33
86
public:
34
87
DocVisitor (
35
88
const AdocCorpus& corpus,
@@ -126,7 +179,7 @@ DocVisitor::
126
179
operator ()(
127
180
doc::Heading const & I)
128
181
{
129
- fmt::format_to (ins_, " \n === {}\n " , I.string );
182
+ fmt::format_to (ins_, " \n === {}\n " , escapeAdoc ( I.string ) );
130
183
}
131
184
132
185
// Also handles doc::Brief
@@ -135,22 +188,18 @@ DocVisitor::
135
188
operator ()(
136
189
doc::Paragraph const & I)
137
190
{
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 ))
139
197
{
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 );
151
201
}
152
202
dest_.push_back (' \n ' );
153
- // dest_.push_back('\n');
154
203
}
155
204
156
205
void
@@ -161,7 +210,7 @@ operator()(
161
210
dest_.append (" link:" );
162
211
dest_.append (I.href );
163
212
dest_.push_back (' [' );
164
- dest_.append (I.string );
213
+ dest_.append (escapeAdoc ( I.string ) );
165
214
dest_.push_back (' ]' );
166
215
}
167
216
@@ -170,20 +219,16 @@ DocVisitor::
170
219
operator ()(
171
220
doc::ListItem const & I)
172
221
{
222
+ std::span children = I.children ;
223
+ if (children.empty ())
224
+ return ;
173
225
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 ))
175
228
{
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 );
187
232
}
188
233
dest_.push_back (' \n ' );
189
234
}
@@ -220,7 +265,7 @@ operator()(doc::Text const& I)
220
265
// Asciidoc text must not have leading
221
266
// else they can be rendered up as code.
222
267
std::string_view s = trim (I.string );
223
- fmt::format_to ( std::back_inserter (dest_), " pass:v,q[{}] " , s );
268
+ dest_. append ( escapeAdoc (s) );
224
269
}
225
270
226
271
void
@@ -253,11 +298,10 @@ void
253
298
DocVisitor::
254
299
operator ()(doc::Reference const & I)
255
300
{
256
- // dest_ += I.string;
257
301
if (I.id == SymbolID::invalid)
258
302
return (*this )(static_cast <const doc::Text&>(I));
259
303
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 ) );
261
305
}
262
306
263
307
std::size_t
0 commit comments