Crinja::Value
Inherits Comparable / Iterable / Enumerable / Struct / Value / Object
=== 2. Safer attribute resolution on indexable values ==================
Upstream Resolver.resolve_attribute calls name.to_i (which raises
ArgumentError("Invalid Int32: \"<name>\"") on non-numeric names) for
any indexable value, including Strings. The most common way to hit
this is iterating a hash with a single loop variable —
{% for k in site.taxonomies.tags %}{{ k.name }}{% endfor %}
yields hash keys (Strings), and k.name then runs "<key>".to_i.
The user sees a Crystal-internal stack trace with no template
file:line:col, which makes the typo (for k, v in …) impossible to
locate.
Two changes here:
- Use
to_i?so non-numeric attribute names cleanly fall through instead of crashing the resolver. - When attribute access is non-numeric and the underlying value is
a String, raise
UndefinedError. Crinja'sMemberExpressionevaluator catches and re-raises it labeled with the full expression (k.name), which ourError [HWARO_E_TEMPLATE]formatter prints with template file:line:col. DefaultUndefinedrenders as empty, which is the correct behavior for hashes / objects ({% if page.optional %}-style guards rely on it), but on a primitive String the access is almost always a typo, so a loud error is more helpful than silent empty output.
See: https://github.com/hahwul/hwaro/issues/482
=== 3. Empty-collection falsiness (Jinja2 alignment) ==================
Upstream Value#truthy? only treats false, 0, nil, and
Undefined as falsy. Python Jinja2 also treats empty collections —
[], {}, "" — as falsy, which is what {% if items %} and
{% if page.translations %} rely on across hwaro's docs and
scaffolds. Without this patch, the canonical lang-switcher idiom
{% if page.translations %}<nav>…</nav>{% endif %}
always rendered an empty <nav> for pages with no translations,
because Crinja saw [] as truthy.
See: https://github.com/hahwul/hwaro/issues/486