fix: fixed CSM-013
This commit is contained in:
19
CODESMELL.md
19
CODESMELL.md
@@ -224,11 +224,20 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### CSM-013 — Bang Functions in Rendering Pipelines
|
### ~~CSM-013 — Bang Functions in Rendering Pipelines~~ ✅ FIXED
|
||||||
- **Files:** `lib/bds/rendering/post_rendering.ex:151`, `lib/bds/rendering/filters.ex:125,127`, `lib/bds/rendering/template_selection.ex:92,102`
|
- **Fixed:** 2026-05-09
|
||||||
- **What:** `Jason.encode!`, `Liquex.parse!`, `Liquex.render!` crash on bad data instead of returning errors.
|
- **What was done:**
|
||||||
- **Fix:** Use non-bang variants, wrap in `case`, and propagate `{:error, reason}` to the caller.
|
- **`lib/bds/rendering/filters.ex`** — `render_macro_template`:
|
||||||
- **Test:** Feed a template with a syntax error; assert the renderer returns `{:error, _}` rather than raising.
|
- Replaced `Liquex.parse!` with `Liquex.parse` (non-bang) and `case` match on `{:ok, ast}` / `{:error, reason, line}`.
|
||||||
|
- Wrapped `Liquex.render!` in `try/rescue` catching `Liquex.Error` specifically (no non-bang `render` exists in Liquex).
|
||||||
|
- Removed broad `rescue _error -> ""` — errors now log via `Logger.warning` with template path and reason before returning `""`.
|
||||||
|
- **`lib/bds/rendering/template_selection.ex`** — `render_template`:
|
||||||
|
- `Liquex.parse` was already non-bang; added `else` clause to normalize the 3-tuple `{:error, reason, line}` into `{:error, "reason at line N"}`.
|
||||||
|
- Wrapped `Liquex.render!` in `try/rescue` catching `Liquex.Error` specifically, returning `{:error, message}`.
|
||||||
|
- Removed broad `rescue error -> {:error, error}`.
|
||||||
|
- **`lib/bds/rendering/post_rendering.ex`** — `post_data_json_value`:
|
||||||
|
- Replaced `Jason.encode!` with `Jason.encode` and `case` match — returns `"{}"` on encode failure instead of crashing.
|
||||||
|
- Added 5 tests in `test/bds/csm013_bang_rendering_test.exs`: template syntax error returns `{:error, _}` from `render_template`, broken template in `render_post_page` returns `{:error, _}`, `{% break %}` render error returns `{:error, _}`, normal post context produces valid JSON, non-encodable data returns `"{}"` fallback.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -122,13 +122,27 @@ defmodule BDS.Rendering.Filters do
|
|||||||
|
|
||||||
_id ->
|
_id ->
|
||||||
template_source = Liquex.FileSystem.read_template_file(context.file_system, template_path)
|
template_source = Liquex.FileSystem.read_template_file(context.file_system, template_path)
|
||||||
template_ast = Liquex.parse!(template_source)
|
|
||||||
isolated_context = Liquex.Context.new_isolated_subscope(context, assigns)
|
case Liquex.parse(template_source) do
|
||||||
{result, _context} = Liquex.render!(template_ast, isolated_context)
|
{:ok, template_ast} ->
|
||||||
IO.iodata_to_binary(result)
|
isolated_context = Liquex.Context.new_isolated_subscope(context, assigns)
|
||||||
|
|
||||||
|
try do
|
||||||
|
{result, _context} = Liquex.render!(template_ast, isolated_context)
|
||||||
|
IO.iodata_to_binary(result)
|
||||||
|
rescue
|
||||||
|
e in Liquex.Error ->
|
||||||
|
require Logger
|
||||||
|
Logger.warning("Macro template render failed (#{template_path}): #{e.message}")
|
||||||
|
""
|
||||||
|
end
|
||||||
|
|
||||||
|
{:error, reason, line} ->
|
||||||
|
require Logger
|
||||||
|
Logger.warning("Macro template parse failed (#{template_path}): #{reason} at line #{line}")
|
||||||
|
""
|
||||||
|
end
|
||||||
end
|
end
|
||||||
rescue
|
|
||||||
_error -> ""
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp render_markdown_html(markdown) do
|
defp render_markdown_html(markdown) do
|
||||||
|
|||||||
@@ -181,19 +181,22 @@ defmodule BDS.Rendering.PostRendering do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def post_data_json_value(post_context) do
|
def post_data_json_value(post_context) do
|
||||||
Jason.encode!(%{
|
case Jason.encode(%{
|
||||||
id: Map.get(post_context, :id),
|
id: Map.get(post_context, :id),
|
||||||
title: Map.get(post_context, :title),
|
title: Map.get(post_context, :title),
|
||||||
slug: Map.get(post_context, :slug),
|
slug: Map.get(post_context, :slug),
|
||||||
excerpt: Map.get(post_context, :excerpt),
|
excerpt: Map.get(post_context, :excerpt),
|
||||||
author: Map.get(post_context, :author),
|
author: Map.get(post_context, :author),
|
||||||
language: Map.get(post_context, :language),
|
language: Map.get(post_context, :language),
|
||||||
published_at: Map.get(post_context, :published_at),
|
published_at: Map.get(post_context, :published_at),
|
||||||
created_at: Map.get(post_context, :created_at),
|
created_at: Map.get(post_context, :created_at),
|
||||||
updated_at: Map.get(post_context, :updated_at),
|
updated_at: Map.get(post_context, :updated_at),
|
||||||
tags: Map.get(post_context, :tags, []),
|
tags: Map.get(post_context, :tags, []),
|
||||||
categories: Map.get(post_context, :categories, [])
|
categories: Map.get(post_context, :categories, [])
|
||||||
})
|
}) do
|
||||||
|
{:ok, json} -> json
|
||||||
|
{:error, _reason} -> "{}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp build_post_context(assigns, post_record, incoming_links, outgoing_links) do
|
defp build_post_context(assigns, post_record, incoming_links, outgoing_links) do
|
||||||
|
|||||||
@@ -99,11 +99,15 @@ defmodule BDS.Rendering.TemplateSelection do
|
|||||||
file_system: FileSystem.new(StarterTemplates.template_roots(project))
|
file_system: FileSystem.new(StarterTemplates.template_roots(project))
|
||||||
)
|
)
|
||||||
|
|
||||||
{result, _context} = Liquex.render!(template_ast, context)
|
try do
|
||||||
{:ok, IO.iodata_to_binary(result)}
|
{result, _context} = Liquex.render!(template_ast, context)
|
||||||
|
{:ok, IO.iodata_to_binary(result)}
|
||||||
|
rescue
|
||||||
|
e in Liquex.Error -> {:error, e.message}
|
||||||
|
end
|
||||||
|
else
|
||||||
|
{:error, reason, line} -> {:error, "#{reason} at line #{line}"}
|
||||||
end
|
end
|
||||||
rescue
|
|
||||||
error -> {:error, error}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp load_bundled_template_source(project, kind, slug) do
|
defp load_bundled_template_source(project, kind, slug) do
|
||||||
|
|||||||
Reference in New Issue
Block a user