Skip to content

Commit 96578fe

Browse files
committed
build(jerryscript): improve tests
1 parent 723379e commit 96578fe

File tree

14 files changed

+390
-173
lines changed

14 files changed

+390
-173
lines changed

CMakeLists.txt

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -343,14 +343,7 @@ target_include_directories(mrdocs-core
343343
"$<BUILD_INTERFACE:${jerryscript_ROOT}/include>"
344344
"$<BUILD_INTERFACE:/usr/local/include>"
345345
)
346-
# JerryScript: Link jerry-core and jerry-port.
347-
# When JERRY_EXTERNAL_CONTEXT=ON, jerry-port is built WITHOUT jerry-port-context.c,
348-
# so mrdocs-core provides the only implementations of jerry_port_context_* functions.
349-
# This avoids ODR violations and makes the design explicit.
350-
target_link_libraries(mrdocs-core PRIVATE jerryscript::jerry-core)
351-
if(TARGET jerryscript::jerry-port)
352-
target_link_libraries(mrdocs-core PRIVATE jerryscript::jerry-port)
353-
endif()
346+
target_link_libraries(mrdocs-core PRIVATE jerryscript::jerry-core jerryscript::jerry-port)
354347
target_link_libraries(mrdocs-core PRIVATE Lua::lua)
355348

356349
# Clang

include/mrdocs/Support/JavaScript.hpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,12 @@ class Handlebars;
8383
- `jerry_port_context_free`: Frees context memory
8484
- `jerry_port_context_get`: Returns current thread's active context
8585
86-
The default jerry-port uses a static global pointer, limiting all threads
87-
to a single shared context. Our TLS-based implementations allow each
88-
thread to have its own active context, enabling parallel JavaScript
89-
execution. Our symbols are linked before jerry-port so they take
90-
precedence during symbol resolution.
86+
The default jerry-port context functions use a static global pointer,
87+
limiting all threads to a single shared context. When building with
88+
JERRY_EXTERNAL_CONTEXT=ON, these functions are excluded from jerry-port
89+
(see third-party/patches/jerryscript/CMakeLists.txt), and mrdocs provides
90+
TLS-based implementations that allow each thread to have its own active
91+
context, enabling parallel JavaScript execution.
9192
*/
9293
namespace js {
9394

src/lib/Gen/hbs/AddonPaths.hpp

Lines changed: 140 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,35 @@
33
// See https://llvm.org/LICENSE.txt for license information.
44
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
55
//
6-
// Internal helper for Handlebars addon search paths.
6+
// Copyright (c) 2025 Alan de Freitas ([email protected])
7+
//
8+
// Official repository: https://github.com/cppalliance/mrdocs
79
//
810

911
#ifndef MRDOCS_LIB_GEN_HBS_ADDONPATHS_HPP
1012
#define MRDOCS_LIB_GEN_HBS_ADDONPATHS_HPP
1113

1214
#include <lib/ConfigImpl.hpp>
1315
#include <mrdocs/Support/Path.hpp>
16+
#include <optional>
17+
#include <string>
18+
#include <string_view>
1419
#include <vector>
1520

1621
namespace mrdocs::hbs::addon_paths {
1722

23+
/** Returns the list of addon root directories from the configuration.
24+
25+
This function collects all valid addon root paths by checking
26+
the primary addons directory and any supplemental addon directories
27+
specified in the configuration.
28+
29+
@param config The configuration containing addon path settings.
30+
@return A vector of existing addon root directory paths. The primary
31+
addons directory (if it exists) appears first, followed by
32+
any existing supplemental addon directories in their
33+
configured order.
34+
*/
1835
inline std::vector<std::string>
1936
addonRoots(Config const& config)
2037
{
@@ -32,6 +49,128 @@ addonRoots(Config const& config)
3249
return roots;
3350
}
3451

52+
/** Returns directories containing Handlebars partial templates.
53+
54+
For each addon root, this function looks for partial templates in:
55+
1. `generator/common/partials/` - shared partials for all formats
56+
2. `generator/<ext>/partials/` - format-specific partials
57+
58+
The order preserves root precedence: for each root, common partials
59+
are loaded first, then format-specific ones. Later roots (supplemental
60+
addons) can override partials from earlier roots.
61+
62+
@param roots The addon root directories to search.
63+
@param ext The output format extension (e.g., "html", "adoc").
64+
@return A vector of existing partial directories in load order.
65+
*/
66+
inline std::vector<std::string>
67+
partialDirs(std::vector<std::string> const& roots, std::string_view ext)
68+
{
69+
std::vector<std::string> dirs;
70+
dirs.reserve(roots.size() * 2);
71+
72+
for (auto const& root : roots)
73+
{
74+
auto const commonDir = files::appendPath(root, "generator", "common", "partials");
75+
if (files::exists(commonDir))
76+
dirs.push_back(commonDir);
77+
78+
auto const formatDir = files::appendPath(root, "generator", ext, "partials");
79+
if (files::exists(formatDir))
80+
dirs.push_back(formatDir);
81+
}
82+
83+
return dirs;
84+
}
85+
86+
/** Returns directories containing JavaScript helper scripts.
87+
88+
For each addon root, this function looks for helper scripts in:
89+
1. `generator/common/helpers/` - shared helpers for all formats
90+
2. `generator/<ext>/helpers/` - format-specific helpers
91+
92+
The order preserves root precedence: for each root, common helpers
93+
are loaded first, then format-specific ones. Later roots (supplemental
94+
addons) can override helpers from earlier roots.
95+
96+
@param roots The addon root directories to search.
97+
@param ext The output format extension (e.g., "html", "adoc").
98+
@return A vector of existing helper directories in load order.
99+
*/
100+
inline std::vector<std::string>
101+
helperDirs(std::vector<std::string> const& roots, std::string_view ext)
102+
{
103+
std::vector<std::string> dirs;
104+
dirs.reserve(roots.size() * 2);
105+
106+
for (auto const& root : roots)
107+
{
108+
auto const commonDir = files::appendPath(root, "generator", "common", "helpers");
109+
if (files::exists(commonDir))
110+
dirs.push_back(commonDir);
111+
112+
auto const formatDir = files::appendPath(root, "generator", ext, "helpers");
113+
if (files::exists(formatDir))
114+
dirs.push_back(formatDir);
115+
}
116+
return dirs;
117+
}
118+
119+
/** Returns directories containing layout templates.
120+
121+
For each addon root, this function looks for layout templates in:
122+
`generator/<ext>/layouts/`
123+
124+
Layout templates define the overall page structure (e.g., wrapper.html.hbs,
125+
index.html.hbs). Later roots can override layouts from earlier roots.
126+
127+
@param roots The addon root directories to search.
128+
@param ext The output format extension (e.g., "html", "adoc").
129+
@return A vector of existing layout directories in load order.
130+
*/
131+
inline std::vector<std::string>
132+
layoutDirs(std::vector<std::string> const& roots, std::string_view ext)
133+
{
134+
std::vector<std::string> dirs;
135+
dirs.reserve(roots.size());
136+
for (auto const& root : roots)
137+
{
138+
auto const dir = files::appendPath(root, "generator", ext, "layouts");
139+
if (files::exists(dir))
140+
dirs.push_back(dir);
141+
}
142+
return dirs;
143+
}
144+
145+
/** Searches addon directories for a specific file.
146+
147+
Searches through addon roots in reverse order (supplemental addons
148+
first) to find the specified file. This allows supplemental addons
149+
to override files from the primary addon directory.
150+
151+
@param config The configuration containing addon paths.
152+
@param generator The generator subdirectory (e.g., "html", "common").
153+
@param subdir The subdirectory within the generator (e.g., "layouts").
154+
@param filename The filename to search for.
155+
@return The full path to the file if found, or std::nullopt.
156+
*/
157+
inline std::optional<std::string>
158+
findFile(
159+
Config const& config,
160+
std::string_view generator,
161+
std::string_view subdir,
162+
std::string_view filename)
163+
{
164+
auto roots = addonRoots(config);
165+
for (auto it = roots.rbegin(); it != roots.rend(); ++it)
166+
{
167+
std::string candidate = files::appendPath(*it, "generator", generator, subdir, filename);
168+
if (files::exists(candidate))
169+
return candidate;
170+
}
171+
return std::nullopt;
172+
}
173+
35174
} // namespace mrdocs::hbs::addon_paths
36175

37176
#endif // MRDOCS_LIB_GEN_HBS_ADDONPATHS_HPP

src/lib/Gen/hbs/Builder.cpp

Lines changed: 74 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -28,63 +28,17 @@ namespace hbs {
2828

2929
namespace {
3030

31-
std::vector<std::string>
32-
makePartialDirs(std::vector<std::string> const& roots, std::string_view ext)
33-
{
34-
std::vector<std::string> dirs;
35-
dirs.reserve(roots.size() * 2);
36-
37-
// Preserve root precedence: for each root load common first, then format.
38-
// Later roots (supplemental addons) still override earlier ones.
39-
for (auto const& root : roots)
40-
{
41-
auto const commonDir = files::appendPath(root, "generator", "common", "partials");
42-
if (files::exists(commonDir))
43-
dirs.push_back(commonDir);
44-
45-
auto const formatDir = files::appendPath(root, "generator", ext, "partials");
46-
if (files::exists(formatDir))
47-
dirs.push_back(formatDir);
48-
}
49-
50-
return dirs;
51-
}
31+
/** Loads Handlebars partial templates from a directory.
5232
53-
std::vector<std::string>
54-
makeHelperDirs(std::vector<std::string> const& roots, std::string_view ext)
55-
{
56-
std::vector<std::string> dirs;
57-
dirs.reserve(roots.size() * 2);
58-
59-
// Preserve root precedence: for each root load common first, then format.
60-
// Later roots (supplemental addons) still override earlier ones.
61-
for (auto const& root : roots)
62-
{
63-
auto const commonDir = files::appendPath(root, "generator", "common", "helpers");
64-
if (files::exists(commonDir))
65-
dirs.push_back(commonDir);
66-
67-
auto const formatDir = files::appendPath(root, "generator", ext, "helpers");
68-
if (files::exists(formatDir))
69-
dirs.push_back(formatDir);
70-
}
71-
return dirs;
72-
}
73-
74-
std::vector<std::string>
75-
makeLayoutDirs(std::vector<std::string> const& roots, std::string_view ext)
76-
{
77-
std::vector<std::string> dirs;
78-
dirs.reserve(roots.size());
79-
for (auto const& root : roots)
80-
{
81-
auto const dir = files::appendPath(root, "generator", ext, "layouts");
82-
if (files::exists(dir))
83-
dirs.push_back(dir);
84-
}
85-
return dirs;
86-
}
33+
Recursively scans the specified directory for `.hbs` files and
34+
registers each as a Handlebars partial. The partial name is derived
35+
from the file's relative path (without extension), allowing
36+
subdirectory organization (e.g., `components/button.hbs` becomes
37+
partial `components/button`).
8738
39+
@param hbs The Handlebars instance to register partials with.
40+
@param partialsPath The directory path to scan for partial files.
41+
*/
8842
void
8943
loadPartials(
9044
Handlebars& hbs,
@@ -126,19 +80,22 @@ loadPartials(
12680
}
12781
}
12882

129-
/* Make a URL relative to another URL.
83+
/** Makes a URL relative to another URL.
13084
131-
This function is a version of the Antora `relativize` helper,
132-
used to create relative URLs between two paths in Antora projects.
85+
This function implements Antora-style URL relativization, creating
86+
relative URLs between two paths. It takes a target path (`to`) and
87+
a source path (`from`), returning a relative path from `from` to `to`.
13388
134-
The function takes two paths, `to` and `from`, and returns a
135-
relative path from `from` to `to`.
89+
When called with a single argument, the current symbol's URL (from
90+
`data.root.symbol.url`) is used as the source path.
13691
137-
If `from` is not provided, then the URL of the symbol being
138-
rendered is used as the `from` path.
92+
@param to0 The target URL to make relative.
93+
@param from0 The source URL to relativize from (optional).
94+
@param options Handlebars options containing context data.
95+
@return The relative URL path, or the original URL if not absolute.
13996
140-
@see https://gitlab.com/antora/antora-ui-default/-/blob/master/src/helpers/relativize.js
141-
*/
97+
@see https://gitlab.com/antora/antora-ui-default/-/blob/master/src/helpers/relativize.js
98+
*/
14299
dom::Value
143100
relativize_fn(dom::Value to0, dom::Value from0, dom::Value options)
144101
{
@@ -214,15 +171,35 @@ relativize_fn(dom::Value to0, dom::Value from0, dom::Value options)
214171
return relativePath;
215172
}
216173

217-
// Registration helpers
174+
/** Registers partial templates from multiple directories.
218175
176+
Iterates through each directory and loads all `.hbs` files as
177+
Handlebars partials. Later directories in the list can override
178+
partials from earlier ones, enabling supplemental addons to
179+
customize templates.
180+
181+
@param hbs The Handlebars instance to register partials with.
182+
@param dirs The list of directories to load partials from.
183+
*/
219184
void
220185
registerPartials(Handlebars& hbs, std::vector<std::string> const& dirs)
221186
{
222187
for (auto const& dir : dirs)
223188
loadPartials(hbs, dir);
224189
}
225190

191+
/** Registers default Handlebars Generator helpers.
192+
193+
Registers the default set of helpers available in all templates:
194+
- `primary_location`: Returns the primary source location for a symbol
195+
- `relativize`: Creates relative URLs between paths
196+
- Constructor, string, Antora, logical, math, container, and type helpers
197+
198+
These helpers are registered before user-defined helpers, allowing
199+
users to override built-in behavior if needed.
200+
201+
@param hbs The Handlebars instance to register helpers with.
202+
*/
226203
void
227204
registerDefaultHelpers(Handlebars& hbs)
228205
{
@@ -263,6 +240,24 @@ registerDefaultHelpers(Handlebars& hbs)
263240
hbs.registerHelper("relativize", dom::makeInvocable(relativize_fn));
264241
}
265242

243+
/** Registers user-defined JavaScript helpers from addon directories.
244+
245+
Scans the specified directories for JavaScript files and registers
246+
them as Handlebars helpers. Files are categorized into two types:
247+
248+
- **Utility files** (prefixed with `_`): Executed as scripts to define
249+
shared globals. Loaded alphabetically before helper files.
250+
- **Helper files**: Registered as Handlebars helpers with the filename
251+
(minus `.js`) as the helper name.
252+
253+
This separation allows helpers to share common code through utilities
254+
without duplicating implementations.
255+
256+
@param hbs The Handlebars instance to register helpers with.
257+
@param ctx The JavaScript context for script execution.
258+
@param helperDirs The directories to scan for helper files.
259+
@return Success, or an error if loading/registration fails.
260+
*/
266261
Expected<void>
267262
registerUserHelpers(
268263
Handlebars& hbs,
@@ -340,6 +335,17 @@ registerUserHelpers(
340335
return {};
341336
}
342337

338+
/** Loads a layout template from addon directories.
339+
340+
Searches through the layout directories for the specified template
341+
file. If found in multiple directories, later directories override
342+
earlier ones (enabling supplemental addons to customize layouts).
343+
344+
@param templates The map to store loaded templates (filename -> content).
345+
@param layoutDirs The directories to search for the template.
346+
@param filename The template filename to load (e.g., "index.html.hbs").
347+
@return Success, or throws an error if the template is not found.
348+
*/
343349
Expected<void, Error>
344350
loadLayoutTemplate(
345351
std::map<std::string, std::string, std::less<>>& templates,
@@ -374,9 +380,9 @@ Builder(
374380

375381
auto const& config = domCorpus->config;
376382
auto const roots = addon_paths::addonRoots(config);
377-
auto const partialDirs = makePartialDirs(roots, domCorpus.fileExtension);
378-
auto const helperDirs = makeHelperDirs(roots, domCorpus.fileExtension);
379-
auto const layoutDirs = makeLayoutDirs(roots, domCorpus.fileExtension);
383+
auto const partialDirs = addon_paths::partialDirs(roots, domCorpus.fileExtension);
384+
auto const helperDirs = addon_paths::helperDirs(roots, domCorpus.fileExtension);
385+
auto const layoutDirs = addon_paths::layoutDirs(roots, domCorpus.fileExtension);
380386

381387
// Load partials (later dirs overwrite earlier ones because we walk in order)
382388
registerPartials(hbs_, partialDirs);

0 commit comments

Comments
 (0)