Skip to content

Commit 5bc9f53

Browse files
committed
refactor: no intermediary buffers for wrapper template
1 parent decaf3e commit 5bc9f53

File tree

3 files changed

+113
-53
lines changed

3 files changed

+113
-53
lines changed

src/lib/Gen/hbs/Builder.cpp

+51-31
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,8 @@ Builder(
3535
{
3636
namespace fs = std::filesystem;
3737

38-
Config const& config = domCorpus->config;
39-
4038
// load partials
41-
std::string partialsPath = files::appendPath(
42-
config->addons, "generator", domCorpus.fileExtension, "partials");
39+
std::string partialsPath = templatesDir("partials");
4340
forEachFile(partialsPath, true,
4441
[&](std::string_view pathName) -> Error
4542
{
@@ -60,8 +57,7 @@ Builder(
6057
}).maybeThrow();
6158

6259
// Load JavaScript helpers
63-
std::string helpersPath = files::appendPath(
64-
config->addons, "generator", domCorpus.fileExtension, "helpers");
60+
std::string helpersPath = templatesDir("helpers");
6561
forEachFile(helpersPath, true,
6662
[&](std::string_view pathName)-> Expected<void>
6763
{
@@ -126,11 +122,7 @@ callTemplate(
126122
std::string_view name,
127123
dom::Value const& context)
128124
{
129-
Config const& config = domCorpus->config;
130-
131-
auto layoutDir = files::appendPath(config->addons,
132-
"generator", domCorpus.fileExtension, "layouts");
133-
auto pathName = files::appendPath(layoutDir, name);
125+
auto pathName = files::appendPath(layoutDir(), name);
134126
MRDOCS_TRY(auto fileText, files::getFileText(pathName));
135127
HandlebarsOptions options;
136128
options.noEscape = true;
@@ -244,40 +236,68 @@ operator()(OverloadSet const& OS)
244236

245237
Expected<void>
246238
Builder::
247-
wrapPage(
248-
std::ostream& out,
249-
std::istream& in)
239+
renderWrapped(std::ostream& os, std::function<Error()> contentsCb)
250240
{
251-
auto const wrapperFile = fmt::format("wrapper.{}.hbs", domCorpus.fileExtension);
241+
auto const wrapperFile = fmt::format(
242+
"wrapper.{}.hbs", domCorpus.fileExtension);
252243
dom::Object ctx;
253-
ctx.set("contents", dom::makeInvocable([&in](
254-
dom::Value const& options) -> Expected<dom::Value>
244+
ctx.set("contents", dom::makeInvocable([&](
245+
dom::Value const& options) -> Expected<dom::Value>
255246
{
256-
// Helper to write contents directly to stream
257-
// AFREITAS: custom functions should set options["write"]
258-
// to avoid creating a string.
259-
return std::string(
260-
std::istreambuf_iterator<char>(in),
261-
std::istreambuf_iterator<char>());
247+
Error e = contentsCb();
248+
if (e.failed())
249+
{
250+
return Unexpected(e);
251+
}
252+
return {};
262253
}));
263-
// Render directly to ostream
264-
Config const& config = domCorpus->config;
265-
auto layoutDir = files::appendPath(config->addons,
266-
"generator", domCorpus.fileExtension, "layouts");
267-
auto pathName = files::appendPath(layoutDir, wrapperFile);
254+
255+
// Render the wrapper directly to ostream
256+
auto pathName = files::appendPath(layoutDir(), wrapperFile);
268257
MRDOCS_TRY(auto fileText, files::getFileText(pathName));
269258
HandlebarsOptions options;
270259
options.noEscape = true;
271-
OutputRef outRef(out);
260+
OutputRef outRef(os);
272261
Expected<void, HandlebarsError> exp =
273-
hbs_.try_render_to(outRef, fileText, ctx, options);
262+
hbs_.try_render_to(
263+
outRef, fileText, ctx, options);
274264
if (!exp)
275265
{
276-
return Unexpected(Error(exp.error().what()));
266+
Error(exp.error().what()).Throw();
277267
}
278268
return {};
279269
}
280270

271+
std::string
272+
Builder::
273+
layoutDir() const
274+
{
275+
return templatesDir("layouts");
276+
}
277+
278+
std::string
279+
Builder::
280+
templatesDir() const
281+
{
282+
Config const& config = domCorpus->config;
283+
return files::appendPath(
284+
config->addons,
285+
"generator",
286+
domCorpus.fileExtension);
287+
}
288+
289+
std::string
290+
Builder::
291+
templatesDir(std::string_view subdir) const
292+
{
293+
Config const& config = domCorpus->config;
294+
return files::appendPath(
295+
config->addons,
296+
"generator",
297+
domCorpus.fileExtension,
298+
subdir);
299+
}
300+
281301

282302
// Define Builder::operator() for each Info type
283303
#define DEFINE(T) template Expected<std::string> \

src/lib/Gen/hbs/Builder.hpp

+35-6
Original file line numberDiff line numberDiff line change
@@ -44,24 +44,53 @@ class Builder
4444
Builder(HandlebarsCorpus const& corpus);
4545

4646
/** Render the contents for a symbol.
47+
48+
If the output is single page or embedded,
49+
this function renders the index template
50+
with the symbol.
51+
52+
If the output is multi-page and not embedded,
53+
this function renders the wrapper template
54+
with the index template as the contents.
4755
*/
4856
template<class T>
4957
Expected<std::string>
5058
operator()(T const&);
5159

52-
/** Render the contents for an overload set.
53-
*/
60+
/// @copydoc operator()(T const&)
5461
Expected<std::string>
5562
operator()(OverloadSet const&);
5663

57-
/** Wrap the contents of a page in the page template.
64+
/** Render the contents in the wrapper layout.
65+
66+
This function will render the contents
67+
of the wrapper template.
68+
69+
When the {{contents}} are rendered in the
70+
wrapper template, the specified function
71+
will be executed to render the contents
72+
of the page.
73+
5874
*/
5975
Expected<void>
60-
wrapPage(
61-
std::ostream& out,
62-
std::istream& in);
76+
renderWrapped(std::ostream& os, std::function<Error()> contentsCb);
6377

6478
private:
79+
/** The directory with the all templates.
80+
*/
81+
std::string
82+
templatesDir() const;
83+
84+
/** A subdirectory of the templates dir
85+
*/
86+
std::string
87+
templatesDir(std::string_view subdir) const;
88+
89+
/** The directory with the layout templates.
90+
*/
91+
std::string
92+
layoutDir() const;
93+
6594
/** Create a handlebars context with the symbol and helper information.
6695
6796
The helper information includes all information from the

src/lib/Gen/hbs/HandlebarsGenerator.cpp

+27-16
Original file line numberDiff line numberDiff line change
@@ -99,26 +99,37 @@ buildOne(
9999
auto ex = createExecutors(domCorpus);
100100
MRDOCS_CHECK_OR(ex, ex.error());
101101

102-
// Visit the corpus
103-
std::stringstream ss;
104-
std::ostream& oss = corpus.config->embedded ? os : ss;
105-
SinglePageVisitor visitor(*ex, corpus, oss);
106-
visitor(corpus.globalNamespace());
102+
// Embedded mode
103+
if (corpus.config->embedded)
104+
{
105+
// Visit the corpus
106+
SinglePageVisitor visitor(*ex, corpus, os);
107+
visitor(corpus.globalNamespace());
107108

108-
// Wait for all executors to finish and check errors
109-
auto errors = ex->wait();
110-
MRDOCS_CHECK_OR(errors.empty(), errors);
109+
// Wait for all executors to finish and check errors
110+
auto errors = ex->wait();
111+
MRDOCS_CHECK_OR(errors.empty(), errors);
111112

112-
// Wrap page
113-
if (!corpus.config->embedded)
114-
{
115-
ex->async([&os, &ss](Builder& builder) {
116-
builder.wrapPage(os, ss);
117-
});
118-
errors = ex->wait();
119-
MRDOCS_CHECK_OR(errors.empty(), {errors});
113+
return Error::success();
120114
}
121115

116+
// Wrapped mode
117+
Builder inlineBuilder(domCorpus);
118+
auto exp = inlineBuilder.renderWrapped(os, [&]() -> Error {
119+
// This helper will write contents directly to ostream
120+
SinglePageVisitor visitor(*ex, corpus, os);
121+
visitor(corpus.globalNamespace());
122+
123+
// Wait for all executors to finish and check errors
124+
auto errors = ex->wait();
125+
MRDOCS_CHECK_OR(errors.empty(), errors);
126+
127+
return Error::success();
128+
});
129+
130+
// Check for errors in the wrapping process
131+
MRDOCS_CHECK_OR(exp, exp.error());
132+
122133
return Error::success();
123134
}
124135

0 commit comments

Comments
 (0)